1 """engine.SCons.Tool.msvc
3 Tool-specific initialization for Microsoft Visual C/C++.
5 There normally shouldn't be any need to import this module directly.
6 It will usually be imported through the generic SCons.Tool.Tool()
14 # Permission is hereby granted, free of charge, to any person obtaining
15 # a copy of this software and associated documentation files (the
16 # "Software"), to deal in the Software without restriction, including
17 # without limitation the rights to use, copy, modify, merge, publish,
18 # distribute, sublicense, and/or sell copies of the Software, and to
19 # permit persons to whom the Software is furnished to do so, subject to
20 # the following conditions:
22 # The above copyright notice and this permission notice shall be included
23 # in all copies or substantial portions of the Software.
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
43 import SCons.Platform.win32
45 import SCons.Tool.msvs
49 CSuffixes = ['.c', '.C']
50 CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
52 def _parse_msvc7_overrides(version,platform):
53 """ Parse any overridden defaults for MSVS directory locations
56 # First, we get the shell folder for this user:
57 if not SCons.Util.can_read_reg:
58 raise SCons.Errors.InternalError, "No Windows registry module was found"
62 (comps, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
63 r'Software\Microsoft\Windows\CurrentVersion' +\
64 r'\Explorer\Shell Folders\Local AppData')
65 except SCons.Util.RegError:
66 raise SCons.Errors.InternalError, \
67 "The Local AppData directory was not found in the registry."
69 comps = comps + '\\Microsoft\\VisualStudio\\' + version + '\\VCComponents.dat'
72 if os.path.exists(comps):
73 # now we parse the directories from this file, if it exists.
74 # We only look for entries after:
75 # [VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories],
76 # since this file could contain a number of things...
84 f = codecs.open(comps, 'r', 'utf16')
85 encoder = codecs.getencoder('ascii')
86 lines = map(lambda l, e=encoder: e(l)[0], f.readlines())
87 except (LookupError, UnicodeError):
88 lines = codecs.open(comps, 'r', 'utf8').readlines()
90 lines = open(comps, 'r').readlines()
91 if 'x86' == platform: platform = 'Win32'
96 if line.find(r'[VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories]'%platform) >= 0:
98 elif line == '' or line[:1] == '[':
101 kv = line.split('=', 1)
104 key = key.replace(' Dirs','')
105 dirs[key.upper()] = val
108 # since the file didn't exist, we have only the defaults in
109 # the registry to work with.
111 if 'x86' == platform: platform = 'Win32'
114 K = 'SOFTWARE\\Microsoft\\VisualStudio\\' + version
115 K = K + r'\VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories'%platform
116 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,K)
120 (key,val,t) = SCons.Util.RegEnumValue(k,i)
121 key = key.replace(' Dirs','')
122 dirs[key.upper()] = val
124 except SCons.Util.RegError:
126 except SCons.Util.RegError:
127 # if we got here, then we didn't find the registry entries:
128 raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
131 def _parse_msvc8_overrides(version,platform,suite):
132 """ Parse any overridden defaults for MSVC directory locations
135 # In VS8 the user can change the location of the settings file that
136 # contains the include, lib and binary paths. Try to get the location
138 if not SCons.Util.can_read_reg:
139 raise SCons.Errors.InternalError, "No Windows registry module was found"
142 if suite == 'EXPRESS':
145 # ToDo: add registry key strings for the other versions of visual
149 (settings_path, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
150 r'Software\Microsoft' + s + version +\
151 r'\Profile\AutoSaveFile')
152 settings_path = settings_path.upper()
153 except SCons.Util.RegError:
154 raise SCons.Errors.InternalError, \
155 "The VS8 settings file location was not found in the registry."
157 # Look for potential environment variables in the settings path
158 if settings_path.find('%VSSPV_VISUALSTUDIO_DIR%') >= 0:
159 # First replace a special variable named %vsspv_visualstudio_dir%
160 # that is not found in the OSs environment variables...
162 (value, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
163 r'Software\Microsoft' + s + version +\
164 r'\VisualStudioLocation')
165 settings_path = settings_path.replace('%VSSPV_VISUALSTUDIO_DIR%', value)
166 except SCons.Util.RegError:
167 raise SCons.Errors.InternalError, "The VS8 settings file location was not found in the registry."
169 if settings_path.find('%') >= 0:
170 # Collect global environment variables
173 # Read all the global environment variables of the current user
174 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_CURRENT_USER, r'Environment')
178 (key,val,t) = SCons.Util.RegEnumValue(k,i)
179 env_vars[key.upper()] = val.upper()
181 except SCons.Util.RegError:
184 # And some more variables that are not found in the registry
185 env_vars['USERPROFILE'] = os.getenv('USERPROFILE')
186 env_vars['SystemDrive'] = os.getenv('SystemDrive')
191 for env_var in env_vars:
192 if settings_path.find(r'%' + env_var + r'%') >= 0:
193 settings_path = settings_path.replace(r'%' + env_var + r'%', env_vars[env_var])
198 if os.path.exists(settings_path):
199 # now we parse the directories from this file, if it exists.
200 import xml.dom.minidom
201 doc = xml.dom.minidom.parse(settings_path)
202 user_settings = doc.getElementsByTagName('UserSettings')[0]
203 tool_options = user_settings.getElementsByTagName('ToolsOptions')[0]
204 tool_options_categories = tool_options.getElementsByTagName('ToolsOptionsCategory')
205 for category in tool_options_categories:
206 category_name = category.attributes.get('name')
207 if category_name is not None and category_name.value == 'Projects':
208 subcategories = category.getElementsByTagName('ToolsOptionsSubCategory')
209 for subcategory in subcategories:
210 subcategory_name = subcategory.attributes.get('name')
211 if subcategory_name is not None and subcategory_name.value == 'VCDirectories':
212 properties = subcategory.getElementsByTagName('PropertyValue')
213 for property in properties:
214 property_name = property.attributes.get('name')
215 if property_name is None:
217 elif property_name.value == 'IncludeDirectories':
218 include_dirs = property.childNodes[0].data
219 # ToDo: Support for other destinations than Win32
220 include_dirs = include_dirs.replace('Win32|', '')
221 dirs['INCLUDE'] = include_dirs
222 elif property_name.value == 'LibraryDirectories':
223 lib_dirs = property.childNodes[0].data.replace('Win32|', '')
224 # ToDo: Support for other destinations than Win32
225 lib_dirs = lib_dirs.replace('Win32|', '')
226 dirs['LIBRARY'] = lib_dirs
227 elif property_name.value == 'ExecutableDirectories':
228 path_dirs = property.childNodes[0].data.replace('Win32|', '')
229 # ToDo: Support for other destinations than Win32
230 path_dirs = path_dirs.replace('Win32|', '')
231 dirs['PATH'] = path_dirs
233 # There are no default directories in the registry for VS8 Express :(
234 raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
237 def _get_msvc7_path(path, version, platform):
239 Get Visual Studio directories from version 7 (MSVS .NET)
240 (it has a different registry structure than versions before it)
242 # first, look for a customization of the default values in the
243 # registry: These are sometimes stored in the Local Settings area
244 # for Visual Studio, in a file, so we have to parse it.
245 dirs = _parse_msvc7_overrides(version,platform)
247 if dirs.has_key(path):
250 raise SCons.Errors.InternalError, \
251 "Unable to retrieve the %s path from MS VC++."%path
253 # collect some useful information for later expansions...
254 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
256 # expand the directory path variables that we support. If there
257 # is a variable we don't support, then replace that entry with
258 # "---Unknown Location VSInstallDir---" or something similar, to clue
259 # people in that we didn't find something, and so env expansion doesn't
260 # do weird things with the $(xxx)'s
261 s = re.compile('\$\(([a-zA-Z0-9_]+?)\)')
263 def repl(match, paths=paths):
264 key = string.upper(match.group(1))
265 if paths.has_key(key):
268 # Now look in the global environment variables
269 envresult = os.getenv(key)
270 if not envresult is None:
271 return envresult + '\\'
273 return '---Unknown Location %s---' % match.group()
276 for entry in p.split(os.pathsep):
277 entry = s.sub(repl,entry).rstrip('\n\r')
280 return string.join(rv,os.pathsep)
282 def _get_msvc8_path(path, version, platform, suite):
284 Get Visual Studio directories from version 8 (MSVS 2005)
285 (it has a different registry structure than versions before it)
287 # first, look for a customization of the default values in the
288 # registry: These are sometimes stored in the Local Settings area
289 # for Visual Studio, in a file, so we have to parse it.
290 dirs = _parse_msvc8_overrides(version, platform, suite)
292 if dirs.has_key(path):
295 raise SCons.Errors.InternalError, \
296 "Unable to retrieve the %s path from MS VC++."%path
298 # collect some useful information for later expansions...
299 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
301 # expand the directory path variables that we support. If there
302 # is a variable we don't support, then replace that entry with
303 # "---Unknown Location VSInstallDir---" or something similar, to clue
304 # people in that we didn't find something, and so env expansion doesn't
305 # do weird things with the $(xxx)'s
306 s = re.compile('\$\(([a-zA-Z0-9_]+?)\)')
308 def repl(match, paths=paths):
309 key = string.upper(match.group(1))
310 if paths.has_key(key):
313 return '---Unknown Location %s---' % match.group()
316 for entry in p.split(os.pathsep):
317 entry = s.sub(repl,entry).rstrip('\n\r')
320 return string.join(rv,os.pathsep)
322 def get_msvc_path(env, path, version):
324 Get a list of visualstudio directories (include, lib or path).
325 Return a string delimited by the os.pathsep separator (';'). An
326 exception will be raised if unable to access the registry or
327 appropriate registry keys not found.
330 if not SCons.Util.can_read_reg:
331 raise SCons.Errors.InternalError, "No Windows registry module was found"
333 # normalize the case for comparisons (since the registry is case
335 path = string.upper(path)
340 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
341 if version_num >= 8.0:
342 platform = env.get('MSVS8_PLATFORM', 'x86')
343 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
347 if version_num >= 8.0:
348 return _get_msvc8_path(path, str(version_num), platform, suite)
349 elif version_num >= 7.0:
350 return _get_msvc7_path(path, str(version_num), platform)
352 path = string.upper(path + ' Dirs')
353 K = ('Software\\Microsoft\\Devstudio\\%s\\' +
354 'Build System\\Components\\Platforms\\Win32 (x86)\\Directories') % \
356 for base in (SCons.Util.HKEY_CURRENT_USER,
357 SCons.Util.HKEY_LOCAL_MACHINE):
359 k = SCons.Util.RegOpenKeyEx(base,K)
363 (p,v,t) = SCons.Util.RegEnumValue(k,i)
364 if string.upper(p) == path:
367 except SCons.Util.RegError:
369 except SCons.Util.RegError:
372 # if we got here, then we didn't find the registry entries:
373 raise SCons.Errors.InternalError, "The %s path was not found in the registry."%path
375 def _get_msvc6_default_paths(version, use_mfc_dirs):
376 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
377 three environment variables that should be set in order to execute
378 the MSVC 6.0 tools properly, if the information wasn't available
379 from the registry."""
386 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
387 MVSdir = paths['VSINSTALLDIR']
388 except (SCons.Util.RegError, SCons.Errors.InternalError, KeyError):
389 if os.environ.has_key('MSDEVDIR'):
390 MVSdir = os.path.normpath(os.path.join(os.environ['MSDEVDIR'],'..','..'))
392 MVSdir = r'C:\Program Files\Microsoft Visual Studio'
394 if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
395 MVSVCdir = paths['VCINSTALLDIR']
397 MVSVCdir = os.path.join(MVSdir,'VC98')
399 MVSCommondir = r'%s\Common' % MVSdir
401 mfc_include_ = r'%s\ATL\include;%s\MFC\include;' % (MVSVCdir, MVSVCdir)
402 mfc_lib_ = r'%s\MFC\lib;' % MVSVCdir
406 include_path = r'%s%s\include' % (mfc_include_, MVSVCdir)
407 lib_path = r'%s%s\lib' % (mfc_lib_, MVSVCdir)
409 if os.environ.has_key('OS') and os.environ['OS'] == "Windows_NT":
414 exe_path = r'%s\tools\%s;%s\MSDev98\bin;%s\tools;%s\bin' % (MVSCommondir, osdir, MVSCommondir, MVSCommondir, MVSVCdir)
415 return (include_path, lib_path, exe_path)
417 def _get_msvc7_default_paths(env, version, use_mfc_dirs):
418 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
419 three environment variables that should be set in order to execute
420 the MSVC .NET tools properly, if the information wasn't available
421 from the registry."""
429 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
430 MVSdir = paths['VSINSTALLDIR']
431 except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError):
432 if os.environ.has_key('VSCOMNTOOLS'):
433 MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..'))
435 # last resort -- default install location
436 MVSdir = r'C:\Program Files\Microsoft Visual Studio .NET'
439 if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
440 MVSVCdir = paths['VCINSTALLDIR']
442 MVSVCdir = os.path.join(MVSdir,'Vc7')
444 MVSCommondir = r'%s\Common7' % MVSdir
446 mfc_include_ = r'%s\atlmfc\include;' % MVSVCdir
447 mfc_lib_ = r'%s\atlmfc\lib;' % MVSVCdir
451 include_path = r'%s%s\include;%s\PlatformSDK\include' % (mfc_include_, MVSVCdir, MVSVCdir)
452 lib_path = r'%s%s\lib;%s\PlatformSDK\lib' % (mfc_lib_, MVSVCdir, MVSVCdir)
453 exe_path = r'%s\IDE;%s\bin;%s\Tools;%s\Tools\bin' % (MVSCommondir,MVSVCdir, MVSCommondir, MVSCommondir )
455 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'):
456 include_path = include_path + r';%s\include'%paths['FRAMEWORKSDKDIR']
457 lib_path = lib_path + r';%s\lib'%paths['FRAMEWORKSDKDIR']
458 exe_path = exe_path + r';%s\bin'%paths['FRAMEWORKSDKDIR']
460 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'):
461 exe_path = exe_path + r';%s\%s'%(paths['FRAMEWORKDIR'],paths['FRAMEWORKVERSION'])
463 return (include_path, lib_path, exe_path)
465 def _get_msvc8_default_paths(env, version, suite, use_mfc_dirs):
466 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
467 three environment variables that should be set in order to execute
468 the MSVC 8 tools properly, if the information wasn't available
469 from the registry."""
477 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
478 MVSdir = paths['VSINSTALLDIR']
479 except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError):
480 if os.environ.has_key('VSCOMNTOOLS'):
481 MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..'))
483 # last resort -- default install location
484 MVSdir = os.getenv('ProgramFiles') + r'\Microsoft Visual Studio 8'
487 if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
488 MVSVCdir = paths['VCINSTALLDIR']
490 MVSVCdir = os.path.join(MVSdir,'VC')
492 MVSCommondir = os.path.join(MVSdir, 'Common7')
493 include_paths.append( os.path.join(MVSVCdir, 'include') )
494 lib_paths.append( os.path.join(MVSVCdir, 'lib') )
495 for base, subdir in [(MVSCommondir,'IDE'), (MVSVCdir,'bin'),
496 (MVSCommondir,'Tools'), (MVSCommondir,r'Tools\bin')]:
497 exe_paths.append( os.path.join( base, subdir) )
499 if paths.has_key('PLATFORMSDKDIR'):
500 PlatformSdkDir = paths['PLATFORMSDKDIR']
502 PlatformSdkDir = os.path.join(MVSVCdir,'PlatformSDK')
503 platform_include_path = os.path.join( PlatformSdkDir, 'Include' )
504 include_paths.append( platform_include_path )
505 lib_paths.append( os.path.join( PlatformSdkDir, 'Lib' ) )
507 if paths.has_key('PLATFORMSDKDIR'):
508 include_paths.append( os.path.join( platform_include_path, 'mfc' ) )
509 include_paths.append( os.path.join( platform_include_path, 'atl' ) )
511 atlmfc_path = os.path.join( MVSVCdir, 'atlmfc' )
512 include_paths.append( os.path.join( atlmfc_path, 'include' ) )
513 lib_paths.append( os.path.join( atlmfc_path, 'lib' ) )
515 env_include_path = SCons.Util.get_environment_var('INCLUDE')
517 include_paths.append( env_include_path )
519 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'):
520 include_paths.append( os.path.join( paths['FRAMEWORKSDKDIR'], 'include' ) )
521 lib_paths.append( os.path.join( paths['FRAMEWORKSDKDIR'], 'lib' ) )
522 exe_paths.append( paths['FRAMEWORKSDKDIR'], 'bin' )
524 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'):
525 exe_paths.append( os.path.join( paths['FRAMEWORKDIR'], paths['FRAMEWORKVERSION'] ) )
527 include_path = string.join( include_paths, os.pathsep )
528 lib_path = string.join(lib_paths, os.pathsep )
529 exe_path = string.join(exe_paths, os.pathsep )
530 return (include_path, lib_path, exe_path)
532 def get_msvc_paths(env, version=None, use_mfc_dirs=0):
533 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
534 of those three environment variables that should be set
535 in order to execute the MSVC tools properly."""
541 versions = SCons.Tool.msvs.get_visualstudio_versions()
543 version = versions[0] #use highest version by default
547 # Some of the configured directories only
548 # appear if the user changes them from the default.
549 # Therefore, we'll see if we can get the path to the MSDev
550 # base installation from the registry and deduce the default
552 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
553 if version_num >= 8.0:
554 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
555 defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs)
556 elif version_num >= 7.0:
557 defpaths = _get_msvc7_default_paths(env, version, use_mfc_dirs)
559 defpaths = _get_msvc6_default_paths(version, use_mfc_dirs)
562 include_path = get_msvc_path(env, "include", version)
563 except (SCons.Util.RegError, SCons.Errors.InternalError):
564 include_path = defpaths[0]
567 lib_path = get_msvc_path(env, "lib", version)
568 except (SCons.Util.RegError, SCons.Errors.InternalError):
569 lib_path = defpaths[1]
572 exe_path = get_msvc_path(env, "path", version)
573 except (SCons.Util.RegError, SCons.Errors.InternalError):
574 exe_path = defpaths[2]
576 return (include_path, lib_path, exe_path)
578 def get_msvc_default_paths(env, version=None, use_mfc_dirs=0):
579 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
580 three environment variables that should be set in order to execute
581 the MSVC tools properly. This will only return the default
582 locations for the tools, not the values used by MSVS in their
583 directory setup area. This can help avoid problems with different
584 developers having different settings, and should allow the tools
585 to run in most cases."""
587 if not version and not SCons.Util.can_read_reg:
592 version = SCons.Tool.msvs.get_visualstudio_versions()[0] #use highest version
593 except KeyboardInterrupt:
598 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
599 if version_num >= 8.0:
600 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
601 defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs)
602 elif version_num >= 7.0:
603 return _get_msvc7_default_paths(env, version, use_mfc_dirs)
605 return _get_msvc6_default_paths(version, use_mfc_dirs)
607 def validate_vars(env):
608 """Validate the PCH and PCHSTOP construction variables."""
609 if env.has_key('PCH') and env['PCH']:
610 if not env.has_key('PCHSTOP'):
611 raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
612 if not SCons.Util.is_String(env['PCHSTOP']):
613 raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
615 def pch_emitter(target, source, env):
616 """Adds the object file target."""
624 if SCons.Util.splitext(str(t))[1] == '.pch':
626 if SCons.Util.splitext(str(t))[1] == '.obj':
630 obj = SCons.Util.splitext(str(pch))[0]+'.obj'
632 target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
634 return (target, source)
636 def object_emitter(target, source, env, parent_emitter):
637 """Sets up the PCH dependencies for an object file."""
641 parent_emitter(target, source, env)
643 if env.has_key('PCH') and env['PCH']:
644 env.Depends(target, env['PCH'])
646 return (target, source)
648 def static_object_emitter(target, source, env):
649 return object_emitter(target, source, env,
650 SCons.Defaults.StaticObjectEmitter)
652 def shared_object_emitter(target, source, env):
653 return object_emitter(target, source, env,
654 SCons.Defaults.SharedObjectEmitter)
656 pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
657 pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
659 source_scanner=SCons.Tool.SourceFileScanner)
660 res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
661 res_builder = SCons.Builder.Builder(action=res_action, suffix='.res',
662 source_scanner=SCons.Tool.SourceFileScanner)
663 SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
666 """Add Builders and construction variables for MSVC++ to an Environment."""
667 static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
669 for suffix in CSuffixes:
670 static_obj.add_action(suffix, SCons.Defaults.CAction)
671 shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
672 static_obj.add_emitter(suffix, static_object_emitter)
673 shared_obj.add_emitter(suffix, shared_object_emitter)
675 for suffix in CXXSuffixes:
676 static_obj.add_action(suffix, SCons.Defaults.CXXAction)
677 shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
678 static_obj.add_emitter(suffix, static_object_emitter)
679 shared_obj.add_emitter(suffix, shared_object_emitter)
681 env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}'])
682 env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
683 env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
685 env['CCFLAGS'] = SCons.Util.CLVar('/nologo')
686 env['CCCOM'] = '$CC $CCFLAGS $CCCOMFLAGS'
688 env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
689 env['SHCCCOM'] = '$SHCC $SHCCFLAGS $CCCOMFLAGS'
691 env['CXXFLAGS'] = SCons.Util.CLVar('$CCFLAGS $( /TP $)')
692 env['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS'
693 env['SHCXX'] = '$CXX'
694 env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
695 env['SHCXXCOM'] = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
696 env['CPPDEFPREFIX'] = '/D'
697 env['CPPDEFSUFFIX'] = ''
698 env['INCPREFIX'] = '/I'
699 env['INCSUFFIX'] = ''
700 # env.Append(OBJEMITTER = [static_object_emitter])
701 # env.Append(SHOBJEMITTER = [shared_object_emitter])
702 env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
705 env['RCFLAGS'] = SCons.Util.CLVar('')
706 env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
707 env['BUILDERS']['RES'] = res_builder
708 env['OBJPREFIX'] = ''
709 env['OBJSUFFIX'] = '.obj'
710 env['SHOBJPREFIX'] = '$OBJPREFIX'
711 env['SHOBJSUFFIX'] = '$OBJSUFFIX'
714 version = SCons.Tool.msvs.get_default_visualstudio_version(env)
715 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
716 if version_num == 8.0:
717 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
719 use_mfc_dirs = env.get('MSVS_USE_MFC_DIRS', 0)
720 if env.get('MSVS_IGNORE_IDE_PATHS', 0):
721 _get_paths = get_msvc_default_paths
723 _get_paths = get_msvc_paths
724 include_path, lib_path, exe_path = _get_paths(env, version, use_mfc_dirs)
726 # since other tools can set these, we just make sure that the
727 # relevant stuff from MSVS is in there somewhere.
728 env.PrependENVPath('INCLUDE', include_path)
729 env.PrependENVPath('LIB', lib_path)
730 env.PrependENVPath('PATH', exe_path)
731 except (SCons.Util.RegError, SCons.Errors.InternalError):
734 env['CFILESUFFIX'] = '.c'
735 env['CXXFILESUFFIX'] = '.cc'
737 env['PCHPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Yd") or ""}'])
738 env['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
739 env['BUILDERS']['PCH'] = pch_builder
741 if not env.has_key('ENV'):
743 if not env['ENV'].has_key('SystemRoot'): # required for dlls in the winsxs folders
744 env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root()
747 if SCons.Tool.msvs.is_msvs_installed():
748 # there's at least one version of MSVS installed.
751 return env.Detect('cl')