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"
141 # XXX This code assumes anything that isn't EXPRESS uses the default
142 # registry key string. Is this really true for all VS suites?
143 if suite == 'EXPRESS':
146 s = '\\VisualStudio\\'
150 (settings_path, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
151 r'Software\Microsoft' + s + version +\
152 r'\Profile\AutoSaveFile')
153 settings_path = settings_path.upper()
154 except SCons.Util.RegError:
155 raise SCons.Errors.InternalError, \
156 "The VS8 settings file location was not found in the registry."
158 # Look for potential environment variables in the settings path
159 if settings_path.find('%VSSPV_VISUALSTUDIO_DIR%') >= 0:
160 # First replace a special variable named %vsspv_visualstudio_dir%
161 # that is not found in the OSs environment variables...
163 (value, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
164 r'Software\Microsoft' + s + version +\
165 r'\VisualStudioLocation')
166 settings_path = settings_path.replace('%VSSPV_VISUALSTUDIO_DIR%', value)
167 except SCons.Util.RegError:
168 raise SCons.Errors.InternalError, "The VS8 settings file location was not found in the registry."
170 if settings_path.find('%') >= 0:
171 # Collect global environment variables
174 # Read all the global environment variables of the current user
175 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_CURRENT_USER, r'Environment')
179 (key,val,t) = SCons.Util.RegEnumValue(k,i)
180 env_vars[key.upper()] = val.upper()
182 except SCons.Util.RegError:
185 # And some more variables that are not found in the registry
186 env_vars['USERPROFILE'] = os.getenv('USERPROFILE')
187 env_vars['SystemDrive'] = os.getenv('SystemDrive')
192 for env_var in env_vars:
193 if settings_path.find(r'%' + env_var + r'%') >= 0:
194 settings_path = settings_path.replace(r'%' + env_var + r'%', env_vars[env_var])
199 if os.path.exists(settings_path):
200 # now we parse the directories from this file, if it exists.
201 import xml.dom.minidom
202 doc = xml.dom.minidom.parse(settings_path)
203 user_settings = doc.getElementsByTagName('UserSettings')[0]
204 tool_options = user_settings.getElementsByTagName('ToolsOptions')[0]
205 tool_options_categories = tool_options.getElementsByTagName('ToolsOptionsCategory')
206 for category in tool_options_categories:
207 category_name = category.attributes.get('name')
208 if category_name is not None and category_name.value == 'Projects':
209 subcategories = category.getElementsByTagName('ToolsOptionsSubCategory')
210 for subcategory in subcategories:
211 subcategory_name = subcategory.attributes.get('name')
212 if subcategory_name is not None and subcategory_name.value == 'VCDirectories':
213 properties = subcategory.getElementsByTagName('PropertyValue')
214 for property in properties:
215 property_name = property.attributes.get('name')
216 if property_name is None:
218 elif property_name.value == 'IncludeDirectories':
219 include_dirs = property.childNodes[0].data
220 # ToDo: Support for other destinations than Win32
221 include_dirs = include_dirs.replace('Win32|', '')
222 dirs['INCLUDE'] = include_dirs
223 elif property_name.value == 'LibraryDirectories':
224 lib_dirs = property.childNodes[0].data.replace('Win32|', '')
225 # ToDo: Support for other destinations than Win32
226 lib_dirs = lib_dirs.replace('Win32|', '')
227 dirs['LIBRARY'] = lib_dirs
228 elif property_name.value == 'ExecutableDirectories':
229 path_dirs = property.childNodes[0].data.replace('Win32|', '')
230 # ToDo: Support for other destinations than Win32
231 path_dirs = path_dirs.replace('Win32|', '')
232 dirs['PATH'] = path_dirs
234 # There are no default directories in the registry for VS8 Express :(
235 raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
238 def _get_msvc7_path(path, version, platform):
240 Get Visual Studio directories from version 7 (MSVS .NET)
241 (it has a different registry structure than versions before it)
243 # first, look for a customization of the default values in the
244 # registry: These are sometimes stored in the Local Settings area
245 # for Visual Studio, in a file, so we have to parse it.
246 dirs = _parse_msvc7_overrides(version,platform)
248 if dirs.has_key(path):
251 raise SCons.Errors.InternalError, \
252 "Unable to retrieve the %s path from MS VC++."%path
254 # collect some useful information for later expansions...
255 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
257 # expand the directory path variables that we support. If there
258 # is a variable we don't support, then replace that entry with
259 # "---Unknown Location VSInstallDir---" or something similar, to clue
260 # people in that we didn't find something, and so env expansion doesn't
261 # do weird things with the $(xxx)'s
262 s = re.compile('\$\(([a-zA-Z0-9_]+?)\)')
264 def repl(match, paths=paths):
265 key = string.upper(match.group(1))
266 if paths.has_key(key):
269 # Now look in the global environment variables
270 envresult = os.getenv(key)
271 if not envresult is None:
272 return envresult + '\\'
274 return '---Unknown Location %s---' % match.group()
277 for entry in p.split(os.pathsep):
278 entry = s.sub(repl,entry).rstrip('\n\r')
281 return string.join(rv,os.pathsep)
283 def _get_msvc8_path(path, version, platform, suite):
285 Get Visual Studio directories from version 8 (MSVS 2005)
286 (it has a different registry structure than versions before it)
288 # first, look for a customization of the default values in the
289 # registry: These are sometimes stored in the Local Settings area
290 # for Visual Studio, in a file, so we have to parse it.
291 dirs = _parse_msvc8_overrides(version, platform, suite)
293 if dirs.has_key(path):
296 raise SCons.Errors.InternalError, \
297 "Unable to retrieve the %s path from MS VC++."%path
299 # collect some useful information for later expansions...
300 paths = SCons.Tool.msvs.get_msvs_install_dirs(version, suite)
302 # expand the directory path variables that we support. If there
303 # is a variable we don't support, then replace that entry with
304 # "---Unknown Location VSInstallDir---" or something similar, to clue
305 # people in that we didn't find something, and so env expansion doesn't
306 # do weird things with the $(xxx)'s
307 s = re.compile('\$\(([a-zA-Z0-9_]+?)\)')
309 def repl(match, paths=paths):
310 key = string.upper(match.group(1))
311 if paths.has_key(key):
314 return '---Unknown Location %s---' % match.group()
317 for entry in p.split(os.pathsep):
318 entry = s.sub(repl,entry).rstrip('\n\r')
321 return string.join(rv,os.pathsep)
323 def get_msvc_path(env, path, version):
325 Get a list of visualstudio directories (include, lib or path).
326 Return a string delimited by the os.pathsep separator (';'). An
327 exception will be raised if unable to access the registry or
328 appropriate registry keys not found.
331 if not SCons.Util.can_read_reg:
332 raise SCons.Errors.InternalError, "No Windows registry module was found"
334 # normalize the case for comparisons (since the registry is case
336 path = string.upper(path)
341 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
342 if version_num >= 8.0:
343 platform = env.get('MSVS8_PLATFORM', 'x86')
344 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
348 if version_num >= 8.0:
349 return _get_msvc8_path(path, str(version_num), platform, suite)
350 elif version_num >= 7.0:
351 return _get_msvc7_path(path, str(version_num), platform)
353 path = string.upper(path + ' Dirs')
354 K = ('Software\\Microsoft\\Devstudio\\%s\\' +
355 'Build System\\Components\\Platforms\\Win32 (x86)\\Directories') % \
357 for base in (SCons.Util.HKEY_CURRENT_USER,
358 SCons.Util.HKEY_LOCAL_MACHINE):
360 k = SCons.Util.RegOpenKeyEx(base,K)
364 (p,v,t) = SCons.Util.RegEnumValue(k,i)
365 if string.upper(p) == path:
368 except SCons.Util.RegError:
370 except SCons.Util.RegError:
373 # if we got here, then we didn't find the registry entries:
374 raise SCons.Errors.InternalError, "The %s path was not found in the registry."%path
376 def _get_msvc6_default_paths(version, use_mfc_dirs):
377 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
378 three environment variables that should be set in order to execute
379 the MSVC 6.0 tools properly, if the information wasn't available
380 from the registry."""
387 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
388 MVSdir = paths['VSINSTALLDIR']
389 except (SCons.Util.RegError, SCons.Errors.InternalError, KeyError):
390 if os.environ.has_key('MSDEVDIR'):
391 MVSdir = os.path.normpath(os.path.join(os.environ['MSDEVDIR'],'..','..'))
393 MVSdir = r'C:\Program Files\Microsoft Visual Studio'
395 if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
396 MVSVCdir = paths['VCINSTALLDIR']
398 MVSVCdir = os.path.join(MVSdir,'VC98')
400 MVSCommondir = r'%s\Common' % MVSdir
402 mfc_include_ = r'%s\ATL\include;%s\MFC\include;' % (MVSVCdir, MVSVCdir)
403 mfc_lib_ = r'%s\MFC\lib;' % MVSVCdir
407 include_path = r'%s%s\include' % (mfc_include_, MVSVCdir)
408 lib_path = r'%s%s\lib' % (mfc_lib_, MVSVCdir)
410 if os.environ.has_key('OS') and os.environ['OS'] == "Windows_NT":
415 exe_path = r'%s\tools\%s;%s\MSDev98\bin;%s\tools;%s\bin' % (MVSCommondir, osdir, MVSCommondir, MVSCommondir, MVSVCdir)
416 return (include_path, lib_path, exe_path)
418 def _get_msvc7_default_paths(env, version, use_mfc_dirs):
419 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
420 three environment variables that should be set in order to execute
421 the MSVC .NET tools properly, if the information wasn't available
422 from the registry."""
430 paths = SCons.Tool.msvs.get_msvs_install_dirs(version)
431 MVSdir = paths['VSINSTALLDIR']
432 except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError):
433 if os.environ.has_key('VSCOMNTOOLS'):
434 MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..'))
436 # last resort -- default install location
437 MVSdir = r'C:\Program Files\Microsoft Visual Studio .NET'
440 if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
441 MVSVCdir = paths['VCINSTALLDIR']
443 MVSVCdir = os.path.join(MVSdir,'Vc7')
445 MVSCommondir = r'%s\Common7' % MVSdir
447 mfc_include_ = r'%s\atlmfc\include;' % MVSVCdir
448 mfc_lib_ = r'%s\atlmfc\lib;' % MVSVCdir
452 include_path = r'%s%s\include;%s\PlatformSDK\include' % (mfc_include_, MVSVCdir, MVSVCdir)
453 lib_path = r'%s%s\lib;%s\PlatformSDK\lib' % (mfc_lib_, MVSVCdir, MVSVCdir)
454 exe_path = r'%s\IDE;%s\bin;%s\Tools;%s\Tools\bin' % (MVSCommondir,MVSVCdir, MVSCommondir, MVSCommondir )
456 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'):
457 include_path = include_path + r';%s\include'%paths['FRAMEWORKSDKDIR']
458 lib_path = lib_path + r';%s\lib'%paths['FRAMEWORKSDKDIR']
459 exe_path = exe_path + r';%s\bin'%paths['FRAMEWORKSDKDIR']
461 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'):
462 exe_path = exe_path + r';%s\%s'%(paths['FRAMEWORKDIR'],paths['FRAMEWORKVERSION'])
464 return (include_path, lib_path, exe_path)
466 def _get_msvc8_default_paths(env, version, suite, use_mfc_dirs):
467 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
468 three environment variables that should be set in order to execute
469 the MSVC 8 tools properly, if the information wasn't available
470 from the registry."""
478 paths = SCons.Tool.msvs.get_msvs_install_dirs(version, suite)
479 MVSdir = paths['VSINSTALLDIR']
480 except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError):
481 if os.environ.has_key('VSCOMNTOOLS'):
482 MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..'))
484 # last resort -- default install location
485 MVSdir = os.getenv('ProgramFiles') + r'\Microsoft Visual Studio 8'
488 if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'):
489 MVSVCdir = paths['VCINSTALLDIR']
491 MVSVCdir = os.path.join(MVSdir,'VC')
493 MVSCommondir = os.path.join(MVSdir, 'Common7')
494 include_paths.append( os.path.join(MVSVCdir, 'include') )
495 lib_paths.append( os.path.join(MVSVCdir, 'lib') )
496 for base, subdir in [(MVSCommondir,'IDE'), (MVSVCdir,'bin'),
497 (MVSCommondir,'Tools'), (MVSCommondir,r'Tools\bin')]:
498 exe_paths.append( os.path.join( base, subdir) )
500 if paths.has_key('PLATFORMSDKDIR'):
501 PlatformSdkDir = paths['PLATFORMSDKDIR']
503 PlatformSdkDir = os.path.join(MVSVCdir,'PlatformSDK')
504 platform_include_path = os.path.join( PlatformSdkDir, 'Include' )
505 include_paths.append( platform_include_path )
506 lib_paths.append( os.path.join( PlatformSdkDir, 'Lib' ) )
508 if paths.has_key('PLATFORMSDKDIR'):
509 include_paths.append( os.path.join( platform_include_path, 'mfc' ) )
510 include_paths.append( os.path.join( platform_include_path, 'atl' ) )
512 atlmfc_path = os.path.join( MVSVCdir, 'atlmfc' )
513 include_paths.append( os.path.join( atlmfc_path, 'include' ) )
514 lib_paths.append( os.path.join( atlmfc_path, 'lib' ) )
516 env_include_path = SCons.Util.get_environment_var('INCLUDE')
518 include_paths.append( env_include_path )
520 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'):
521 fwdir = paths['FRAMEWORKSDKDIR']
522 include_paths.append( os.path.join( fwdir, 'include' ) )
523 lib_paths.append( os.path.join( fwdir, 'lib' ) )
524 exe_paths.append( os.path.join( fwdir, 'bin' ) )
526 if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'):
527 exe_paths.append( os.path.join( paths['FRAMEWORKDIR'], paths['FRAMEWORKVERSION'] ) )
529 include_path = string.join( include_paths, os.pathsep )
530 lib_path = string.join(lib_paths, os.pathsep )
531 exe_path = string.join(exe_paths, os.pathsep )
532 return (include_path, lib_path, exe_path)
534 def get_msvc_paths(env, version=None, use_mfc_dirs=0):
535 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
536 of those three environment variables that should be set
537 in order to execute the MSVC tools properly."""
543 versions = SCons.Tool.msvs.get_visualstudio_versions()
545 version = versions[0] #use highest version by default
549 # Some of the configured directories only
550 # appear if the user changes them from the default.
551 # Therefore, we'll see if we can get the path to the MSDev
552 # base installation from the registry and deduce the default
554 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
555 if version_num >= 8.0:
556 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
557 defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs)
558 elif version_num >= 7.0:
559 defpaths = _get_msvc7_default_paths(env, version, use_mfc_dirs)
561 defpaths = _get_msvc6_default_paths(version, use_mfc_dirs)
564 include_path = get_msvc_path(env, "include", version)
565 except (SCons.Util.RegError, SCons.Errors.InternalError):
566 include_path = defpaths[0]
569 lib_path = get_msvc_path(env, "lib", version)
570 except (SCons.Util.RegError, SCons.Errors.InternalError):
571 lib_path = defpaths[1]
574 exe_path = get_msvc_path(env, "path", version)
575 except (SCons.Util.RegError, SCons.Errors.InternalError):
576 exe_path = defpaths[2]
578 return (include_path, lib_path, exe_path)
580 def get_msvc_default_paths(env, version=None, use_mfc_dirs=0):
581 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those
582 three environment variables that should be set in order to execute
583 the MSVC tools properly. This will only return the default
584 locations for the tools, not the values used by MSVS in their
585 directory setup area. This can help avoid problems with different
586 developers having different settings, and should allow the tools
587 to run in most cases."""
589 if not version and not SCons.Util.can_read_reg:
594 version = SCons.Tool.msvs.get_visualstudio_versions()[0] #use highest version
595 except KeyboardInterrupt:
600 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
601 if version_num >= 8.0:
602 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
603 return _get_msvc8_default_paths(env, version, suite, use_mfc_dirs)
604 elif version_num >= 7.0:
605 return _get_msvc7_default_paths(env, version, use_mfc_dirs)
607 return _get_msvc6_default_paths(version, use_mfc_dirs)
609 def validate_vars(env):
610 """Validate the PCH and PCHSTOP construction variables."""
611 if env.has_key('PCH') and env['PCH']:
612 if not env.has_key('PCHSTOP'):
613 raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
614 if not SCons.Util.is_String(env['PCHSTOP']):
615 raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
617 def pch_emitter(target, source, env):
618 """Adds the object file target."""
626 if SCons.Util.splitext(str(t))[1] == '.pch':
628 if SCons.Util.splitext(str(t))[1] == '.obj':
632 obj = SCons.Util.splitext(str(pch))[0]+'.obj'
634 target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
636 return (target, source)
638 def object_emitter(target, source, env, parent_emitter):
639 """Sets up the PCH dependencies for an object file."""
643 parent_emitter(target, source, env)
645 if env.has_key('PCH') and env['PCH']:
646 env.Depends(target, env['PCH'])
648 return (target, source)
650 def static_object_emitter(target, source, env):
651 return object_emitter(target, source, env,
652 SCons.Defaults.StaticObjectEmitter)
654 def shared_object_emitter(target, source, env):
655 return object_emitter(target, source, env,
656 SCons.Defaults.SharedObjectEmitter)
658 pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
659 pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
661 source_scanner=SCons.Tool.SourceFileScanner)
662 res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
663 res_builder = SCons.Builder.Builder(action=res_action,
667 source_scanner=SCons.Tool.SourceFileScanner)
668 SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
671 """Add Builders and construction variables for MSVC++ to an Environment."""
672 static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
674 for suffix in CSuffixes:
675 static_obj.add_action(suffix, SCons.Defaults.CAction)
676 shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
677 static_obj.add_emitter(suffix, static_object_emitter)
678 shared_obj.add_emitter(suffix, shared_object_emitter)
680 for suffix in CXXSuffixes:
681 static_obj.add_action(suffix, SCons.Defaults.CXXAction)
682 shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
683 static_obj.add_emitter(suffix, static_object_emitter)
684 shared_obj.add_emitter(suffix, shared_object_emitter)
686 env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}'])
687 env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
688 env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
690 env['CCFLAGS'] = SCons.Util.CLVar('/nologo')
691 env['CFLAGS'] = SCons.Util.CLVar('')
692 env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
694 env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
695 env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
696 env['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
698 env['CXXFLAGS'] = SCons.Util.CLVar('$CCFLAGS $( /TP $)')
699 env['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS'
700 env['SHCXX'] = '$CXX'
701 env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
702 env['SHCXXCOM'] = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
703 env['CPPDEFPREFIX'] = '/D'
704 env['CPPDEFSUFFIX'] = ''
705 env['INCPREFIX'] = '/I'
706 env['INCSUFFIX'] = ''
707 # env.Append(OBJEMITTER = [static_object_emitter])
708 # env.Append(SHOBJEMITTER = [shared_object_emitter])
709 env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
712 env['RCFLAGS'] = SCons.Util.CLVar('')
713 env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
714 env['BUILDERS']['RES'] = res_builder
715 env['OBJPREFIX'] = ''
716 env['OBJSUFFIX'] = '.obj'
717 env['SHOBJPREFIX'] = '$OBJPREFIX'
718 env['SHOBJSUFFIX'] = '$OBJSUFFIX'
721 version = SCons.Tool.msvs.get_default_visualstudio_version(env)
722 version_num, suite = SCons.Tool.msvs.msvs_parse_version(version)
723 if version_num == 8.0:
724 suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env)
726 use_mfc_dirs = env.get('MSVS_USE_MFC_DIRS', 0)
727 if env.get('MSVS_IGNORE_IDE_PATHS', 0):
728 _get_paths = get_msvc_default_paths
730 _get_paths = get_msvc_paths
731 include_path, lib_path, exe_path = _get_paths(env, version, use_mfc_dirs)
733 # since other tools can set these, we just make sure that the
734 # relevant stuff from MSVS is in there somewhere.
735 env.PrependENVPath('INCLUDE', include_path)
736 env.PrependENVPath('LIB', lib_path)
737 env.PrependENVPath('PATH', exe_path)
738 except (SCons.Util.RegError, SCons.Errors.InternalError):
741 env['CFILESUFFIX'] = '.c'
742 env['CXXFILESUFFIX'] = '.cc'
744 env['PCHPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Yd") or ""}'])
745 env['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
746 env['BUILDERS']['PCH'] = pch_builder
748 if not env.has_key('ENV'):
750 if not env['ENV'].has_key('SystemRoot'): # required for dlls in the winsxs folders
751 env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root()
754 if SCons.Tool.msvs.is_msvs_installed():
755 # there's at least one version of MSVS installed.
758 return env.Detect('cl')