diff options
28 files changed, 843 insertions, 230 deletions
diff --git a/QMTest/TestSConsMSVS.py b/QMTest/TestSConsMSVS.py index f26510b..017a29f 100644 --- a/QMTest/TestSConsMSVS.py +++ b/QMTest/TestSConsMSVS.py @@ -478,7 +478,7 @@ expected_vcprojfile_8_0 = """\ \t\t\t\tReBuildCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"" \t\t\t\tCleanCommandLine="echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c "Test.exe"" \t\t\t\tOutput="Test.exe" -\t\t\t\tPreprocessorDefinitions="DEF1;DEF2" +\t\t\t\tPreprocessorDefinitions="DEF1;DEF2;DEF3=1234" \t\t\t\tIncludeSearchPath="inc1;inc2" \t\t\t\tForcedIncludes="" \t\t\t\tAssemblySearchPath="" @@ -539,7 +539,7 @@ expected_vcprojfile_8_0 = """\ SConscript_contents_8_0 = """\ env=Environment(platform='win32', tools=['msvs'], MSVS_VERSION='8.0', - CPPDEFINES=['DEF1', 'DEF2'], + CPPDEFINES=['DEF1', 'DEF2',('DEF3','1234')], CPPPATH=['inc1', 'inc2']) testsrc = ['test1.cpp', 'test2.cpp'] diff --git a/src/engine/MANIFEST-xml.in b/src/engine/MANIFEST-xml.in index 9cc9923..f6ce08a 100644 --- a/src/engine/MANIFEST-xml.in +++ b/src/engine/MANIFEST-xml.in @@ -22,6 +22,7 @@ SCons/Tool/ar.xml SCons/Tool/as.xml SCons/Tool/bcc32.xml SCons/Tool/c++.xml +SCons/Tool/c++.xml SCons/Tool/cc.xml SCons/Tool/cvf.xml SCons/Tool/default.xml @@ -37,6 +38,7 @@ SCons/Tool/g++.xml SCons/Tool/g77.xml SCons/Tool/gas.xml SCons/Tool/gcc.xml +SCons/Tool/gfortran.xml SCons/Tool/gnulink.xml SCons/Tool/gs.xml SCons/Tool/hpc++.xml @@ -84,6 +86,9 @@ SCons/Tool/sgilink.xml SCons/Tool/sunar.xml SCons/Tool/sunc++.xml SCons/Tool/suncc.xml +SCons/Tool/sunf77.xml +SCons/Tool/sunf90.xml +SCons/Tool/sunf95.xml SCons/Tool/sunlink.xml SCons/Tool/swig.xml SCons/Tool/tar.xml diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 7f18726..2185d30 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -118,10 +118,12 @@ SCons/Tool/lex.py SCons/Tool/link.py SCons/Tool/linkloc.py SCons/Tool/MSCommon/__init__.py +SCons/Tool/MSCommon/arch.py SCons/Tool/MSCommon/common.py SCons/Tool/MSCommon/netframework.py SCons/Tool/MSCommon/sdk.py SCons/Tool/MSCommon/vs.py +SCons/Tool/MSCommon/vc.py SCons/Tool/m4.py SCons/Tool/masm.py SCons/Tool/midl.py diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index e4d6da3..eba86e4 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -367,9 +367,9 @@ def _stripixes(prefix, list, suffix, stripprefixes, stripsuffixes, env, c=None): return c(prefix, stripped, suffix, env) -def _defines(prefix, defs, suffix, env, c=_concat_ixes): - """A wrapper around _concat_ixes that turns a list or string - into a list of C preprocessor command-line definitions. +def processDefines(defs): + """process defines, resolving strings, lists, dictionaries, into a list of + strings """ if SCons.Util.is_List(defs): l = [] @@ -396,7 +396,14 @@ def _defines(prefix, defs, suffix, env, c=_concat_ixes): l.append(str(k) + '=' + str(v)) else: l = [str(defs)] - return c(prefix, env.subst_path(l), suffix, env) + return l + +def _defines(prefix, defs, suffix, env, c=_concat_ixes): + """A wrapper around _concat_ixes that turns a list or string + into a list of C preprocessor command-line definitions. + """ + + return c(prefix, env.subst_path(processDefines(defs)), suffix, env) class NullCmdGenerator: """This is a callable class that can be used in place of other diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 80d8516..ff8b116 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -119,7 +119,11 @@ reserved_construction_var_names = [ 'UNCHANGED_TARGETS', ] -future_reserved_construction_var_names = [] +future_reserved_construction_var_names = [ + #'HOST_OS', + #'HOST_ARCH', + #'HOST_CPU', + ] def copy_non_reserved_keywords(dict): result = semi_deepcopy(dict) @@ -959,6 +963,14 @@ class Base(SubstitutionEnvironment): platform = SCons.Platform.Platform(platform) self._dict['PLATFORM'] = str(platform) platform(self) + + self._dict['HOST_OS'] = self._dict.get('HOST_OS',None) + self._dict['HOST_ARCH'] = self._dict.get('HOST_ARCH',None) + + # Now set defaults for TARGET_{OS|ARCH} + self._dict['TARGET_OS'] = self._dict.get('HOST_OS',None) + self._dict['TARGET_ARCH'] = self._dict.get('HOST_ARCH',None) + # Apply the passed-in and customizable variables to the # environment before calling the tools, because they may use diff --git a/src/engine/SCons/Platform/__init__.xml b/src/engine/SCons/Platform/__init__.xml index a74df5a..99f3322 100644 --- a/src/engine/SCons/Platform/__init__.xml +++ b/src/engine/SCons/Platform/__init__.xml @@ -83,6 +83,47 @@ else: </summary> </cvar> +<cvar name="HOST_OS"> + <summary> + The name of the host operating system used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. + </summary> +</cvar> + +<cvar name="HOST_ARCH"> + <summary> + The name of the host hardware architecture used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. + </summary> +</cvar> + +<cvar name="TARGET_OS"> + <summary> + The name of the target operating system for the compiled objects + created by this Environment. + This defaults to the value of HOST_OS, and the user can override it. + Currently only set for Win32. + </summary> +</cvar> + +<cvar name="TARGET_ARCH"> + <summary> + The name of the target hardware architecture for the compiled objects + created by this Environment. + This defaults to the value of HOST_ARCH, and the user can override it. + Currently only set for Win32. + </summary> +</cvar> + + <cvar name="PROGPREFIX"> <summary> The prefix used for executable file names. diff --git a/src/engine/SCons/Platform/os2.py b/src/engine/SCons/Platform/os2.py index 41e8312..aa348d4 100644 --- a/src/engine/SCons/Platform/os2.py +++ b/src/engine/SCons/Platform/os2.py @@ -31,6 +31,7 @@ selection method. # __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import win32 def generate(env): if not env.has_key('ENV'): @@ -47,6 +48,8 @@ def generate(env): env['SHLIBSUFFIX'] = '.dll' env['LIBPREFIXES'] = '$LIBPREFIX' env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ] + env['HOST_OS'] = 'os2' + env['HOST_ARCH'] = win32.get_architecture().arch # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 1dc7f3c..78822c6 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -42,8 +42,6 @@ from SCons.Platform.posix import exitvalmap from SCons.Platform import TempFileMunge import SCons.Util - - try: import msvcrt import win32api @@ -67,7 +65,7 @@ else: _builtin_file = __builtin__.file _builtin_open = __builtin__.open - + def _scons_file(*args, **kw): fp = apply(_builtin_file, args, kw) win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()), @@ -239,6 +237,53 @@ def get_program_files_dir(): return val + + +# Determine which windows CPU were running on. +class ArchDefinition: + """ + A class for defining architecture-specific settings and logic. + """ + def __init__(self, arch, synonyms=[]): + self.arch = arch + self.synonyms = synonyms + +SupportedArchitectureList = [ + ArchDefinition( + 'x86', + ['i386', 'i486', 'i586', 'i686'], + ), + + ArchDefinition( + 'x86_64', + ['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'], + ), + + ArchDefinition( + 'ia64', + ['IA64'], + ), +] + +SupportedArchitectureMap = {} +for a in SupportedArchitectureList: + SupportedArchitectureMap[a.arch] = a + for s in a.synonyms: + SupportedArchitectureMap[s] = a + +def get_architecture(arch=None): + """Returns the definition for the specified architecture string. + + If no string is specified, the system default is returned (as defined + by the PROCESSOR_ARCHITEW6432 or PROCESSOR_ARCHITECTURE environment + variables). + """ + if arch is None: + arch = os.environ.get('PROCESSOR_ARCHITEW6432') + if not arch: + arch = os.environ['PROCESSOR_ARCHITECTURE'] + return SupportedArchitectureMap.get(arch, '') + def generate(env): # Attempt to find cmd.exe (for WinNT/2k/XP) or # command.com for Win9x @@ -329,6 +374,10 @@ def generate(env): env['TEMPFILEPREFIX'] = '@' env['MAXLINELENGTH'] = 2048 env['ESCAPE'] = escape + + env['HOST_OS'] = 'win32' + env['HOST_ARCH'] = get_architecture().arch + # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py index a59bf15..c883287 100644 --- a/src/engine/SCons/Tool/MSCommon/__init__.py +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -36,10 +36,16 @@ import SCons.Errors import SCons.Platform.win32 import SCons.Util -from SCons.Tool.MSCommon.vs import detect_msvs, \ - get_default_version, \ +from SCons.Tool.MSCommon.sdk import mssdk_exists, \ + mssdk_setup_env + +from SCons.Tool.MSCommon.vc import msvc_exists, \ + msvc_setup_env + +from SCons.Tool.MSCommon.vs import get_default_version, \ get_vs_by_version, \ merge_default_version, \ + msvs_exists, \ query_versions # Local Variables: diff --git a/src/engine/SCons/Tool/MSCommon/arch.py b/src/engine/SCons/Tool/MSCommon/arch.py new file mode 100644 index 0000000..2638b72 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/arch.py @@ -0,0 +1,61 @@ +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """Module to define supported Windows chip architectures. +""" + +import os + +class ArchDefinition: + """ + A class for defining architecture-specific settings and logic. + """ + def __init__(self, arch, synonyms=[]): + self.arch = arch + self.synonyms = synonyms + +SupportedArchitectureList = [ + ArchitectureDefinition( + 'x86', + ['i386', 'i486', 'i586', 'i686'], + ), + + ArchitectureDefinition( + 'x86_64', + ['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'], + ), + + ArchitectureDefinition( + 'ia64', + ['IA64'], + ), +] + +SupportedArchitectureMap = {} +for a in SupportedArchitectureList: + SupportedArchitectureMap[a.arch] = a + for s in a.synonyms: + SupportedArchitectureMap[s] = a + diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 3583246..f74d10c 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -24,7 +24,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" __doc__ = """ -Common helper functions for working with +Common helper functions for working with the Microsoft tool chain. """ import copy @@ -36,7 +36,10 @@ import SCons.Util logfile = os.environ.get('SCONS_MSCOMMON_DEBUG') -if logfile: +if logfile == '-': + def debug(x): + print x +elif logfile: try: import logging except ImportError: @@ -48,19 +51,25 @@ else: debug = lambda x: None -# TODO(sgk): unused +_is_win64 = None + def is_win64(): """Return true if running on windows 64 bits.""" - # Unfortunately, python does not seem to have anything useful: neither - # sys.platform nor os.name gives something different on windows running on - # 32 bits or 64 bits. Note that we don't care about whether python itself - # is 32 or 64 bits here - value = "Software\Wow6432Node" - yo = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0] - if yo is None: - return 0 - else: - return 1 + # Unfortunately, python does not provide a useful way to determine + # if the underlying Windows OS is 32-bit or 64-bit. Worse, whether + # the Python itself is 32-bit or 64-bit affects what it returns, + # so nothing in sys.* or os.* help. So we go to the registry to + # look directly for a clue from Windows, caching the result to + # avoid repeated registry calls. + global _is_win64 + if _is_win64 is None: + try: + yo = read_reg(r'Software\Wow6432Node') + except WindowsError: + yo = None + _is_win64 = (yo is not None) + return _is_win64 + def read_reg(value): return SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0] diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 6791fd7..d9f609c 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -31,9 +31,12 @@ PSDK 2003 R1 is the earliest version detected. import os import SCons.Errors -from SCons.Tool.MSCommon.common import debug, read_reg import SCons.Util +import common + +debug = common.debug + # SDK Checks. This is of course a mess as everything else on MS platforms. Here # is what we do to detect the SDK: # @@ -69,15 +72,15 @@ class SDKDefinition: Return None if failed or the directory does not exist. """ if not SCons.Util.can_read_reg: - debug('find_sdk_dir(): can not read registry') + debug('find_sdk_dir(): can not read registry') return None hkey = self.HKEY_FMT % self.hkey_data try: - sdk_dir = read_reg(hkey) + sdk_dir = common.read_reg(hkey) except WindowsError, e: - debug('find_sdk_dir(): no registry key %s' % hkey) + debug('find_sdk_dir(): no SDK registry key %s' % repr(hkey)) return None if not os.path.exists(sdk_dir): @@ -86,7 +89,7 @@ class SDKDefinition: ftc = os.path.join(sdk_dir, self.sanity_check_file) if not os.path.exists(ftc): - debug("find_sdk_dir(): sanity check %s not found" % ftc) + debug("find_sdk_dir(): sanity check %s not found" % ftc) return None return sdk_dir @@ -127,21 +130,40 @@ class PlatformSDK(SDKDefinition): # If you update this list, update the documentation in Tool/mssdk.xml. SupportedSDKList = [ WindowsSDK('6.1', - sanity_check_file=r'include\windows.h'), + sanity_check_file=r'bin\SetEnv.Cmd', + include_subdir='include', + lib_subdir={ + 'x86' : ['lib'], + 'x86_64' : [r'lib\x64'], + 'ia64' : [r'lib\ia64'], + }, + ), WindowsSDK('6.0A', - sanity_check_file=r'include\windows.h'), + sanity_check_file=r'include\windows.h', + include_subdir='include', + lib_subdir={ + 'x86' : ['lib'], + 'x86_64' : [r'lib\x64'], + 'ia64' : [r'lib\ia64'], + }, + ), WindowsSDK('6.0', - sanity_check_file=r'bin\gacutil.exe'), + sanity_check_file=r'bin\gacutil.exe', + include_subdir='include', + lib_subdir='lib', + ), PlatformSDK('2003R2', sanity_check_file=r'SetEnv.Cmd', - uuid="D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1"), + uuid="D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1" + ), PlatformSDK('2003R1', sanity_check_file=r'SetEnv.Cmd', - uuid="8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3"), + uuid="8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3", + ), ] SupportedSDKMap = {} @@ -215,7 +237,7 @@ def get_cur_sdk_dir_from_reg(): return None try: - val = read_reg(_CURINSTALLED_SDK_HKEY_ROOT) + val = common.read_reg(_CURINSTALLED_SDK_HKEY_ROOT) debug("Found current sdk dir in registry: %s" % val) except WindowsError, e: debug("Did not find current sdk in registry") @@ -227,28 +249,66 @@ def get_cur_sdk_dir_from_reg(): return val - -def detect_sdk(): - return (len(get_installed_sdks()) > 0) - -def set_sdk_by_version(env, mssdk): +def get_sdk_by_version(mssdk): if not SupportedSDKMap.has_key(mssdk): msg = "SDK version %s is not supported" % repr(mssdk) raise SCons.Errors.UserError, msg get_installed_sdks() - sdk = InstalledSDKMap.get(mssdk) - if not sdk: - msg = "SDK version %s is not installed" % repr(mssdk) - raise SCons.Errors.UserError, msg - set_sdk_by_directory(env, sdk.get_sdk_dir()) + return InstalledSDKMap.get(mssdk) -def set_default_sdk(env, msver): +def get_default_sdk(): """Set up the default Platform/Windows SDK.""" - # For MSVS < 8, use integrated windows sdk by default - if msver >= 8: - sdks = get_installed_sdks() - if len(sdks) > 0: - set_sdk_by_directory(env, sdks[0].get_sdk_dir()) + get_installed_sdks() + return InstalledSDKList[0] + +def mssdk_setup_env(env): + debug('msvs_setup_env()') + if env.has_key('MSSDK_DIR'): + sdk_dir = env['MSSDK_DIR'] + if sdk_dir is None: + return + sdk_dir = env.subst(sdk_dir) + elif env.has_key('MSSDK_VERSION'): + sdk_version = env['MSSDK_VERSION'] + if sdk_version is None: + msg = "SDK version %s is not installed" % repr(mssdk) + raise SCons.Errors.UserError, msg + sdk_version = env.subst(sdk_version) + mssdk = get_sdk_by_version(sdk_version) + sdk_dir = mssdk.get_sdk_dir() + elif env.has_key('MSVS_VERSION'): + msvs_version = env['MSVS_VERSION'] + debug('Getting MSVS_VERSION from env:%s'%msvs_version) + if msvs_version is None: + return + msvs_version = env.subst(msvs_version) + import vs + msvs = vs.get_vs_by_version(msvs_version) + debug('msvs is :%s'%msvs) + sdk_version = msvs.sdk_version + if not sdk_version: + return + mssdk = get_sdk_by_version(sdk_version) + if not mssdk: + mssdk = get_default_sdk() + if not mssdk: + return + sdk_dir = mssdk.get_sdk_dir() + else: + mssdk = get_default_sdk() + if not mssdk: + return + sdk_dir = mssdk.get_sdk_dir() + + set_sdk_by_directory(env, sdk_dir) + + #print "No MSVS_VERSION: this is likely to be a bug" + +def mssdk_exists(version=None): + sdks = get_installed_sdks() + if version is None: + return len(sdks) > 0 + return sdks.has_key(version) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py new file mode 100644 index 0000000..222c284 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -0,0 +1,340 @@ +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__doc__ = """Module for Visual C/C++ detection and configuration. +""" + +import os + +import SCons.Warnings + +import common + +debug = common.debug + +class VisualC: + """ + An base class for finding installed versions of Visual C/C++. + """ + def __init__(self, version, **kw): + self.version = version + self.__dict__.update(kw) + self._cache = {} + + def vcbin_arch(self): + if common.is_win64(): + result = { + 'x86_64' : ['amd64', r'BIN\x86_amd64'], + 'ia64' : [r'BIN\ia64'], + }.get(target_arch, []) + else: + result = { + 'x86_64' : ['x86_amd64'], + 'ia64' : ['x86_ia64'], + }.get(target_arch, []) + # TODO(1.5) + #return ';'.join(result) + return string.join(result, ';') + + # Support for searching for an appropriate .bat file. + # The map is indexed by (target_architecture, host_architecture). + # Entries where the host_architecture is None specify the + # cross-platform "default" .bat file if there isn't sn entry + # specific to the current host architecture. + + batch_file_map = { + ('x86_64', 'x86_64') : [ + r'bin\amd64\vcvarsamd64.bat', + r'bin\x86_amd64\vcvarsx86_amd64.bat', + ], + ('x86_64', 'x86') : [ + r'bin\x86_amd64\vcvarsx86_amd64.bat', + ], + ('ia64', 'ia64') : [ + r'bin\ia64\vcvarsia64.bat', + r'bin\x86_ia64\vcvarsx86_ia64.bat', + ], + ('ia64', None) : [ + r'bin\x86_ia64\vcvarsx86_ia64.bat', + ], + ('x86', None) : [ + r'bin\vcvars32.bat', + ], + } + + def find_batch_file(self, target_architecture, host_architecture): + key = (target_architecture, host_architecture) + potential_batch_files = self.batch_file_map.get(key) + if not potential_batch_files: + key = (target_architecture, None) + potential_batch_files = self.batch_file_map.get(key) + if potential_batch_files: + product_dir = self.get_vc_dir() + for batch_file in potential_batch_files: + bf = os.path.join(product_dir, batch_file) + if os.path.isfile(bf): + return bf + return None + + def find_vc_dir(self): + root = 'Software\\' + if common.is_win64(): + root = root + 'Wow6432Node\\' + for key in self.hkeys: + key = root + key + try: + comps = common.read_reg(key) + except WindowsError, e: + debug('find_vc_dir(): no VC registry key %s' % repr(key)) + else: + debug('find_vc_dir(): found VC in registry: %s' % comps) + return comps + return None + + # + + def get_batch_file(self, target_architecture, host_architecture): + try: + return self._cache['batch_file'] + except KeyError: + batch_file = self.find_batch_file(target_architecture, host_architecture) + self._cache['batch_file'] = batch_file + return batch_file + + def get_vc_dir(self): + try: + return self._cache['vc_dir'] + except KeyError: + vc_dir = self.find_vc_dir() + self._cache['vc_dir'] = vc_dir + return vc_dir + + def reset(self): + self._cache={} + + +# The list of supported Visual C/C++ versions we know how to detect. +# +# The first VC found in the list is the one used by default if there +# are multiple VC installed. Barring good reasons to the contrary, +# this means we should list VC with from most recent to oldest. +# +# If you update this list, update the documentation in Tool/vc.xml. +SupportedVCList = [ + VisualC('9.0', + hkeys=[ + r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir', + r'Microsoft\VCExpress\9.0\Setup\VC\ProductDir', + ], + default_install=r'Microsoft Visual Studio 9.0\VC', + common_tools_var='VS90COMNTOOLS', + vc_subdir=r'\VC', + batch_file_base='vcvars', + supported_arch=['x86', 'x86_64', 'ia64'], + atlmc_include_subdir = [r'ATLMFC\INCLUDE'], + atlmfc_lib_subdir = { + 'x86' : r'ATLMFC\LIB', + 'x86_64' : r'ATLMFC\LIB\amd64', + 'ia64' : r'ATLMFC\LIB\ia64', + }, + crt_lib_subdir = { + 'x86_64' : r'LIB\amd64', + 'ia64' : r'LIB\ia64', + }, + ), + VisualC('8.0', + hkeys=[ + r'Microsoft\VisualStudio\8.0\Setup\VC\ProductDir', + r'Microsoft\VCExpress\8.0\Setup\VC\ProductDir', + ], + default_install=r'%s\Microsoft Visual Studio 8\VC', + common_tools_var='VS80COMNTOOLS', + vc_subdir=r'\VC', + batch_file_base='vcvars', + supported_arch=['x86', 'x86_64', 'ia64'], + atlmc_include_subdir = [r'ATLMFC\INCLUDE'], + atlmfc_lib_subdir = { + 'x86' : r'ATLMFC\LIB', + 'x86_64' : r'ATLMFC\LIB\amd64', + 'ia64' : r'ATLMFC\LIB\ia64', + }, + crt_lib_subdir = { + 'x86_64' : r'LIB\amd64', + 'ia64' : r'LIB\ia64', + }, + ), + VisualC('7.1', + hkeys=[ + r'Microsoft\VisualStudio\7.1\Setup\VC\ProductDir', + ], + default_install=r'%s\Microsoft Visual Studio 7.1.NET 2003\VC7', + common_tools_var='VS71COMNTOOLS', + vc_subdir=r'\VC7', + batch_file_base='vcvars', + supported_arch=['x86'], + atlmc_include_subdir = [r'ATLMFC\INCLUDE'], + atlmfc_lib_subdir = { + 'x86' : r'ATLMFC\LIB', + }, + ), + VisualC('7.0', + hkeys=[ + r'Microsoft\VisualStudio\7.0\Setup\VC\ProductDir', + ], + default_install=r'%s\Microsoft Visual Studio .NET\VC7', + common_tools_var='VS70COMNTOOLS', + vc_subdir=r'\VC7', + batch_file_base='vcvars', + supported_arch=['x86'], + atlmc_include_subdir = [r'ATLMFC\INCLUDE'], + atlmfc_lib_subdir = { + 'x86' : r'ATLMFC\LIB', + }, + ), + VisualC('6.0', + hkeys=[ + r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir', + ], + default_install=r'%s\Microsoft Visual Studio\VC98', + common_tools_var='VS60COMNTOOLS', + vc_subdir=r'\VC98', + batch_file_base='vcvars', + supported_arch=['x86'], + atlmc_include_subdir = [r'ATL\INCLUDE', r'MFC\INCLUDE'], + atlmfc_lib_subdir = { + 'x86' : r'MFC\LIB', + }, + ), +] + +SupportedVCMap = {} +for vc in SupportedVCList: + SupportedVCMap[vc.version] = vc + + +# Finding installed versions of Visual C/C++ isn't cheap, because it goes +# not only to the registry but also to the disk to sanity-check that there +# is, in fact, something installed there and that the registry entry isn't +# just stale. Find this information once, when requested, and cache it. + +InstalledVCList = None +InstalledVCMap = None + +def get_installed_vcs(): + global InstalledVCList + global InstalledVCMap + if InstalledVCList is None: + InstalledVCList = [] + InstalledVCMap = {} + for vc in SupportedVCList: + debug('trying to find VC %s' % vc.version) + if vc.get_vc_dir(): + debug('found VC %s' % vc.version) + InstalledVCList.append(vc) + InstalledVCMap[vc.version] = vc + return InstalledVCList + + +def set_vc_by_version(env, msvc): + if not SupportedVCMap.has_key(msvc): + msg = "VC version %s is not supported" % repr(msvc) + raise SCons.Errors.UserError, msg + get_installed_vcs() + vc = InstalledVCMap.get(msvc) + if not vc: + msg = "VC version %s is not installed" % repr(msvc) + raise SCons.Errors.UserError, msg + set_vc_by_directory(env, vc.get_vc_dir()) + +# New stuff + +def script_env(script): + stdout = common.get_output(script) + return common.parse_output(stdout) + +def msvc_setup_env(env): + debug('msvc_setup_env()') + installed_vcs = get_installed_vcs() + msvc_version = env.get('MSVC_VERSION') + if not msvc_version: + if not installed_vcs: + msg = 'No installed VCs' + debug('msv %s\n' % repr(msg)) + SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg) + return + msvc = installed_vcs[0] + msvc_version = msvc.version + env['MSVC_VERSION'] = msvc_version + else: + msvc = InstalledVCMap.get(msvc_version) + if not msvc: + msg = 'VC version %s not installed' % msvc_version + debug('msv %s\n' % repr(msg)) + SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg) + return + + host_platform = env.get('HOST_ARCH') + if not host_platform: + #host_platform = get_default_host_platform() + host_platform = 'x86' + target_platform = env.get('TARGET_ARCH') + if not target_platform: + target_platform = host_platform + + use_script = env.get('MSVC_USE_SCRIPT', True) + if SCons.Util.is_String(use_script): + debug('use_script 1 %s\n' % repr(use_script)) + d = script_env(use_script) + elif use_script: + script = msvc.get_batch_file(target_platform, host_platform) + debug('use_script 2 %s target_platform:%s host_platform:%s\n' % (repr(script),target_platform,host_platform)) + d = script_env(script) + else: + debug('msvc.get_default_env()\n') + d = msvc.get_default_env() + + for k, v in d.items(): + env.PrependENVPath(k, v, delete_existing=True) + +def msvc_exists(version=None): + vcs = get_installed_vcs() + if version is None: + return len(vcs) > 0 + return InstalledVCMap.has_key(version) + + +def reset_installed_vcs(): + global InstalledVCList + global InstalledVCMap + InstalledVCList = None + InstalledVCMap = None + for vc in SupportedVCList: + vc.reset() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index da22fa9..8d5c66b 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -31,11 +31,14 @@ import os import SCons.Errors import SCons.Util -from SCons.Tool.MSCommon.common import debug, \ - read_reg, \ - normalize_env, \ - get_output, \ - parse_output +from common import debug, \ + get_output, \ + is_win64, \ + normalize_env, \ + parse_output, \ + read_reg + +import SCons.Tool.MSCommon.vc class VisualStudio: """ @@ -44,70 +47,75 @@ class VisualStudio: """ def __init__(self, version, **kw): self.version = version + kw['vc_version'] = kw.get('vc_version', version) + kw['sdk_version'] = kw.get('sdk_version', version) self.__dict__.update(kw) self._cache = {} # def find_batch_file(self): - """Try to find the Visual Studio or Visual C/C++ batch file. - - Return None if failed or the batch file does not exist. - """ - pdir = self.get_vc_product_dir() - if not pdir: - debug('find_batch_file(): no pdir') + vs_dir = self.get_vs_dir() + if not vs_dir: + debug('find_executable(): no vs_dir') return None - batch_file = os.path.normpath(os.path.join(pdir, self.batch_file)) + batch_file = os.path.join(vs_dir, self.batch_file_path) batch_file = os.path.normpath(batch_file) if not os.path.isfile(batch_file): debug('find_batch_file(): %s not on file system' % batch_file) return None return batch_file + def find_vs_dir_by_vc(self): + SCons.Tool.MSCommon.vc.get_installed_vcs() + ivc = SCons.Tool.MSCommon.vc.InstalledVCMap.get(self.vc_version) + if not ivc: + debug('find_vs_dir(): no installed VC %s' % self.vc_version) + return None + return ivc.get_vc_dir()[:-len(ivc.vc_subdir)] + + def find_vs_dir_by_reg(self): + root = 'Software\\' + + if is_win64(): + root = root + 'Wow6432Node\\' + for key in self.hkeys: + if key=='use_dir': + return self.find_vs_dir_by_vc() + key = root + key + try: + comps = read_reg(key) + except WindowsError, e: + debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key)) + else: + debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps) + return comps + return None + + def find_vs_dir(self): + """ Can use registry or location of VC to find vs dir + First try to find by registry, and if that fails find via VC dir + """ + + + if True: + vs_dir=self.find_vs_dir_by_reg() + return vs_dir + else: + return self.find_vs_dir_by_vc() + def find_executable(self): - pdir = self.get_vc_product_dir() - if not pdir: - debug('find_executable(): no pdir') + vs_dir = self.get_vs_dir() + if not vs_dir: + debug('find_executable(): no vs_dir (%s)'%vs_dir) return None - executable = os.path.join(pdir, self.executable_path) + executable = os.path.join(vs_dir, self.executable_path) executable = os.path.normpath(executable) if not os.path.isfile(executable): debug('find_executable(): %s not on file system' % executable) return None return executable - - def find_vc_product_dir(self): - if not SCons.Util.can_read_reg: - debug('find_vc_product_dir(): can not read registry') - return None - key = self.hkey_root + '\\' + self.vc_product_dir_key - try: - comps = read_reg(key) - except WindowsError, e: - debug('find_vc_product_dir(): no registry key %s' % key) - else: - if self.batch_file_dir_reg_relpath: - comps = os.path.join(comps, self.batch_file_dir_reg_relpath) - comps = os.path.normpath(comps) - if os.path.exists(comps): - return comps - else: - debug('find_vc_product_dir(): %s not on file system' % comps) - - d = os.environ.get(self.common_tools_var) - if not d: - msg = 'find_vc_product_dir(): no %s variable' - debug(msg % self.common_tools_var) - return None - if not os.path.isdir(d): - debug('find_vc_product_dir(): %s not on file system' % d) - return None - if self.batch_file_dir_env_relpath: - d = os.path.join(d, self.batch_file_dir_env_relpath) - d = os.path.normpath(d) - return d - + # def get_batch_file(self): @@ -120,12 +128,22 @@ class VisualStudio: def get_executable(self): try: + debug('get_executable using cache'%self._cache['executable']) return self._cache['executable'] except KeyError: executable = self.find_executable() self._cache['executable'] = executable + debug('get_executable not in cache:%s'%executable) return executable + def get_vs_dir(self): + try: + return self._cache['vs_dir'] + except KeyError: + vs_dir = self.find_vs_dir() + self._cache['vs_dir'] = vs_dir + return vs_dir + def get_supported_arch(self): try: return self._cache['supported_arch'] @@ -135,14 +153,6 @@ class VisualStudio: self._cache['supported_arch'] = self.supported_arch return self.supported_arch - def get_vc_product_dir(self): - try: - return self._cache['vc_product_dir'] - except KeyError: - vc_product_dir = self.find_vc_product_dir() - self._cache['vc_product_dir'] = vc_product_dir - return vc_product_dir - def reset(self): self._cache = {} @@ -197,10 +207,6 @@ SupportedVSList = [ #VisualStudio('TBD', # hkey_root=r'TBD', # common_tools_var='TBD', - # batch_file='TBD', - # vc_product_dir_key=r'TBD', - # batch_file_dir_reg_relpath=None, - # batch_file_dir_env_relpath=r'TBD', # executable_path=r'TBD', # default_dirname='TBD', #), @@ -209,13 +215,11 @@ SupportedVSList = [ # The batch file we look for is in the VC directory, # so the devenv.com executable is up in ..\..\Common7\IDE. VisualStudio('9.0', - hkey_root=r'Software\Microsoft\VisualStudio\9.0', + sdk_version='6.1', + hkeys=[r'Microsoft\VisualStudio\9.0\Setup\VS\ProductDir'], common_tools_var='VS90COMNTOOLS', - batch_file='vcvarsall.bat', - vc_product_dir_key=r'Setup\VC\ProductDir', - batch_file_dir_reg_relpath=None, - batch_file_dir_env_relpath=r'..\..\VC', - executable_path=r'..\Common7\IDE\devenv.com', + executable_path=r'Common7\IDE\devenv.com', + batch_file_path=r'Common7\Tools\vsvars32.bat', default_dirname='Microsoft Visual Studio 9', supported_arch=['x86', 'amd64'], ), @@ -224,13 +228,12 @@ SupportedVSList = [ # The batch file we look for is in the VC directory, # so the VCExpress.exe executable is up in ..\..\Common7\IDE. VisualStudio('9.0Exp', - hkey_root=r'Software\Microsoft\VisualStudio\9.0', + vc_version='9.0', + sdk_version='6.1', + hkeys=[r'Microsoft\VCExpress\9.0\Setup\VS\ProductDir'], common_tools_var='VS90COMNTOOLS', - batch_file='vcvarsall.bat', - vc_product_dir_key=r'Setup\VC\ProductDir', - batch_file_dir_reg_relpath=None, - batch_file_dir_env_relpath=r'..\..\VC', - executable_path=r'..\Common7\IDE\VCExpress.exe', + executable_path=r'Common7\IDE\VCExpress.exe', + batch_file_path=r'Common7\Tools\vsvars32.bat', default_dirname='Microsoft Visual Studio 9', supported_arch=['x86'], ), @@ -239,13 +242,11 @@ SupportedVSList = [ # The batch file we look for is in the VC directory, # so the devenv.com executable is up in ..\..\Common7\IDE. VisualStudio('8.0', - hkey_root=r'Software\Microsoft\VisualStudio\8.0', + sdk_version='6.0A', + hkeys=[r'Microsoft\VisualStudio\8.0\Setup\VS\ProductDir'], common_tools_var='VS80COMNTOOLS', - batch_file='vcvarsall.bat', - vc_product_dir_key=r'Setup\VC\ProductDir', - batch_file_dir_reg_relpath=None, - batch_file_dir_env_relpath=r'..\..\VC', - executable_path=r'..\Common7\IDE\devenv.com', + executable_path=r'Common7\IDE\devenv.com', + batch_file_path=r'Common7\Tools\vsvars32.bat', default_dirname='Microsoft Visual Studio 8', supported_arch=['x86', 'amd64'], ), @@ -254,15 +255,12 @@ SupportedVSList = [ # The batch file we look for is in the VC directory, # so the VCExpress.exe executable is up in ..\..\Common7\IDE. VisualStudio('8.0Exp', - hkey_root=r'Software\Microsoft\VCExpress\8.0', + vc_version='8.0', + sdk_version='6.0A', + hkeys=[r'Microsoft\VCExpress\8.0\Setup\VS\ProductDir'], common_tools_var='VS80COMNTOOLS', - batch_file='vcvarsall.bat', - vc_product_dir_key=r'Setup\VC\ProductDir', - batch_file_dir_reg_relpath=None, - batch_file_dir_env_relpath=r'..\..\VC', - # The batch file is in the VC directory, so - # so the devenv.com executable is next door in ..\IDE. - executable_path=r'..\Common7\IDE\VCExpress.exe', + executable_path=r'Common7\IDE\VCExpress.exe', + batch_file_path=r'Common7\Tools\vsvars32.bat', default_dirname='Microsoft Visual Studio 8', supported_arch=['x86'], ), @@ -271,13 +269,11 @@ SupportedVSList = [ # The batch file we look for is in the Common7\Tools directory, # so the devenv.com executable is next door in ..\IDE. VisualStudio('7.1', - hkey_root=r'Software\Microsoft\VisualStudio\7.1', + sdk_version='6.0', + hkeys=[r'Microsoft\VisualStudio\7.1\Setup\VS\ProductDir'], common_tools_var='VS71COMNTOOLS', - batch_file='vsvars32.bat', - vc_product_dir_key=r'Setup\VC\ProductDir', - batch_file_dir_reg_relpath=r'..\Common7\Tools', - batch_file_dir_env_relpath=None, - executable_path=r'..\IDE\devenv.com', + executable_path=r'IDE\devenv.com', + batch_file_path=r'Common7\Tools\vsvars32.bat', default_dirname='Microsoft Visual Studio .NET', supported_arch=['x86'], ), @@ -286,26 +282,23 @@ SupportedVSList = [ # The batch file we look for is in the Common7\Tools directory, # so the devenv.com executable is next door in ..\IDE. VisualStudio('7.0', - hkey_root=r'Software\Microsoft\VisualStudio\7.0', + sdk_version='2003R2', + hkeys=[r'Microsoft\VisualStudio\7.0\Setup\VS\ProductDir'], common_tools_var='VS70COMNTOOLS', - batch_file='vsvars32.bat', - vc_product_dir_key=r'Setup\VC\ProductDir', - batch_file_dir_reg_relpath=r'..\Common7\Tools', - batch_file_dir_env_relpath=None, - executable_path=r'..\IDE\devenv.com', + executable_path=r'IDE\devenv.com', + batch_file_path=r'Common7\Tools\vsvars32.bat', default_dirname='Microsoft Visual Studio .NET', supported_arch=['x86'], ), # Visual Studio 6.0 VisualStudio('6.0', - hkey_root=r'Software\Microsoft\VisualStudio\6.0', + sdk_version='2003R1', + hkeys=[r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual Studio\ProductDir', + 'use_dir'], common_tools_var='VS60COMNTOOLS', - batch_file='vcvars32.bat', - vc_product_dir_key='Setup\Microsoft Visual C++\ProductDir', - batch_file_dir_reg_relpath='Bin', - batch_file_dir_env_relpath=None, executable_path=r'Common\MSDev98\Bin\MSDEV.COM', + batch_file_path=r'Common7\Tools\vsvars32.bat', default_dirname='Microsoft Visual Studio', supported_arch=['x86'], ), @@ -323,7 +316,7 @@ for vs in SupportedVSList: # requested, and cache it. InstalledVSList = None -InstalledVSMap = None +InstalledVSMap = None def get_installed_visual_studios(): global InstalledVSList @@ -343,10 +336,14 @@ def reset_installed_visual_studios(): global InstalledVSList global InstalledVSMap InstalledVSList = None - InstalledVSMap = None + InstalledVSMap = None for vs in SupportedVSList: vs.reset() - + + # Need to clear installed VC's as well as they are used in finding + # installed VS's + SCons.Tool.MSCommon.vc.reset_installed_vcs() + # We may be asked to update multiple construction environments with # SDK information. When doing this, we check on-disk for whether @@ -380,15 +377,19 @@ def reset_installed_visual_studios(): # for variable, directory in env_tuple_list: # env.PrependENVPath(variable, directory) -def detect_msvs(): +def msvs_exists(): return (len(get_installed_visual_studios()) > 0) def get_vs_by_version(msvs): + global InstalledVSMap + global SupportedVSMap + if not SupportedVSMap.has_key(msvs): msg = "Visual Studio version %s is not supported" % repr(msvs) raise SCons.Errors.UserError, msg get_installed_visual_studios() vs = InstalledVSMap.get(msvs) + debug('InstalledVSMap:%s'%InstalledVSMap) # Some check like this would let us provide a useful error message # if they try to set a Visual Studio version that's not installed. # However, we also want to be able to run tests (like the unit diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 4c00ebc..910e6a1 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -550,6 +550,7 @@ def FindAllTools(tools, env): def tool_list(platform, env): + other_plat_tools=[] # XXX this logic about what tool to prefer on which platform # should be moved into either the platform files or # the tool files themselves. @@ -563,14 +564,15 @@ def tool_list(platform, env): assemblers = ['masm', 'nasm', 'gas', '386asm' ] fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran'] ars = ['mslib', 'ar', 'tlib'] + other_plat_tools=['msvs','midl'] elif str(platform) == 'os2': "prefer IBM tools on OS/2" - linkers = ['ilink', 'gnulink', 'mslink'] - c_compilers = ['icc', 'gcc', 'msvc', 'cc'] - cxx_compilers = ['icc', 'g++', 'msvc', 'c++'] - assemblers = ['nasm', 'masm', 'gas'] + linkers = ['ilink', 'gnulink', ]#'mslink'] + c_compilers = ['icc', 'gcc',]# 'msvc', 'cc'] + cxx_compilers = ['icc', 'g++',]# 'msvc', 'c++'] + assemblers = ['nasm',]# 'masm', 'gas'] fortran_compilers = ['ifl', 'g77'] - ars = ['ar', 'mslib'] + ars = ['ar',]# 'mslib'] elif str(platform) == 'irix': "prefer MIPSPro on IRIX" linkers = ['sgilink', 'gnulink'] @@ -650,14 +652,14 @@ def tool_list(platform, env): 'dvipdf', 'dvips', 'gs', 'jar', 'javac', 'javah', 'latex', 'lex', - 'm4', 'midl', 'msvs', + 'm4', #'midl', 'msvs', 'pdflatex', 'pdftex', 'Perforce', 'RCS', 'rmic', 'rpcgen', 'SCCS', # 'Subversion', 'swig', 'tar', 'tex', - 'yacc', 'zip', 'rpm', 'wix'], + 'yacc', 'zip', 'rpm', 'wix']+other_plat_tools, env) tools = ([linker, c_compiler, cxx_compiler, diff --git a/src/engine/SCons/Tool/linkloc.py b/src/engine/SCons/Tool/linkloc.py index 3aeb693..4ee0020 100644 --- a/src/engine/SCons/Tool/linkloc.py +++ b/src/engine/SCons/Tool/linkloc.py @@ -43,7 +43,7 @@ import SCons.Errors import SCons.Tool import SCons.Util -from SCons.Tool.MSCommon import detect_msvs, merge_default_version +from SCons.Tool.MSCommon import msvs_exists, merge_default_version from SCons.Tool.PharLapCommon import addPharLapPaths _re_linker_command = re.compile(r'(\s)@\s*([^\s]+)') @@ -100,7 +100,7 @@ def generate(env): addPharLapPaths(env) def exists(env): - if detect_msvs(): + if msvs_exists(): return env.Detect('linkloc') else: return 0 diff --git a/src/engine/SCons/Tool/midl.py b/src/engine/SCons/Tool/midl.py index 441f884..0ba940e 100644 --- a/src/engine/SCons/Tool/midl.py +++ b/src/engine/SCons/Tool/midl.py @@ -41,7 +41,7 @@ import SCons.Defaults import SCons.Scanner.IDL import SCons.Util -from MSCommon import detect_msvs +from MSCommon import msvs_exists def midl_emitter(target, source, env): """Produces a list of outputs from the MIDL compiler""" @@ -81,7 +81,7 @@ def generate(env): env['BUILDERS']['TypeLibrary'] = midl_builder def exists(env): - return detect_msvs() + return msvs_exists() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslib.py b/src/engine/SCons/Tool/mslib.py index d23f63b..9d0fcef 100644 --- a/src/engine/SCons/Tool/mslib.py +++ b/src/engine/SCons/Tool/mslib.py @@ -39,7 +39,7 @@ import SCons.Tool.msvs import SCons.Tool.msvc import SCons.Util -from MSCommon import detect_msvs, merge_default_version +from MSCommon import msvs_exists, merge_default_version def generate(env): """Add Builders and construction variables for lib to an Environment.""" @@ -55,7 +55,7 @@ def generate(env): env['LIBSUFFIX'] = '.lib' def exists(env): - return detect_msvs() + return msvs_exists() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index d2089d3..e2ff4ac 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -44,7 +44,7 @@ import SCons.Tool.msvc import SCons.Tool.msvs import SCons.Util -from MSCommon import merge_default_version, detect_msvs +from MSCommon import merge_default_version, msvs_exists def pdbGenerator(env, target, source, for_signature): try: @@ -256,7 +256,7 @@ def generate(env): env['LDMODULECOM'] = compositeLdmodAction def exists(env): - return detect_msvs() + return msvs_exists() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mssdk.py b/src/engine/SCons/Tool/mssdk.py index 652a0c2..6103f30 100644 --- a/src/engine/SCons/Tool/mssdk.py +++ b/src/engine/SCons/Tool/mssdk.py @@ -33,29 +33,15 @@ It will usually be imported through the generic SCons.Tool.Tool() selection method. """ -from SCons.Tool.MSCommon.sdk import detect_sdk, \ - set_default_sdk, \ - set_sdk_by_directory, \ - set_sdk_by_version +from MSCommon import mssdk_exists, \ + mssdk_setup_env def generate(env): """Add construction variables for an MS SDK to an Environment.""" - if env.has_key('MSSDK_DIR'): - set_sdk_by_directory(env, env.subst('$MSSDK_DIR')) - return - - if env.has_key('MSSDK_VERSION'): - set_sdk_by_version(env, env.subst('$MSSDK_VERSION')) - return - - if env.has_key('MSVS_VERSION'): - set_default_sdk(env, env['MSVS_VERSION']) - - #print "No MSVS_VERSION: this is likely to be a bug" - return + mssdk_setup_env(env) def exists(env): - return detect_sdk() + return mssdk_exists() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index e68f982..8976852 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -48,7 +48,7 @@ import SCons.Util import SCons.Warnings import SCons.Scanner.RC -from MSCommon import merge_default_version, detect_msvs +from MSCommon import msvc_exists, msvc_setup_env CSuffixes = ['.c', '.C'] CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++'] @@ -233,7 +233,7 @@ def generate(env): env['SHOBJSUFFIX'] = '$OBJSUFFIX' # Set-up ms tools paths for default version - merge_default_version(env) + msvc_setup_env(env) import mssdk mssdk.generate(env) @@ -251,7 +251,7 @@ def generate(env): env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root() def exists(env): - return detect_msvs() + return msvc_exists('cl') # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index 31dcdf1..0c33075 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -274,3 +274,15 @@ in the &cv-CPPPATH; construction variable when the &cv-RCINCFLAGS; variable is expanded. </summary> </cvar> + +<cvar name="MSVC_VERSION"> +<summary> +Sets the preferred version of Microsoft Visual C/C++ to use. + +If &v-MSVC_VERSION; is not set, +&SCons; will (by default) select the latest version +of Visual C/C++ installed on your system. +If the specified version isn't installed, +tool initialization will fail. +</summary> +</cvar> diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 2862f71..b0893da 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -49,7 +49,8 @@ import SCons.Script.SConscript import SCons.Util import SCons.Warnings -from MSCommon import detect_msvs, merge_default_version +from MSCommon import msvs_exists, merge_default_version +from SCons.Defaults import processDefines ############################################################################## # Below here are the classes and functions for generation of @@ -689,7 +690,7 @@ class _GenerateV7DSP(_DSPGenerator): # TODO(1.5) #preprocdefs = xmlify(';'.join(self.env.get('CPPDEFINES', []))) #includepath = xmlify(';'.join(self.env.get('CPPPATH', []))) - preprocdefs = xmlify(string.join(self.env.get('CPPDEFINES', []), ';')) + preprocdefs = xmlify(string.join(processDefines(self.env.get('CPPDEFINES', [])), ';')) includepath = xmlify(string.join(self.env.get('CPPPATH', []), ';')) if not env_has_buildtarget: @@ -1424,7 +1425,7 @@ def generate(env): env['SCONS_HOME'] = os.environ.get('SCONS_HOME') def exists(env): - return detect_msvs() + return msvs_exists() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvs.xml b/src/engine/SCons/Tool/msvs.xml index 821bbca..66441eb 100644 --- a/src/engine/SCons/Tool/msvs.xml +++ b/src/engine/SCons/Tool/msvs.xml @@ -491,10 +491,11 @@ external environment variable is left untouched. <cvar name="MSVS_VERSION"> <summary> -Sets the preferred version of MSVS to use. +Sets the preferred version of Microsoft Visual Studio to use. -SCons will (by default) select the latest version of MSVS -installed on your machine. +If &v-MSVS_VERSION; is not set, +&SCons; will (by default) select the latest version +of Visual Studio installed on your system. So, if you have version 6 and version 7 (MSVS .NET) installed, it will prefer version 7. You can override this by @@ -502,7 +503,8 @@ specifying the <envar>MSVS_VERSION</envar> variable in the Environment initialization, setting it to the appropriate version ('6.0' or '7.0', for example). -If the given version isn't installed, tool initialization will fail. +If the specified version isn't installed, +tool initialization will fail. </summary> </cvar> diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 1fb1e75..0c5379f 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -495,7 +495,7 @@ class DummyRegistry: mykey = 'HKEY_CURRENT_USER\\' + key if root == SCons.Util.HKEY_LOCAL_MACHINE: mykey = 'HKEY_LOCAL_MACHINE\\' + key - #print "Open Key",mykey + debug("Open Key:%s"%mykey) return self.root.key(mykey) def DummyOpenKeyEx(root, key): @@ -527,14 +527,15 @@ class msvsTestCase(unittest.TestCase): """This test case is run several times with different defaults. See its subclasses below.""" def setUp(self): + debug("THIS TYPE :%s"%self) global registry registry = self.registry from SCons.Tool.MSCommon.vs import reset_installed_visual_studios reset_installed_visual_studios() - def test_detect_msvs(self): - """Test the detect_msvs() function""" - r = detect_msvs() + def test_msvs_exists(self): + """Test the msvs_exists() function""" + r = msvs_exists() assert r == (self.number_of_versions > 0), r def test_get_default_version(self): @@ -544,9 +545,9 @@ class msvsTestCase(unittest.TestCase): env = DummyEnv() v1 = get_default_version(env) assert env['MSVS_VERSION'] == self.default_version, \ - (self.default_version, env['MSVS_VERSION']) + ("env['MSVS_VERSION'] != self.default_version",self.default_version, env['MSVS_VERSION']) assert env['MSVS']['VERSION'] == self.default_version, \ - (self.default_version, env['MSVS']['VERSION']) + ("env['MSVS']['VERSION'] != self.default_version",self.default_version, env['MSVS']['VERSION']) assert v1 == self.default_version, (self.default_version, v1) env = DummyEnv({'MSVS_VERSION':'7.0'}) @@ -615,8 +616,10 @@ class msvs6and7TestCase(msvsTestCase): highest_version = '7.0' number_of_versions = 2 install_locs = { - '6.0' : {'VSINSTALLDIR': 'C:\\VS6\\VC98', 'VCINSTALLDIR': 'C:\\VS6\\VC98\\Bin'}, - '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7\\Tools'}, + '6.0' : {'VSINSTALLDIR': 'C:\\VS6\\VC98', + 'VCINSTALLDIR': 'C:\\VS6\\VC98\\Bin'}, + '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7', + 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7\\Tools'}, '7.1' : {}, '8.0' : {}, '8.0Exp' : {}, @@ -631,7 +634,8 @@ class msvs7TestCase(msvsTestCase): number_of_versions = 1 install_locs = { '6.0' : {}, - '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7\\Tools'}, + '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7', + 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Common7\\Tools'}, '7.1' : {}, '8.0' : {}, '8.0Exp' : {}, @@ -647,7 +651,8 @@ class msvs71TestCase(msvsTestCase): install_locs = { '6.0' : {}, '7.0' : {}, - '7.1' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7\\Tools'}, + '7.1' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7', + 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Common7\\Tools'}, '8.0' : {}, '8.0Exp' : {}, } @@ -664,7 +669,8 @@ class msvs8ExpTestCase(msvsTestCase): # XXX: only one still not working '7.0' : {}, '7.1' : {}, '8.0' : {}, - '8.0Exp' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC'}, + '8.0Exp' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8', + 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC'}, } default_install_loc = install_locs['8.0Exp'] @@ -678,7 +684,8 @@ class msvs80TestCase(msvsTestCase): '6.0' : {}, '7.0' : {}, '7.1' : {}, - '8.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC'}, + '8.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8', + 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 8\\VC'}, '8.0Exp' : {}, } default_install_loc = install_locs['8.0'] @@ -705,10 +712,11 @@ if __name__ == "__main__": sys.stdout.write("NO RESULT for msvsTests.py: '%s' is not win32\n" % sys.platform) sys.exit(0) - SCons.Util.RegOpenKeyEx = DummyOpenKeyEx - SCons.Util.RegEnumKey = DummyEnumKey - SCons.Util.RegEnumValue = DummyEnumValue + SCons.Util.RegOpenKeyEx = DummyOpenKeyEx + SCons.Util.RegEnumKey = DummyEnumKey + SCons.Util.RegEnumValue = DummyEnumValue SCons.Util.RegQueryValueEx = DummyQueryValue + os.path.exists = DummyExists # make sure all files exist :-) os.path.isfile = DummyExists # make sure all files are files :-) os.path.isdir = DummyExists # make sure all dirs are dirs :-) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index ebdd1cd..23d75e1 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -675,11 +675,11 @@ try: can_read_reg = 1 hkey_mod = _winreg - RegOpenKeyEx = _winreg.OpenKeyEx - RegEnumKey = _winreg.EnumKey - RegEnumValue = _winreg.EnumValue + RegOpenKeyEx = _winreg.OpenKeyEx + RegEnumKey = _winreg.EnumKey + RegEnumValue = _winreg.EnumValue RegQueryValueEx = _winreg.QueryValueEx - RegError = _winreg.error + RegError = _winreg.error except ImportError: try: @@ -688,11 +688,11 @@ except ImportError: can_read_reg = 1 hkey_mod = win32con - RegOpenKeyEx = win32api.RegOpenKeyEx - RegEnumKey = win32api.RegEnumKey - RegEnumValue = win32api.RegEnumValue + RegOpenKeyEx = win32api.RegOpenKeyEx + RegEnumKey = win32api.RegEnumKey + RegEnumValue = win32api.RegEnumValue RegQueryValueEx = win32api.RegQueryValueEx - RegError = win32api.error + RegError = win32api.error except ImportError: class _NoError(Exception): @@ -700,10 +700,10 @@ except ImportError: RegError = _NoError if can_read_reg: - HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT + HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE - HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER - HKEY_USERS = hkey_mod.HKEY_USERS + HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER + HKEY_USERS = hkey_mod.HKEY_USERS def RegGetValue(root, key): """This utility function returns a value in the registry diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index bfc01b3..c783d1e 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -115,6 +115,12 @@ class StackSizeWarning(Warning): class TaskmasterNeedsExecuteWarning(FutureDeprecatedWarning): pass +class VisualCMissingWarning(Warning): + pass + +class VisualStudioMissingWarning(Warning): + pass + class FortranCxxMixWarning(LinkWarning): pass diff --git a/test/MSVS/vs-8.0-clean.py b/test/MSVS/vs-8.0-clean.py index f17c605..8bcc16e 100644 --- a/test/MSVS/vs-8.0-clean.py +++ b/test/MSVS/vs-8.0-clean.py @@ -45,7 +45,7 @@ expected_vcprojfile = TestSConsMSVS.expected_vcprojfile_8_0 test.write('SConstruct', """\ env=Environment(platform='win32', tools=['msvs'], MSVS_VERSION='8.0', - CPPDEFINES=['DEF1', 'DEF2'], + CPPDEFINES=['DEF1', 'DEF2',('DEF3','1234')], CPPPATH=['inc1', 'inc2']) testsrc = ['test1.cpp', 'test2.cpp'] |