From: bdbaddog Date: Tue, 21 Jul 2009 00:48:33 +0000 (+0000) Subject: In addition to changed merged below, commented out for platform os2 use of msvc,... X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=55307a7aadc171562bbca09d2d970fee5ffc8223;p=scons.git In addition to changed merged below, commented out for platform os2 use of msvc, mslib, mslink as they cause test/import.py to fail. I don't have an OS2 system to resolve the issues on. Merged revisions 4065,4067-4068,4071-4072,4074,4076,4085,4111,4163,4222 via svnmerge from http://scons.tigris.org/svn/scons/branches/vs_revamp ................ r4065 | stevenknight | 2009-03-02 16:48:05 -0800 (Mon, 02 Mar 2009) | 42 lines Copy over changes by hand from branches/core (I was working in a directory pointing to the wrong branch): ........ r4059 | stevenknight | 2009-03-02 06:54:13 -0800 (Mon, 02 Mar 2009) | 14 lines Initial prototypes of modules for architecture support (MSCommon/arch.py) and Visual C/C++ configuration distinct from (and in preference to) the Visual Studio configuration, incorporating configuration info and ideas from Jason Kenny's latest parts/tools/MSCommon work. This has a lot of cut-and-paste right now and does NOT actually work. In particular, there are no changes to the rest of the infrastructure to actually call any of this new stuff. I'm checking these in so I can sync on other systems for continued development. The ultimate goal is for much of the current MSCommon/vs.py module's logic to migrate to MSCommon/vc.py, since that's what we're actually interested in configuring. ........ r4058 | stevenknight | 2009-03-02 06:49:35 -0800 (Mon, 02 Mar 2009) | 2 lines Fix doc string. ........ r4056 | stevenknight | 2009-03-01 06:10:31 -0800 (Sun, 01 Mar 2009) | 4 lines Change the sanity_check file for 6.1 per Jason's update. Add an optional version string argument to detect_sdk(). Import directly from common, not SCons.Tool.MSCommon.common. ........ r4055 | stevenknight | 2009-02-28 05:29:03 -0800 (Sat, 28 Feb 2009) | 5 lines Minor common.py enhancements: Refactor is_win64() to cache its return value so we don't have to hit registry every time we want to know if the OS is 64-bit. Accept SCONS_MSCOMMON_DEBUG=- to mean print debug messages to stdout. ........ ................ r4067 | stevenknight | 2009-03-06 04:59:21 -0800 (Fri, 06 Mar 2009) | 4 lines Fix entries in batch_file_map, after a double-check with the original code. Use a host_architecture of None in the map to indicate the "default" entry if there isn't a specific .bat file for our current architecture. ................ r4068 | stevenknight | 2009-03-06 05:15:39 -0800 (Fri, 06 Mar 2009) | 2 lines Add include_subdir and lib_subdir data to the SDK definitions. ................ r4071 | stevenknight | 2009-03-10 07:42:53 -0700 (Tue, 10 Mar 2009) | 4 lines Capture basically working snapshot. src/engine/SCons/Tool/msvsTests.py and test/IDL/midl.py still fail, and code needs clean up. ................ r4072 | stevenknight | 2009-03-11 06:38:37 -0700 (Wed, 11 Mar 2009) | 2 lines Fix path to Common7\Tools. Find vs*.bat files. ................ r4074 | stevenknight | 2009-03-13 17:11:55 -0700 (Fri, 13 Mar 2009) | 3 lines Import SCons.Tool.MSCommon.vc so it works regardless of other sys.path manipulation. ................ r4076 | stevenknight | 2009-03-19 08:08:48 -0700 (Thu, 19 Mar 2009) | 7 lines Refactor SDK support: * New mssdk_exists() and mssdk_setup_env() methods as the primary public entry points. * Call internal sdk.*() utility functions that just return information (like the SDK structure) not handle the actual setting. * Give the VisualStudio definitions explicit settings for the SDK version. ................ r4085 | bdbaddog | 2009-04-05 14:30:46 -0700 (Sun, 05 Apr 2009) | 3 lines Fix "can't find module vc" issue when building on windows. ................ r4111 | stevenknight | 2009-04-19 07:47:47 -0700 (Sun, 19 Apr 2009) | 2 lines Doc updates for how MSVS_VERSION is used. ................ r4163 | bdbaddog | 2009-04-29 17:32:43 -0700 (Wed, 29 Apr 2009) | 4 lines Fix for bug 2405 Also refactored some logic from Defaults._defines() into Defaults.processDefines() which is then used by msvs.py ................ r4222 | bdbaddog | 2009-05-31 17:01:22 -0700 (Sun, 31 May 2009) | 8 lines Added definition of HOST_OS|ARCH TARGET_OS|ARCH (For win32 only right now) Migrated some logic to determine arch from Tools/MSCommon -> Platform/Win32.py Fixed lots of minor issues with string values for directories, architectures, and registry keys Switch to find VS installs by registry (was using VC install location previously) Added but commented out that HOST_{OS|ARCH} and TARGET_{OS|ARCH} will become reserved var names in Environment() Need to resolve issues that SCons is issuing messages when SCons itself sets these variables. ................ git-svn-id: http://scons.tigris.org/svn/scons/trunk@4296 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/QMTest/TestSConsMSVS.py b/QMTest/TestSConsMSVS.py index f26510ba..017a29fb 100644 --- a/QMTest/TestSConsMSVS.py +++ b/QMTest/TestSConsMSVS.py @@ -478,7 +478,7 @@ expected_vcprojfile_8_0 = """\ \t\t\t\tReBuildCommandLine="echo Starting SCons && "" -c "" -C "" -f SConstruct "Test.exe"" \t\t\t\tCleanCommandLine="echo Starting SCons && "" -c "" -C "" -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 9cc9923b..f6ce08a5 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 7f187263..2185d301 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 e4d6da30..eba86e4a 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 80d8516d..ff8b1164 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 a74df5a2..99f33226 100644 --- a/src/engine/SCons/Platform/__init__.xml +++ b/src/engine/SCons/Platform/__init__.xml @@ -83,6 +83,47 @@ else: + + + 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. + + + + + + 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. + + + + + + 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. + + + + + + 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. + + + + The prefix used for executable file names. diff --git a/src/engine/SCons/Platform/os2.py b/src/engine/SCons/Platform/os2.py index 41e8312c..aa348d46 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 1dc7f3cb..78822c61 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 a59bf15d..c883287d 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 00000000..2638b72a --- /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 35832466..f74d10cb 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 6791fd7c..d9f609cd 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 00000000..222c2847 --- /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 da22fa9e..8d5c66b7 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 4c00ebc9..910e6a1c 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 3aeb693f..4ee00206 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 441f8842..0ba940e9 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 d23f63bb..9d0fcef0 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 d2089d32..e2ff4ac0 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 652a0c2f..6103f30b 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 e68f9829..89768528 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 31dcdf16..0c330757 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. + + + +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. + + diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 2862f719..b0893da4 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 821bbcae..66441eba 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. -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 MSVS_VERSION 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. diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 1fb1e759..0c5379fe 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 ebdd1cd0..23d75e1e 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 bfc01b33..c783d1ed 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 f17c6051..8bcc16e3 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']