diff options
Diffstat (limited to 'src/engine/SCons/Tool')
-rw-r--r-- | src/engine/SCons/Tool/mslib.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/Tool/mslink.py | 49 | ||||
-rw-r--r-- | src/engine/SCons/Tool/mslink.xml | 38 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvc.py | 279 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvs.py | 426 | ||||
-rw-r--r-- | src/engine/SCons/Tool/msvsTests.py | 433 |
6 files changed, 915 insertions, 316 deletions
diff --git a/src/engine/SCons/Tool/mslib.py b/src/engine/SCons/Tool/mslib.py index 45712dc..ee4ee86 100644 --- a/src/engine/SCons/Tool/mslib.py +++ b/src/engine/SCons/Tool/mslib.py @@ -47,9 +47,9 @@ def generate(env): version = SCons.Tool.msvs.get_default_visualstudio_version(env) if env.has_key('MSVS_IGNORE_IDE_PATHS') and env['MSVS_IGNORE_IDE_PATHS']: - include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(version) + include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(env,version) else: - include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(version) + include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,version) # since other tools can set this, we just make sure that the # relevant stuff from MSVS is in there somewhere. @@ -68,7 +68,7 @@ def exists(env): v = SCons.Tool.msvs.get_visualstudio_versions() except (SCons.Util.RegError, SCons.Errors.InternalError): pass - + if not v: return env.Detect('lib') else: diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index e05530e..fe4e394 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -72,13 +72,13 @@ def win32ShlinkSources(target, source, env, for_signature): # Just treat it as a generic source file. listCmd.append(src) return listCmd - + def win32LibEmitter(target, source, env): SCons.Tool.msvc.validate_vars(env) - + dll = env.FindIxes(target, "SHLIBPREFIX", "SHLIBSUFFIX") no_import_lib = env.get('no_import_lib', 0) - + if not dll: raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX") @@ -86,21 +86,28 @@ def win32LibEmitter(target, source, env): not env.FindIxes(source, "WIN32DEFPREFIX", "WIN32DEFSUFFIX"): # append a def file to the list of sources - source.append(env.ReplaceIxes(dll, + source.append(env.ReplaceIxes(dll, "SHLIBPREFIX", "SHLIBSUFFIX", "WIN32DEFPREFIX", "WIN32DEFSUFFIX")) + version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSION', '6.0')) + if version_num >= 8.0 and env.get('WIN32_INSERT_MANIFEST', 0): + # MSVC 8 automatically generates .manifest files that must be installed + target.append(env.ReplaceIxes(dll, + "SHLIBPREFIX", "SHLIBSUFFIX", + "WIN32SHLIBMANIFESTPREFIX", "WIN32SHLIBMANIFESTSUFFIX")) + if env.has_key('PDB') and env['PDB']: target.append(env['PDB']) if not no_import_lib and \ not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"): # Append an import library to the list of targets. - target.append(env.ReplaceIxes(dll, + target.append(env.ReplaceIxes(dll, "SHLIBPREFIX", "SHLIBSUFFIX", "LIBPREFIX", "LIBSUFFIX")) # and .exp file is created if there are exports from a DLL - target.append(env.ReplaceIxes(dll, + target.append(env.ReplaceIxes(dll, "SHLIBPREFIX", "SHLIBSUFFIX", "WIN32EXPPREFIX", "WIN32EXPSUFFIX")) @@ -108,10 +115,21 @@ def win32LibEmitter(target, source, env): def prog_emitter(target, source, env): SCons.Tool.msvc.validate_vars(env) - + + exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX") + if not exe: + raise SCons.Errors.UserError, "An executable should have exactly one target with the suffix: %s" % env.subst("$PROGSUFFIX") + + version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSION', '6.0')) + if version_num >= 8.0 and env.get('WIN32_INSERT_MANIFEST', 0): + # MSVC 8 automatically generates .manifest files that have to be installed + target.append(env.ReplaceIxes(exe, + "PROGPREFIX", "PROGSUFFIX", + "WIN32PROGMANIFESTPREFIX", "WIN32PROGMANIFESTSUFFIX")) + if env.has_key('PDB') and env['PDB']: target.append(env['PDB']) - + return (target,source) def RegServerFunc(target, source, env): @@ -133,7 +151,7 @@ def generate(env): """Add Builders and construction variables for ar to an Environment.""" SCons.Tool.createSharedLibBuilder(env) SCons.Tool.createProgBuilder(env) - + env['SHLINK'] = '$LINK' env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll') env['_SHLINK_TARGETS'] = win32ShlinkTargets @@ -157,6 +175,11 @@ def generate(env): env['WIN32EXPPREFIX'] = '' env['WIN32EXPSUFFIX'] = '.exp' + env['WIN32SHLIBMANIFESTPREFIX'] = '' + env['WIN32SHLIBMANIFESTSUFFIX'] = env['SHLIBSUFFIX'] + '.manifest' + env['WIN32PROGMANIFESTPREFIX'] = '' + env['WIN32PROGMANIFESTSUFFIX'] = env['PROGSUFFIX'] + '.manifest' + env['REGSVRACTION'] = regServerCheck env['REGSVR'] = os.path.join(SCons.Platform.win32.get_system_root(),'System32','regsvr32') env['REGSVRFLAGS'] = '/s ' @@ -166,9 +189,9 @@ def generate(env): version = SCons.Tool.msvs.get_default_visualstudio_version(env) if env.has_key('MSVS_IGNORE_IDE_PATHS') and env['MSVS_IGNORE_IDE_PATHS']: - include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(version) + include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(env,version) else: - include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(version) + include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,version) # since other tools can set these, we just make sure that the # relevant stuff from MSVS is in there somewhere. @@ -183,8 +206,8 @@ def generate(env): # setting them the same means that LoadableModule works everywhere. SCons.Tool.createLoadableModuleBuilder(env) env['LDMODULE'] = '$SHLINK' - env['LDMODULEPREFIX'] = '$SHLIBPREFIX' - env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' + env['LDMODULEPREFIX'] = '$SHLIBPREFIX' + env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' env['LDMODULEFLAGS'] = '$SHLINKFLAGS' # We can't use '$SHLINKCOM' here because that will stringify the # action list on expansion, and will then try to execute expanded diff --git a/src/engine/SCons/Tool/mslink.xml b/src/engine/SCons/Tool/mslink.xml index 2b901c6..6fac54e 100644 --- a/src/engine/SCons/Tool/mslink.xml +++ b/src/engine/SCons/Tool/mslink.xml @@ -86,6 +86,16 @@ The default is 0 (do not build a .def file). </summary> </cvar> +<cvar name="WIN32_INSERT_MANIFEST"> +<summary> +When this is set to true, +&scons; +will be aware of the +<filename>.manifest</filename> +files generated by Microsoft Visua C/C++ 8. +</summary> +</cvar> + <cvar name="WIN32DEFPREFIX"> <summary> The prefix used for WIN32 .def file names. @@ -109,3 +119,31 @@ XXX The prefix used for WIN32 .def file names. XXX The suffix used for WIN32 .def file names. </summary> </cvar> + +<cvar name="WIN32PROGMANIFESTPREFIX"> +<summary> +The prefix used for executable program <filename>.manifest</filename> files +generated by Microsoft Visual C/C++ .NET 2005. +</summary> +</cvar> + +<cvar name="WIN32PROGMANIFESTSUFFIX"> +<summary> +The suffix used for executable program <filename>.manifest</filename> files +generated by Microsoft Visual C/C++ .NET 2005. +</summary> +</cvar> + +<cvar name="WIN32SHLIBMANIFESTPREFIX"> +<summary> +The prefix used for shared library <filename>.manifest</filename> files +generated by Microsoft Visual C/C++ .NET 2005. +</summary> +</cvar> + +<cvar name="WIN32SHLIBMANIFESTSUFFIX"> +<summary> +The suffix used for shared library <filename>.manifest</filename> files +generated by Microsoft Visual C/C++ .NET 2005. +</summary> +</cvar> diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index d6ecbfa..bc50eaa 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -49,8 +49,9 @@ import SCons.Warnings CSuffixes = ['.c', '.C'] CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++'] -def _parse_msvc7_overrides(version): - """ Parse any overridden defaults for MSVS directory locations in MSVS .NET. """ +def _parse_msvc7_overrides(version,platform): + """ Parse any overridden defaults for MSVS directory locations + in MSVS .NET. """ # First, we get the shell folder for this user: if not SCons.Util.can_read_reg: @@ -62,14 +63,16 @@ def _parse_msvc7_overrides(version): r'Software\Microsoft\Windows\CurrentVersion' +\ r'\Explorer\Shell Folders\Local AppData') except SCons.Util.RegError: - raise SCons.Errors.InternalError, "The Local AppData directory was not found in the registry." + raise SCons.Errors.InternalError, \ + "The Local AppData directory was not found in the registry." comps = comps + '\\Microsoft\\VisualStudio\\' + version + '\\VCComponents.dat' dirs = {} if os.path.exists(comps): # now we parse the directories from this file, if it exists. - # We only look for entries after: [VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories], + # We only look for entries after: + # [VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories], # since this file could contain a number of things... lines = None try: @@ -85,11 +88,12 @@ def _parse_msvc7_overrides(version): lines = codecs.open(comps, 'r', 'utf8').readlines() if lines is None: lines = open(comps, 'r').readlines() - + if 'x86' == platform: platform = 'Win32' + found = 0 for line in lines: line.strip() - if line.find(r'[VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories]') >= 0: + if line.find(r'[VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories]'%platform) >= 0: found = 1 elif line == '' or line[:1] == '[': found = 0 @@ -103,9 +107,12 @@ def _parse_msvc7_overrides(version): else: # since the file didn't exist, we have only the defaults in # the registry to work with. + + if 'x86' == platform: platform = 'Win32' + try: K = 'SOFTWARE\\Microsoft\\VisualStudio\\' + version - K = K + r'\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories' + K = K + r'\VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories'%platform k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,K) i = 0 while 1: @@ -121,6 +128,115 @@ def _parse_msvc7_overrides(version): raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry." return dirs +def _parse_msvc8_overrides(version,platform,suite): + """ Parse any overridden defaults for MSVC directory locations + in MSVC 2005. """ + + # In VS8 the user can change the location of the settings file that + # contains the include, lib and binary paths. Try to get the location + # from registry + if not SCons.Util.can_read_reg: + raise SCons.Errors.InternalError, "No Windows registry module was found" + + s = '' + if suite == 'EXPRESS': + s = '\\VCExpress\\' + + # ToDo: add registry key strings for the other versions of visual + # studio 2005. + settings_path = "" + try: + (settings_path, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER, + r'Software\Microsoft' + s + version +\ + r'\Profile\AutoSaveFile') + settings_path = settings_path.upper() + except SCons.Util.RegError: + raise SCons.Errors.InternalError, \ + "The VS8 settings file location was not found in the registry." + + # Look for potential environment variables in the settings path + if settings_path.find('%VSSPV_VISUALSTUDIO_DIR%') >= 0: + # First replace a special variable named %vsspv_visualstudio_dir% + # that is not found in the OSs environment variables... + try: + (value, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER, + r'Software\Microsoft' + s + version +\ + r'\VisualStudioLocation') + settings_path = settings_path.replace('%VSSPV_VISUALSTUDIO_DIR%', value) + except SCons.Util.RegError: + raise SCons.Errors.InternalError, "The VS8 settings file location was not found in the registry." + + if settings_path.find('%') >= 0: + # Collect global environment variables + env_vars = {} + + # Read all the global environment variables of the current user + k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_CURRENT_USER, r'Environment') + i = 0 + while 1: + try: + (key,val,t) = SCons.Util.RegEnumValue(k,i) + env_vars[key.upper()] = val.upper() + i = i + 1 + except SCons.Util.RegError: + break + + # And some more variables that are not found in the registry + env_vars['USERPROFILE'] = os.getenv('USERPROFILE') + env_vars['SystemDrive'] = os.getenv('SystemDrive') + + found_var = 1 + while found_var: + found_var = 0 + for env_var in env_vars: + if settings_path.find(r'%' + env_var + r'%') >= 0: + settings_path = settings_path.replace(r'%' + env_var + r'%', env_vars[env_var]) + found_var = 1 + + dirs = {} + + if os.path.exists(settings_path): + # now we parse the directories from this file, if it exists. + import xml.dom.minidom + doc = xml.dom.minidom.parse(settings_path) + user_settings = doc.getElementsByTagName('UserSettings')[0] + tool_options = user_settings.getElementsByTagName('ToolsOptions')[0] + tool_options_categories = tool_options.getElementsByTagName('ToolsOptionsCategory') + for category in tool_options_categories: + category_name = category.attributes.get('name') + if category_name is not None and category_name.value == 'Projects': + subcategories = category.getElementsByTagName('ToolsOptionsSubCategory') + for subcategory in subcategories: + subcategory_name = subcategory.attributes.get('name') + if subcategory_name is not None and subcategory_name.value == 'VCDirectories': + properties = subcategory.getElementsByTagName('PropertyValue') + for property in properties: + property_name = property.attributes.get('name') + if property_name is None: + continue + elif property_name.value == 'IncludeDirectories': + include_dirs = property.childNodes[0].data + # ToDo: Support for other destinations than Win32 + include_dirs = include_dirs.replace('Win32|', '') + dirs['INCLUDE'] = include_dirs + elif property_name.value == 'LibraryDirectories': + lib_dirs = property.childNodes[0].data.replace('Win32|', '') + # ToDo: Support for other destinations than Win32 + lib_dirs = lib_dirs.replace('Win32|', '') + dirs['LIBRARY'] = lib_dirs + elif property_name.value == 'ExecutableDirectories': + path_dirs = property.childNodes[0].data.replace('Win32|', '') + # ToDo: Support for other destinations than Win32 + path_dirs = path_dirs.replace('Win32|', '') + dirs['PATH'] = path_dirs + + dirs['VCINSTALLDIR'] = os.getenv('VCInstallDir') + dirs['VSINSTALLDIR'] = os.getenv('VSInstallDir') + else: + # There are no default directories in the registry for VS8 Express :( + raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry." + return dirs + def _get_msvc7_path(path, version, platform): """ Get Visual Studio directories from version 7 (MSVS .NET) @@ -129,12 +245,13 @@ def _get_msvc7_path(path, version, platform): # first, look for a customization of the default values in the # registry: These are sometimes stored in the Local Settings area # for Visual Studio, in a file, so we have to parse it. - dirs = _parse_msvc7_overrides(version) + dirs = _parse_msvc7_overrides(version,platform) if dirs.has_key(path): p = dirs[path] else: - raise SCons.Errors.InternalError, "Unable to retrieve the %s path from MS VC++."%path + raise SCons.Errors.InternalError, \ + "Unable to retrieve the %s path from MS VC++."%path # collect some useful information for later expansions... paths = SCons.Tool.msvs.get_msvs_install_dirs(version) @@ -160,7 +277,47 @@ def _get_msvc7_path(path, version, platform): return string.join(rv,os.pathsep) -def get_msvc_path (path, version, platform='x86'): +def _get_msvc8_path(path, version, platform, suite): + """ + Get Visual Studio directories from version 8 (MSVS 2005) + (it has a different registry structure than versions before it) + """ + # first, look for a customization of the default values in the + # registry: These are sometimes stored in the Local Settings area + # for Visual Studio, in a file, so we have to parse it. + dirs = _parse_msvc8_overrides(version, platform, suite) + + if dirs.has_key(path): + p = dirs[path] + else: + raise SCons.Errors.InternalError, \ + "Unable to retrieve the %s path from MS VC++."%path + + # collect some useful information for later expansions... + paths = SCons.Tool.msvs.get_msvs_install_dirs(version) + + # expand the directory path variables that we support. If there + # is a variable we don't support, then replace that entry with + # "---Unknown Location VSInstallDir---" or something similar, to clue + # people in that we didn't find something, and so env expansion doesn't + # do weird things with the $(xxx)'s + s = re.compile('\$\(([a-zA-Z0-9_]+?)\)') + + def repl(match, paths=paths): + key = string.upper(match.group(1)) + if paths.has_key(key): + return paths[key] + else: + return '---Unknown Location %s---' % match.group() + + rv = [] + for entry in p.split(os.pathsep): + entry = s.sub(repl,entry).rstrip('\n\r') + rv.append(entry) + + return string.join(rv,os.pathsep) + +def get_msvc_path(env, path, version): """ Get a list of visualstudio directories (include, lib or path). Return a string delimited by ';'. An exception will be raised if unable to @@ -177,13 +334,22 @@ def get_msvc_path (path, version, platform='x86'): if path=='LIB': path= 'LIBRARY' - if float(version) >= 7.0: + version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) + if version_num >= 8.0: + platform = env.get('MSVS8_PLATFORM', 'x86') + suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) + else: + platform = 'x86' + + if version_num >= 8.0: + return _get_msvc8_path(path, version, platform, suite) + elif version_num >= 7.0: return _get_msvc7_path(path, version, platform) path = string.upper(path + ' Dirs') K = ('Software\\Microsoft\\Devstudio\\%s\\' + - 'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \ - (version,platform) + 'Build System\\Components\\Platforms\\Win32 (x86)\\Directories') % \ + (version) for base in (SCons.Util.HKEY_CURRENT_USER, SCons.Util.HKEY_LOCAL_MACHINE): try: @@ -245,7 +411,7 @@ def _get_msvc6_default_paths(version, use_mfc_dirs): exe_path = r'%s\tools\%s;%s\MSDev98\bin;%s\tools;%s\bin' % (MVSCommondir, osdir, MVSCommondir, MVSCommondir, MVSVCdir) return (include_path, lib_path, exe_path) -def _get_msvc7_default_paths(version, use_mfc_dirs): +def _get_msvc7_default_paths(env, version, use_mfc_dirs): """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those three environment variables that should be set in order to execute the MSVC .NET tools properly, if the information wasn't available @@ -293,7 +459,61 @@ def _get_msvc7_default_paths(version, use_mfc_dirs): return (include_path, lib_path, exe_path) -def get_msvc_paths(version=None, use_mfc_dirs=0): +def _get_msvc8_default_paths(env, version, suite, use_mfc_dirs): + """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those + three environment variables that should be set in order to execute + the MSVC 8 tools properly, if the information wasn't available + from the registry.""" + + MVSdir = None + paths = {} + exe_path = '' + lib_path = '' + include_path = '' + try: + paths = SCons.Tool.msvs.get_msvs_install_dirs(version) + MVSdir = paths['VSINSTALLDIR'] + except (KeyError, SCons.Util.RegError, SCons.Errors.InternalError): + if os.environ.has_key('VSCOMNTOOLS'): + MVSdir = os.path.normpath(os.path.join(os.environ['VSCOMNTOOLS'],'..','..')) + else: + # last resort -- default install location + MVSdir = os.getenv('ProgramFiles') + r'\Microsoft Visual Studio 8' + + if MVSdir: + if SCons.Util.can_read_reg and paths.has_key('VCINSTALLDIR'): + MVSVCdir = paths['VCINSTALLDIR'] + else: + MVSVCdir = os.path.join(MVSdir,'VC') + + MVSCommondir = r'%s\Common7' % MVSdir + include_path = r'%s\include' % (MVSVCdir) + lib_path = r'%s\lib' % (MVSVCdir) + exe_path = r'%s\IDE;%s\bin;%s\Tools;%s\Tools\bin' % (MVSCommondir,MVSVCdir, MVSCommondir, MVSCommondir) + + if paths.has_key('PLATFORMSDKDIR'): + PlatformSdkDir = paths['PLATFORMSDKDIR'] + include_path = include_path + r';%sInclude' % PlatformSdkDir + lib_path = lib_path + r';%s\lib' % PlatformSdkDir + if use_mfc_dirs: + include_path = include_path + r';%sInclude\mfc;%sInclude\atl' % (PlatformSdkDir, PlatformSdkDir) + lib_path = lib_path + r';%s\lib' % paths['PLATFORMSDKDIR'] + + envvar = 'include' + SCons.Util.get_environment_var(envvar) + include_path = include_path + envvar + + if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKSDKDIR'): + include_path = include_path + r';%s\include'%paths['FRAMEWORKSDKDIR'] + lib_path = lib_path + r';%s\lib'%paths['FRAMEWORKSDKDIR'] + exe_path = exe_path + r';%s\bin'%paths['FRAMEWORKSDKDIR'] + + if SCons.Util.can_read_reg and paths.has_key('FRAMEWORKDIR') and paths.has_key('FRAMEWORKVERSION'): + exe_path = exe_path + r';%s\%s'%(paths['FRAMEWORKDIR'],paths['FRAMEWORKVERSION']) + + return (include_path, lib_path, exe_path) + +def get_msvc_paths(env, version=None, use_mfc_dirs=0): """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those three environment variables that should be set in order to execute the MSVC tools properly.""" @@ -313,29 +533,33 @@ def get_msvc_paths(version=None, use_mfc_dirs=0): # Therefore, we'll see if we can get the path to the MSDev # base installation from the registry and deduce the default # directories. - if float(version) >= 7.0: - defpaths = _get_msvc7_default_paths(version, use_mfc_dirs) + version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) + if version_num >= 8.0: + suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) + defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs) + elif version_num >= 7.0: + defpaths = _get_msvc7_default_paths(env, version, use_mfc_dirs) else: defpaths = _get_msvc6_default_paths(version, use_mfc_dirs) try: - include_path = get_msvc_path("include", version) + include_path = get_msvc_path(env, "include", version) except (SCons.Util.RegError, SCons.Errors.InternalError): include_path = defpaths[0] try: - lib_path = get_msvc_path("lib", version) + lib_path = get_msvc_path(env, "lib", version) except (SCons.Util.RegError, SCons.Errors.InternalError): lib_path = defpaths[1] try: - exe_path = get_msvc_path("path", version) + exe_path = get_msvc_path(env, "path", version) except (SCons.Util.RegError, SCons.Errors.InternalError): exe_path = defpaths[2] return (include_path, lib_path, exe_path) -def get_msvc_default_paths(version=None, use_mfc_dirs=0): +def get_msvc_default_paths(env, version=None, use_mfc_dirs=0): """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values of those three environment variables that should be set in order to execute the MSVC tools properly. This will only return the default @@ -355,8 +579,12 @@ def get_msvc_default_paths(version=None, use_mfc_dirs=0): except: pass - if float(version) >= 7.0: - return _get_msvc7_default_paths(version, use_mfc_dirs) + version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) + if version_num >= 8.0: + suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) + defpaths = _get_msvc8_default_paths(env, version, suite, use_mfc_dirs) + elif version_num >= 7.0: + return _get_msvc7_default_paths(env, version, use_mfc_dirs) else: return _get_msvc6_default_paths(version, use_mfc_dirs) @@ -468,13 +696,16 @@ def generate(env): try: version = SCons.Tool.msvs.get_default_visualstudio_version(env) + version_num, suite = SCons.Tool.msvs.msvs_parse_version(version) + if version_num == 8.0: + suite = SCons.Tool.msvs.get_default_visualstudio8_suite(env) use_mfc_dirs = env.get('MSVS_USE_MFC_DIRS', 0) if env.get('MSVS_IGNORE_IDE_PATHS', 0): _get_paths = get_msvc_default_paths else: _get_paths = get_msvc_paths - include_path, lib_path, exe_path = _get_paths(version, use_mfc_dirs) + include_path, lib_path, exe_path = _get_paths(env, version, use_mfc_dirs) # since other tools can set these, we just make sure that the # relevant stuff from MSVS is in there somewhere. diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index c2bd20e..6747d54 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -82,6 +82,17 @@ def _generateGUID(slnfile, name): solution = "{" + solution[:8] + "-" + solution[8:12] + "-" + solution[12:16] + "-" + solution[16:20] + "-" + solution[20:32] + "}" return solution +version_re = re.compile(r'(\d+\.\d+)(.*)') + +def msvs_parse_version(s): + """ + Split a Visual Studio version, which may in fact be something like + '7.0Exp', into is version number (returned as a float) and trailing + "suite" portion. + """ + num, suite = version_re.match(s).groups() + return float(num), suite + # This is how we re-invoke SCons from inside MSVS Project files. # The problem is that we might have been invoked as either scons.bat # or scons.py. If we were invoked directly as scons.py, then we could @@ -92,10 +103,13 @@ def _generateGUID(slnfile, name): # which works regardless of how we were invoked. def getExecScriptMain(env, xml=None): scons_home = env.get('SCONS_HOME') - if scons_home: + if not scons_home and os.environ.has_key('SCONS_LIB_DIR'): + scons_home = os.environ['SCONS_LIB_DIR'] + if scons_home: exec_script_main = "from os.path import join; import sys; sys.path = [ r'%s' ] + sys.path; import SCons.Script; SCons.Script.main()" % scons_home else: - exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" + version = SCons.__version__ + exec_script_main = "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-%(version)s'), join(sys.prefix, 'scons-%(version)s'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons') ] + sys.path; import SCons.Script; SCons.Script.main()" % locals() if xml: exec_script_main = xmlify(exec_script_main) return exec_script_main @@ -140,7 +154,7 @@ def makeHierarchy(sources): dict[path[-1]] = file #else: # print 'Warning: failed to decompose path for '+str(file) - return hierarchy + return hierarchy class _DSPGenerator: """ Base class for DSP generators """ @@ -153,10 +167,13 @@ class _DSPGenerator: 'misc'] def __init__(self, dspfile, source, env): - if SCons.Util.is_String(dspfile): - self.dspfile = os.path.abspath(dspfile) + self.dspfile = str(dspfile) + try: + get_abspath = dspfile.get_abspath + except AttributeError: + self.dspabs = os.path.abspath(dspfile) else: - self.dspfile = dspfile.get_abspath() + self.dspabs = get_abspath() if not env.has_key('variant'): raise SCons.Errors.InternalError, \ @@ -213,6 +230,8 @@ class _DSPGenerator: self.sconscript = env['MSVSSCONSCRIPT'] + cmdargs = env.get('cmdargs', '') + self.env = env if self.env.has_key('name'): @@ -237,7 +256,7 @@ class _DSPGenerator: if env.has_key('nokeep') and env['variant'] != 0: self.nokeep = 1 - if self.nokeep == 0 and os.path.exists(self.dspfile): + if self.nokeep == 0 and os.path.exists(self.dspabs): self.Parse() for t in zip(sourcenames,self.srcargs): @@ -253,10 +272,11 @@ class _DSPGenerator: for n in sourcenames: self.sources[n].sort(lambda a, b: cmp(a.lower(), b.lower())) - def AddConfig(variant, buildtarget, outdir): + def AddConfig(variant, buildtarget, outdir, cmdargs): config = Config() config.buildtarget = buildtarget config.outdir = outdir + config.cmdargs = cmdargs match = re.match('(.*)\|(.*)', variant) if match: @@ -264,13 +284,13 @@ class _DSPGenerator: config.platform = match.group(2) else: config.variant = variant - config.platform = 'Win32'; + config.platform = 'Win32' self.configs[variant] = config print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'" for i in range(len(variants)): - AddConfig(variants[i], buildtarget[i], outdir[i]) + AddConfig(variants[i], buildtarget[i], outdir[i],cmdargs) self.platforms = [] for key in self.configs.keys(): @@ -355,7 +375,7 @@ class _GenerateV6DSP(_DSPGenerator): self.file.write('# PROP %sOutput_Dir "%s"\n' '# PROP %sIntermediate_Dir "%s"\n' % (base,outdir,base,outdir)) cmd = 'echo Starting SCons && ' + self.env.subst('$MSVSBUILDCOM', 1) - self.file.write('# PROP %sCmd_Line "%s"\n' + self.file.write('# PROP %sCmd_Line "%s"\n' '# PROP %sRebuild_Opt "-c && %s"\n' '# PROP %sTarget_File "%s"\n' '# PROP %sBsc_Name ""\n' @@ -422,7 +442,7 @@ class _GenerateV6DSP(_DSPGenerator): def Parse(self): try: - dspfile = open(self.dspfile,'r') + dspfile = open(self.dspabs,'r') except IOError: return # doesn't exist yet, so can't add anything to configs. @@ -470,9 +490,9 @@ class _GenerateV6DSP(_DSPGenerator): def Build(self): try: - self.file = open(self.dspfile,'w') + self.file = open(self.dspabs,'w') except IOError, detail: - raise SCons.Errors.InternalError, 'Unable to open "' + self.dspfile + '" for writing:' + str(detail) + raise SCons.Errors.InternalError, 'Unable to open "' + self.dspabs + '" for writing:' + str(detail) else: self.PrintHeader() self.PrintProject() @@ -490,7 +510,7 @@ V7DSPHeader = """\ V7DSPConfiguration = """\ \t\t<Configuration -\t\t\tName="%(variant)s|Win32" +\t\t\tName="%(variant)s|%(platform)s" \t\t\tOutputDirectory="%(outdir)s" \t\t\tIntermediateDirectory="%(outdir)s" \t\t\tConfigurationType="0" @@ -505,15 +525,57 @@ V7DSPConfiguration = """\ \t\t</Configuration> """ +V8DSPHeader = """\ +<?xml version="1.0" encoding="%(encoding)s"?> +<VisualStudioProject +\tProjectType="Visual C++" +\tVersion="%(versionstr)s" +\tName="%(name)s" +%(scc_attrs)s +\tRootNamespace="%(name)s" +\tKeyword="MakeFileProj"> +""" + +V8DSPConfiguration = """\ +\t\t<Configuration +\t\t\tName="%(variant)s|Win32" +\t\t\tConfigurationType="0" +\t\t\tUseOfMFC="0" +\t\t\tATLMinimizesCRunTimeLibraryUsage="false" +\t\t\t> +\t\t\t<Tool +\t\t\t\tName="VCNMakeTool" +\t\t\t\tBuildCommandLine="%(buildcmd)s" +\t\t\t\tReBuildCommandLine="%(rebuildcmd)s" +\t\t\t\tCleanCommandLine="%(cleancmd)s" +\t\t\t\tOutput="%(buildtarget)s" +\t\t\t\tPreprocessorDefinitions="" +\t\t\t\tIncludeSearchPath="" +\t\t\t\tForcedIncludes="" +\t\t\t\tAssemblySearchPath="" +\t\t\t\tForcedUsingAssemblies="" +\t\t\t\tCompileAsManaged="" +\t\t\t/> +\t\t</Configuration> +""" class _GenerateV7DSP(_DSPGenerator): """Generates a Project file for MSVS .NET""" def __init__(self, dspfile, source, env): _DSPGenerator.__init__(self, dspfile, source, env) - self.version = float(env['MSVS_VERSION']) - self.versionstr = '7.00' - if self.version >= 7.1: - self.versionstr = '7.10' + self.version = env['MSVS_VERSION'] + self.version_num, self.suite = msvs_parse_version(self.version) + if self.version_num >= 8.0: + self.versionstr = '8.00' + self.dspheader = V8DSPHeader + self.dspconfiguration = V8DSPConfiguration + else: + if self.version_num >= 7.1: + self.versionstr = '7.10' + else: + self.versionstr = '7.00' + self.dspheader = V7DSPHeader + self.dspconfiguration = V7DSPConfiguration self.file = None def PrintHeader(self): @@ -526,6 +588,8 @@ class _GenerateV7DSP(_DSPGenerator): scc_aux_path = env.get('MSVS_SCC_AUX_PATH', '') scc_local_path = env.get('MSVS_SCC_LOCAL_PATH', '') project_guid = env.get('MSVS_PROJECT_GUID', '') + if self.version_num >= 8.0 and not project_guid: + project_guid = _generateGUID(self.dspfile, '') if scc_provider != '': scc_attrs = ('\tProjectGUID="%s"\n' '\tSccProjectName="%s"\n' @@ -537,7 +601,7 @@ class _GenerateV7DSP(_DSPGenerator): '\tSccProjectName="%s"\n' '\tSccLocalPath="%s"' % (project_guid, scc_project_name, scc_local_path)) - self.file.write(V7DSPHeader % locals()) + self.file.write(self.dspheader % locals()) self.file.write('\t<Platforms>\n') for platform in self.platforms: @@ -546,6 +610,10 @@ class _GenerateV7DSP(_DSPGenerator): '\t\t\tName="%s"/>\n' % platform) self.file.write('\t</Platforms>\n') + if self.version_num >= 8.0: + self.file.write('\t<ToolFiles>\n' + '\t</ToolFiles>\n') + def PrintProject(self): self.file.write('\t<Configurations>\n') @@ -556,25 +624,30 @@ class _GenerateV7DSP(_DSPGenerator): platform = self.configs[kind].platform outdir = self.configs[kind].outdir buildtarget = self.configs[kind].buildtarget + cmdargs = self.configs[kind].cmdargs env_has_buildtarget = self.env.has_key('MSVSBUILDTARGET') if not env_has_buildtarget: self.env['MSVSBUILDTARGET'] = buildtarget starting = 'echo Starting SCons && ' - buildcmd = xmlify(starting + self.env.subst('$MSVSBUILDCOM', 1)) - rebuildcmd = xmlify(starting + self.env.subst('$MSVSREBUILDCOM', 1)) - cleancmd = xmlify(starting + self.env.subst('$MSVSCLEANCOM', 1)) + if cmdargs: + cmdargs = ' ' + cmdargs + else: + cmdargs = '' + buildcmd = xmlify(starting + self.env.subst('$MSVSBUILDCOM', 1) + cmdargs) + rebuildcmd = xmlify(starting + self.env.subst('$MSVSREBUILDCOM', 1) + cmdargs) + cleancmd = xmlify(starting + self.env.subst('$MSVSCLEANCOM', 1) + cmdargs) if not env_has_buildtarget: del self.env['MSVSBUILDTARGET'] - self.file.write(V7DSPConfiguration % locals()) + self.file.write(self.dspconfiguration % locals()) self.file.write('\t</Configurations>\n') - if self.version >= 7.1: - self.file.write('\t<References>\n' + if self.version_num >= 7.1: + self.file.write('\t<References>\n' '\t</References>\n') self.PrintSourceFiles() @@ -659,7 +732,7 @@ class _GenerateV7DSP(_DSPGenerator): def Parse(self): try: - dspfile = open(self.dspfile,'r') + dspfile = open(self.dspabs,'r') except IOError: return # doesn't exist yet, so can't add anything to configs. @@ -706,9 +779,9 @@ class _GenerateV7DSP(_DSPGenerator): def Build(self): try: - self.file = open(self.dspfile,'w') + self.file = open(self.dspabs,'w') except IOError, detail: - raise SCons.Errors.InternalError, 'Unable to open "' + self.dspfile + '" for writing:' + str(detail) + raise SCons.Errors.InternalError, 'Unable to open "' + self.dspabs + '" for writing:' + str(detail) else: self.PrintHeader() self.PrintProject() @@ -731,15 +804,12 @@ class _DSWGenerator: if len(projects) < 1: raise SCons.Errors.UserError, \ "You must specify at least one project to create an MSVSSolution." - if len(projects) > 1: - raise SCons.Errors.UserError, \ - "Currently you can specify at most one project to create an MSVSSolution." - self.dspfile = str(projects[0]) + self.dspfiles = map(str, projects) if self.env.has_key('name'): self.name = self.env['name'] else: - self.name = os.path.basename(SCons.Util.splitext(self.dspfile)[0]) + self.name = os.path.basename(SCons.Util.splitext(self.dswfile)[0]) def Build(self): pass @@ -750,10 +820,15 @@ class _GenerateV7DSW(_DSWGenerator): _DSWGenerator.__init__(self, dswfile, source, env) self.file = None - self.version = float(self.env['MSVS_VERSION']) + self.version = self.env['MSVS_VERSION'] + self.version_num, self.suite = msvs_parse_version(self.version) self.versionstr = '7.00' - if self.version >= 7.1: + if self.version_num >= 8.0: + self.versionstr = '9.00' + elif self.version_num >= 7.1: self.versionstr = '8.00' + if self.version_num >= 8.0: + self.versionstr = '9.00' if env.has_key('slnguid') and env['slnguid']: self.slnguid = env['slnguid'] @@ -778,7 +853,7 @@ class _GenerateV7DSW(_DSWGenerator): config.platform = match.group(2) else: config.variant = variant - config.platform = 'Win32'; + config.platform = 'Win32' self.configs[variant] = config print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'" @@ -830,15 +905,24 @@ class _GenerateV7DSW(_DSWGenerator): def PrintSolution(self): """Writes a solution file""" - self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n' - # the next line has the GUID for an external makefile project. - 'Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "%s", "%s", "%s"\n' - % (self.versionstr, self.name, os.path.basename(self.dspfile), self.slnguid)) - if self.version >= 7.1: - self.file.write('\tProjectSection(ProjectDependencies) = postProject\n' - '\tEndProjectSection\n') - self.file.write('EndProject\n' - 'Global\n') + self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n' % self.versionstr ) + if self.version_num >= 8.0: + self.file.write('# Visual Studio 2005\n') + for p in self.dspfiles: + name = os.path.basename(p) + base, suffix = SCons.Util.splitext(name) + if suffix == '.vcproj': + name = base + # the next line has the GUID for an external makefile project. + self.file.write('Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "%s", "%s", "%s"\n' + % ( name, p, self.slnguid ) ) + if self.version_num >= 7.1 and self.version_num < 8.0: + self.file.write('\tProjectSection(ProjectDependencies) = postProject\n' + '\tEndProjectSection\n') + self.file.write('EndProject\n') + + self.file.write('Global\n') + env = self.env if env.has_key('MSVS_SCC_PROVIDER'): dspfile_base = os.path.basename(self.dspfile) @@ -850,7 +934,7 @@ class _GenerateV7DSW(_DSWGenerator): scc_local_path = env.get('MSVS_SCC_LOCAL_PATH', '') scc_project_base_path = env.get('MSVS_SCC_PROJECT_BASE_PATH', '') # project_guid = env.get('MSVS_PROJECT_GUID', '') - + self.file.write('\tGlobalSection(SourceCodeControl) = preSolution\n' '\t\tSccNumberOfProjects = 2\n' '\t\tSccProjectUniqueName0 = %(dspfile_base)s\n' @@ -864,32 +948,57 @@ class _GenerateV7DSW(_DSWGenerator): '\t\tSccProjectFilePathRelativizedFromConnection1 = %(scc_project_base_path)s\n' '\t\tSolutionUniqueID = %(slnguid)s\n' '\tEndGlobalSection\n' % locals()) - - self.file.write('\tGlobalSection(SolutionConfiguration) = preSolution\n') + + if self.version_num >= 8.0: + self.file.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n') + else: + self.file.write('\tGlobalSection(SolutionConfiguration) = preSolution\n') + confkeys = self.configs.keys() confkeys.sort() cnt = 0 for name in confkeys: variant = self.configs[name].variant - self.file.write('\t\tConfigName.%d = %s\n' % (cnt, variant)) + platform = self.configs[name].platform + if self.version_num >= 8.0: + self.file.write('\t\t%s|%s = %s|%s\n' % (variant, platform, variant, platform)) + else: + self.file.write('\t\tConfigName.%d = %s\n' % (cnt, variant)) cnt = cnt + 1 self.file.write('\tEndGlobalSection\n') - if self.version < 7.1: + if self.version_num < 7.1: self.file.write('\tGlobalSection(ProjectDependencies) = postSolution\n' '\tEndGlobalSection\n') - self.file.write('\tGlobalSection(ProjectConfiguration) = postSolution\n') + if self.version_num >= 8.0: + self.file.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n') + else: + self.file.write('\tGlobalSection(ProjectConfiguration) = postSolution\n') + for name in confkeys: name = name variant = self.configs[name].variant platform = self.configs[name].platform - self.file.write('\t\t%s.%s.ActiveCfg = %s|%s\n' - '\t\t%s.%s.Build.0 = %s|%s\n' %(self.slnguid,variant,variant,platform,self.slnguid,variant,variant,platform)) - self.file.write('\tEndGlobalSection\n' - '\tGlobalSection(ExtensibilityGlobals) = postSolution\n' - '\tEndGlobalSection\n' - '\tGlobalSection(ExtensibilityAddIns) = postSolution\n' - '\tEndGlobalSection\n' - 'EndGlobal\n') + if self.version_num >= 8.0: + for p in self.dspfiles: + guid = _generateGUID(p, '') + self.file.write('\t\t%s.%s|%s.ActiveCfg = %s|%s\n' + '\t\t%s.%s|%s.Build.0 = %s|%s\n' % (guid,variant,platform,variant,platform,guid,variant,platform,variant,platform)) + else: + self.file.write('\t\t%s.%s.ActiveCfg = %s|%s\n' + '\t\t%s.%s.Build.0 = %s|%s\n' %(self.slnguid,variant,variant,platform,self.slnguid,variant,variant,platform)) + + self.file.write('\tEndGlobalSection\n') + + if self.version_num >= 8.0: + self.file.write('\tGlobalSection(SolutionProperties) = preSolution\n' + '\t\tHideSolutionNode = FALSE\n' + '\tEndGlobalSection\n') + else: + self.file.write('\tGlobalSection(ExtensibilityGlobals) = postSolution\n' + '\tEndGlobalSection\n' + '\tGlobalSection(ExtensibilityAddIns) = postSolution\n' + '\tEndGlobalSection\n') + self.file.write('EndGlobal\n') if self.nokeep == 0: pdata = pickle.dumps(self.configs,1) pdata = base64.encodestring(pdata) @@ -941,7 +1050,7 @@ class _GenerateV6DSW(_DSWGenerator): def PrintWorkspace(self): """ writes a DSW file """ name = self.name - dspfile = self.dspfile + dspfile = self.dspfiles[0] self.file.write(V6DSWHeader % locals()) def Build(self): @@ -957,7 +1066,10 @@ class _GenerateV6DSW(_DSWGenerator): def GenerateDSP(dspfile, source, env): """Generates a Project file based on the version of MSVS that is being used""" - if env.has_key('MSVS_VERSION') and float(env['MSVS_VERSION']) >= 7.0: + version_num = 6.0 + if env.has_key('MSVS_VERSION'): + version_num, suite = msvs_parse_version(env['MSVS_VERSION']) + if version_num >= 7.0: g = _GenerateV7DSP(dspfile, source, env) g.Build() else: @@ -967,7 +1079,10 @@ def GenerateDSP(dspfile, source, env): def GenerateDSW(dswfile, source, env): """Generates a Solution/Workspace file based on the version of MSVS that is being used""" - if env.has_key('MSVS_VERSION') and float(env['MSVS_VERSION']) >= 7.0: + version_num = 6.0 + if env.has_key('MSVS_VERSION'): + version_num, suite = msvs_parse_version(env['MSVS_VERSION']) + if version_num >= 7.0: g = _GenerateV7DSW(dswfile, source, env) g.Build() else: @@ -1018,56 +1133,64 @@ def get_visualstudio_versions(): return [] HLM = SCons.Util.HKEY_LOCAL_MACHINE - K = r'Software\Microsoft\VisualStudio' + KEYS = { + r'Software\Microsoft\VisualStudio' : '', + r'Software\Microsoft\VCExpress' : 'Exp', + } L = [] - try: - k = SCons.Util.RegOpenKeyEx(HLM, K) - i = 0 - while 1: - try: - p = SCons.Util.RegEnumKey(k,i) - except SCons.Util.RegError: - break - i = i + 1 - if not p[0] in '123456789' or p in L: - continue - # Only add this version number if there is a valid - # registry structure (includes the "Setup" key), - # and at least some of the correct directories - # exist. Sometimes VS uninstall leaves around - # some registry/filesystem turds that we don't - # want to trip over. Also, some valid registry - # entries are MSDN entries, not MSVS ('7.1', - # notably), and we want to skip those too. - try: - SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p + '\\Setup') - except SCons.Util.RegError: - continue - - id = [] - idk = SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p) - # This is not always here -- it only exists if the - # user installed into a non-standard location (at - # least in VS6 it works that way -- VS7 seems to - # always write it) - try: - id = SCons.Util.RegQueryValueEx(idk, 'InstallDir') - except SCons.Util.RegError: - pass - - # If the InstallDir key doesn't exist, - # then we check the default locations. - if not id or not id[0]: - files_dir = SCons.Platform.win32.get_program_files_dir() - if float(p) < 7.0: - vs = r'Microsoft Visual Studio\Common\MSDev98' - else: - vs = r'Microsoft Visual Studio .NET\Common7\IDE' - id = [ os.path.join(files_dir, vs, 'devenv.exe') ] - if os.path.exists(id[0]): - L.append(p) - except SCons.Util.RegError: - pass + for K, suite_suffix in KEYS.items(): + try: + k = SCons.Util.RegOpenKeyEx(HLM, K) + i = 0 + while 1: + try: + p = SCons.Util.RegEnumKey(k,i) + except SCons.Util.RegError: + break + i = i + 1 + if not p[0] in '123456789' or p in L: + continue + # Only add this version number if there is a valid + # registry structure (includes the "Setup" key), + # and at least some of the correct directories + # exist. Sometimes VS uninstall leaves around + # some registry/filesystem turds that we don't + # want to trip over. Also, some valid registry + # entries are MSDN entries, not MSVS ('7.1', + # notably), and we want to skip those too. + try: + SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p + '\\Setup') + except SCons.Util.RegError: + continue + + id = [] + idk = SCons.Util.RegOpenKeyEx(HLM, K + '\\' + p) + # This is not always here -- it only exists if the + # user installed into a non-standard location (at + # least in VS6 it works that way -- VS7 seems to + # always write it) + try: + id = SCons.Util.RegQueryValueEx(idk, 'InstallDir') + except SCons.Util.RegError: + pass + + # If the InstallDir key doesn't exist, + # then we check the default locations. + # Note: The IDE's executable is not devenv.exe for VS8 Express. + if not id or not id[0]: + files_dir = SCons.Platform.win32.get_program_files_dir() + version_num, suite = msvs_parse_version(p) + if version_num < 7.0: + vs = r'Microsoft Visual Studio\Common\MSDev98' + elif version_num < 8.0: + vs = r'Microsoft Visual Studio .NET\Common7\IDE' + else: + vs = r'Microsoft Visual Studio 8\Common7\IDE' + id = [ os.path.join(files_dir, vs) ] + if os.path.exists(id[0]): + L.append(p + suite_suffix) + except SCons.Util.RegError: + pass if not L: return [] @@ -1087,6 +1210,51 @@ def get_visualstudio_versions(): return L +def get_default_visualstudio8_suite(env): + """ + Returns the Visual Studio 2005 suite identifier set in the env, or the + highest suite installed. + """ + if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']): + env['MSVS'] = {} + + if env.has_key('MSVS_SUITE'): + suite = env['MSVS_SUITE'].upper() + suites = [suite] + else: + suite = 'EXPRESS' + suites = [suite] + if SCons.Util.can_read_reg: + suites = get_visualstudio8_suites() + if suites: + suite = suites[0] #use best suite by default + + env['MSVS_SUITE'] = suite + env['MSVS']['SUITES'] = suites + env['MSVS']['SUITE'] = suite + + return suite + +def get_visualstudio8_suites(): + """ + Returns a sorted list of all installed Visual Studio 2005 suites found + in the registry. The highest version should be the first entry in the list. + """ + + suites = [] + + # ToDo: add tests for better suits than VS8 Express here. + + idk = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, + r'Software\Microsoft\VCExpress\8.0') + try: + id = SCons.Util.RegQueryValueEx(idk, 'InstallDir') + suites.append('EXPRESS') + except SCons.Util.RegError: + pass + + return suites + def is_msvs_installed(): """ Check the registry for an installed visual studio. @@ -1113,22 +1281,26 @@ def get_msvs_install_dirs(version = None): else: return {} - K = 'Software\\Microsoft\\VisualStudio\\' + version + version_num, suite = msvs_parse_version(version) + + if (version_num >= 8.0): + K = 'Software\\Microsoft\\VCExpress\\' + str(version_num) + else: + K = 'Software\\Microsoft\\VisualStudio\\' + str(version_num) # vc++ install dir rv = {} + if (version_num < 7.0): + key = K + r'\Setup\Microsoft Visual C++\ProductDir' + else: + key = K + r'\Setup\VC\ProductDir' try: - if (float(version) < 7.0): - (rv['VCINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, - K + r'\Setup\Microsoft Visual C++\ProductDir') - else: - (rv['VCINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, - K + r'\Setup\VC\ProductDir') + (rv['VCINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, key) except SCons.Util.RegError: pass # visual studio install dir - if (float(version) < 7.0): + if (version_num < 7.0): try: (rv['VSINSTALLDIR'], t) = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, K + r'\Setup\Microsoft Visual Studio\ProductDir') @@ -1237,13 +1409,13 @@ def get_msvs_install_dirs(version = None): except SCons.Util.RegError: pass - return rv; + return rv def GetMSVSProjectSuffix(target, source, env, for_signature): - return env['MSVS']['PROJECTSUFFIX']; + return env['MSVS']['PROJECTSUFFIX'] def GetMSVSSolutionSuffix(target, source, env, for_signature): - return env['MSVS']['SOLUTIONSUFFIX']; + return env['MSVS']['SOLUTIONSUFFIX'] def GenerateProject(target, source, env): # generate the dsp file, according to the version of MSVS. @@ -1494,7 +1666,8 @@ def generate(env): # find them on their own. pass - if (float(env['MSVS_VERSION']) < 7.0): + version_num, suite = msvs_parse_version(env['MSVS_VERSION']) + if (version_num < 7.0): env['MSVS']['PROJECTSUFFIX'] = '.dsp' env['MSVS']['SOLUTIONSUFFIX'] = '.dsw' else: @@ -1514,7 +1687,10 @@ def exists(env): pass if not v: - if env.has_key('MSVS_VERSION') and float(env['MSVS_VERSION']) >= 7.0: + version_num = 6.0 + if env.has_key('MSVS_VERSION'): + version_num, suite = msvs_parse_version(env['MSVS_VERSION']) + if version_num >= 7.0: return env.Detect('devenv') else: return env.Detect('msdev') diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 53198d4..6095dff 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -43,10 +43,6 @@ regdata_6a = string.split(r'''[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudi "ProductDir"="C:\Program Files\Microsoft Visual Studio\MSDN98\98VSa\1033" [HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++] "ProductDir"="C:\Program Files\Microsoft Visual Studio\VC98" -[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion] -"ProgramFilesDir"="C:\Program Files" -"CommonFilesDir"="C:\Program Files\Common Files" -"MediaPath"="C:\WINDOWS\Media" ''','\n') regdata_6b = string.split(r'''[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio] @@ -66,10 +62,6 @@ regdata_6b = string.split(r'''[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudi [HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Microsoft VSEE Client] "ProductDir"="C:\VS6\Common\Tools" [HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Visual Studio 98] -[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion] -"ProgramFilesDir"="C:\Program Files" -"CommonFilesDir"="C:\Program Files\Common Files" -"MediaPath"="C:\WINDOWS\Media" ''','\n') regdata_7 = string.split(r''' @@ -136,93 +128,159 @@ regdata_7 = string.split(r''' "Include Dirs"="$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(VCInstallDir)PlatformSDK\include\prerelease;$(VCInstallDir)PlatformSDK\include;$(FrameworkSDKDir)include" "Source Dirs"="$(VCInstallDir)atlmfc\src\mfc;$(VCInstallDir)atlmfc\src\atl;$(VCInstallDir)crt\src" "Reference Dirs"="" -[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion] -"ProgramFilesDir"="C:\Program Files" -"CommonFilesDir"="C:\Program Files\Common Files" -"MediaPath"="C:\WINDOWS\Media" ''','\n') -regdata_67 = string.split(r''' -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0] -"InstallDir"="C:\VS6\Common\IDE\IDE98" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\ServicePacks] -"sp5"="" -"latest"=dword:00000005 -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup] -"VsCommonDir"="C:\VS6\Common" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Microsoft Visual Basic] -"ProductDir"="C:\VS6\VB98" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++] -"ProductDir"="C:\VS6\VC98" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Microsoft Visual Studio] -"ProductDir"="C:\VS6" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Microsoft VSEE Client] -"ProductDir"="C:\VS6\Common\Tools" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\6.0\Setup\Visual Studio 98] -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0] -"InstallDir"="C:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\" -"Source Directories"="C:\Program Files\Microsoft Visual Studio .NET\Vc7\crt\;C:\Program Files\Microsoft Visual Studio .NET\Vc7\atlmfc\src\mfc\;C:\Program Files\Microsoft Visual Studio .NET\Vc7\atlmfc\src\atl\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\InstalledProducts] -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\InstalledProducts\CrystalReports] -@="#15007" -"Package"="{F05E92C6-8346-11D3-B4AD-00A0C9B04E7B}" -"ProductDetails"="#15009" -"LogoID"="0" -"PID"="#15008" -"UseInterface"=dword:00000001 -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\InstalledProducts\Visual Basic.NET] +regdata_7_1 = string.split(r''' +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1] @="" -"DefaultProductAttribute"="VB" +"Source Directories"="C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\crt\src\;C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc\;C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\atl\" +"ThisVersionSolutionCLSID"="{246C57AE-40DD-4d6b-9E8D-B0F5757BB2A8}" +"ThisVersionDTECLSID"="{8CD2DD97-4EC1-4bc4-9359-89A3EEDD57A6}" +"InstallDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\" +"CLR Version"="v1.1.4322" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\InstalledProducts] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\InstalledProducts\Smart Device Extensions] +"UseInterface"=dword:00000001 +"VS7InstallDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\" +"VBDeviceInstallDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\VB7\" +"CSharpDeviceInstallDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\VC#\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\InstalledProducts\Visual Basic.NET] +"UseInterface"=dword:00000001 "Package"="{164B10B9-B200-11D0-8C61-00A0C91E29D5}" +"DefaultProductAttribute"="VB" +@="" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\InstalledProducts\Visual C#] +"DefaultProductAttribute"="C#" "UseInterface"=dword:00000001 -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\InstalledProducts\Visual C#] +"Package"="{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}" @="" -"Package"="{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\InstalledProducts\Visual JSharp] +@="" +"Package"="{E6FDF8B0-F3D1-11D4-8576-0002A516ECE8}" "UseInterface"=dword:00000001 -"DefaultProductAttribute"="C#" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\InstalledProducts\VisualC++] +"DefaultProductAttribute"="Visual JSharp" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\InstalledProducts\VisualC++] "UseInterface"=dword:00000001 "Package"="{F1C25864-3097-11D2-A5C5-00C04F7968B4}" "DefaultProductAttribute"="VC" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup] -"Dbghelp_path"="C:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\" -"dw_dir"="C:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\MSDN] -"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET\Msdn\1033\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\Servicing\SKU] -"Visual Studio .NET Professional - English"="{D0610409-7D65-11D5-A54F-0090278A1BB8}" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\VB] -"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET\Vb7\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\VC] -"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET\Vc7\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\VC#] -"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET\VC#\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\Visual Studio .NET Professional - English] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup] +"Dbghelp_path"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\" +"dw_dir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\CSDPROJ] +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\VC#\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\JSHPROJ] +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\VJ#\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\Servicing] +"CurrentSULevel"=dword:00000000 +"CurrentSPLevel"=dword:00000000 +"Server Path"="" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\Servicing\Package] +"FxSDK"="" +"VB"="" +"VC"="" +"VCS"="" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\Servicing\SKU] +"Visual Studio .NET Professional 2003 - English"="{20610409-CA18-41A6-9E21-A93AE82EE7C5}" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\VB] +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Vb7\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\VBDPROJ] +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Vb7\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\VC] +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\VC#] +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\VC#\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\Visual Studio .NET Professional 2003 - English] "InstallSuccess"=dword:00000001 -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\VS] -"EnvironmentDirectory"="C:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\" -"EnvironmentPath"="C:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\devenv.exe" -"VS7EnvironmentLocation"="C:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\devenv.exe" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\VS] +"EnvironmentDirectory"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\" +"EnvironmentPath"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe" +"VS7EnvironmentLocation"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe" "MSMDir"="C:\Program Files\Common Files\Merge Modules\" -"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET\" -"VS7CommonBinDir"="C:\Program Files\Microsoft Visual Studio .NET\Common7\Tools\" -"VS7CommonDir"="C:\Program Files\Microsoft Visual Studio .NET\Common7\" -"VSUpdateDir"="C:\Program Files\Microsoft Visual Studio .NET\Setup\VSUpdate\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\VS\BuildNumber] -"1033"="7.0.9466" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\Setup\VS\Pro] -"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET\" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\VC] -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\VC\VC_OBJECTS_PLATFORM_INFO] -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\VC\VC_OBJECTS_PLATFORM_INFO\Win32] -@="{A54AAE91-30C2-11D3-87BF-A04A4CC10000}" -[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories] -"Path Dirs"="$(VCInstallDir)bin;$(VSInstallDir)Common7\Tools\bin\prerelease;$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;C:\Program Files\HTML Help Workshop\;$(FrameworkSDKDir)bin;$(FrameworkDir)$(FrameworkVersion);C:\perl\bin;C:\cygwin\bin;c:\cygwin\usr\bin;C:\bin;C:\program files\perforce;C:\cygwin\usr\local\bin\i686-pc-cygwin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem" +"VS7CommonBinDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\" +"VS7CommonDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\" +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\" +"VSUpdateDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\Setup\VSUpdate\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\VS\BuildNumber] +"1033"="7.1.3088" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\Setup\VS\Pro] +"ProductDir"="C:\Program Files\Microsoft Visual Studio .NET 2003\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\VC] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\VC\VC_OBJECTS_PLATFORM_INFO] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\VC\VC_OBJECTS_PLATFORM_INFO\Win32] +@="{759354D0-6B42-4705-AFFB-56E34D2BC3D4}" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories] +"Path Dirs"="$(VCInstallDir)bin;$(VSInstallDir)Common7\Tools\bin\prerelease;$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;C:\Program Files\HTML Help Workshop\;$(FrameworkSDKDir)bin;$(FrameworkDir)$(FrameworkVersion);C:\Perl\bin\;c:\bin;c:\cygwin\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Common Files\Avid;C:\Program Files\backburner 2\;C:\Program Files\cvsnt;C:\Program Files\Subversion\bin;C:\Program Files\Common Files\Adobe\AGL;C:\Program Files\HTMLDoc" "Library Dirs"="$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)PlatformSDK\lib\prerelease;$(VCInstallDir)PlatformSDK\lib;$(FrameworkSDKDir)lib" "Include Dirs"="$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(VCInstallDir)PlatformSDK\include\prerelease;$(VCInstallDir)PlatformSDK\include;$(FrameworkSDKDir)include" "Source Dirs"="$(VCInstallDir)atlmfc\src\mfc;$(VCInstallDir)atlmfc\src\atl;$(VCInstallDir)crt\src" -"Reference Dirs"="" -[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion] +"Reference Dirs"="$(FrameWorkDir)$(FrameWorkVersion)" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\VC\VC_OBJECTS_PLATFORM_INFO\Win32\ToolDefaultExtensionLists] +"VCCLCompilerTool"="*.cpp;*.cxx;*.cc;*.c" +"VCLinkerTool"="*.obj;*.res;*.lib;*.rsc" +"VCLibrarianTool"="*.obj;*.res;*.lib;*.rsc" +"VCMIDLTool"="*.idl;*.odl" +"VCCustomBuildTool"="*.bat" +"VCResourceCompilerTool"="*.rc" +"VCPreBuildEventTool"="*.bat" +"VCPreLinkEventTool"="*.bat" +"VCPostBuildEventTool"="*.bat" +"VCBscMakeTool"="*.sbr" +"VCNMakeTool"="" +"VCWebServiceProxyGeneratorTool"="*.discomap" +"VCWebDeploymentTool"="" +"VCALinkTool"="*.resources" +"VCManagedResourceCompilerTool"="*.resx" +"VCXMLDataGeneratorTool"="*.xsd" +"VCManagedWrapperGeneratorTool"="" +"VCAuxiliaryManagedWrapperGeneratorTool"="" +"VCPrimaryInteropTool"="" +''','\n') + +regdata_8exp = string.split(r''' +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0] +"CLR Version"="v2.0.50727" +"ApplicationID"="VCExpress" +"SecurityAppID"="{741726F6-1EAE-4680-86A6-6085E8872CF8}" +"InstallDir"="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\" +"EnablePreloadCLR"=dword:00000001 +"RestoreAppPath"=dword:00000001 +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\InstalledProducts] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\InstalledProducts\Microsoft Visual C++] +"UseInterface"=dword:00000001 +"Package"="{F1C25864-3097-11D2-A5C5-00C04F7968B4}" +"DefaultProductAttribute"="VC" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\Setup] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\Setup\VC] +"ProductDir"="C:\Program Files\Microsoft Visual Studio 8\VC\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\Setup\VS] +"ProductDir"="C:\Program Files\Microsoft Visual Studio 8\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\VC] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\VC\VC_OBJECTS_PLATFORM_INFO] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\VC\VC_OBJECTS_PLATFORM_INFO\Win32] +@="{72f11281-2429-11d7-8bf6-00b0d03daa06}" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VCExpress\8.0\VC\VC_OBJECTS_PLATFORM_INFO\Win32\ToolDefaultExtensionLists] +"VCCLCompilerTool"="*.cpp;*.cxx;*.cc;*.c" +"VCLinkerTool"="*.obj;*.res;*.lib;*.rsc;*.licenses" +"VCLibrarianTool"="*.obj;*.res;*.lib;*.rsc" +"VCMIDLTool"="*.idl;*.odl" +"VCCustomBuildTool"="*.bat" +"VCResourceCompilerTool"="*.rc" +"VCPreBuildEventTool"="*.bat" +"VCPreLinkEventTool"="*.bat" +"VCPostBuildEventTool"="*.bat" +"VCBscMakeTool"="*.sbr" +"VCFxCopTool"="*.dll;*.exe" +"VCNMakeTool"="" +"VCWebServiceProxyGeneratorTool"="*.discomap" +"VCWebDeploymentTool"="" +"VCALinkTool"="*.resources" +"VCManagedResourceCompilerTool"="*.resx" +"VCXMLDataGeneratorTool"="*.xsd" +"VCManifestTool"="*.manifest" +"VCXDCMakeTool"="*.xdc" +''','\n') + +regdata_cv = string.split(r'''[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion] "ProgramFilesDir"="C:\Program Files" "CommonFilesDir"="C:\Program Files\Common Files" "MediaPath"="C:\WINDOWS\Media" @@ -270,7 +328,7 @@ class RegNode: return (self.valdict[val],1) else: raise SCons.Util.RegError - + def addValue(self,name,val): self.valdict[name] = val self.valarray.append(name) @@ -299,13 +357,13 @@ class RegNode: raise SCons.Util.RegError def addKey(self,name,sep = '\\'): - if name.find(sep) != -1: - keyname, subkeys = name.split(sep,1) + if string.find(name, sep) != -1: + keyname, subkeys = string.split(name, sep, 1) else: keyname = name subkeys = "" - if not self.keydict.has_key(keyname): + if not self.keydict.has_key(keyname): self.keydict[keyname] = RegNode(keyname) self.keyarray.append(keyname) @@ -340,9 +398,9 @@ class DummyRegistry: self.root.addKey('HKEY_CURRENT_USER') self.root.addKey('HKEY_USERS') self.root.addKey('HKEY_CLASSES_ROOT') - + self.parse(data) - + def parse(self, data): parent = self.root keymatch = re.compile('^\[(.*)\]$') @@ -368,7 +426,7 @@ class DummyRegistry: mykey = 'HKEY_LOCAL_MACHINE\\' + key #print "Open Key",mykey return self.root.key(mykey) - + def DummyOpenKeyEx(root, key): return registry.OpenKeyEx(root,key) @@ -395,98 +453,171 @@ def DummyExists(path): return 1 class msvsTestCase(unittest.TestCase): + def setUp(self): + global registry + registry = self.registry + def test_get_default_visual_studio_version(self): """Test retrieval of the default visual studio version""" env = DummyEnv() v1 = get_default_visualstudio_version(env) - assert env['MSVS_VERSION'] == default_version - assert env['MSVS']['VERSION'] == default_version - assert v1 == default_version + assert env['MSVS_VERSION'] == self.default_version, env['MSVS_VERSION'] + assert env['MSVS']['VERSION'] == self.default_version, env['MSVS']['VERSION'] + assert v1 == self.default_version, v1 env = DummyEnv({'MSVS_VERSION':'7.0'}) v2 = get_default_visualstudio_version(env) - assert env['MSVS_VERSION'] == '7.0' - assert env['MSVS']['VERSION'] == '7.0' - assert v2 == '7.0' + assert env['MSVS_VERSION'] == '7.0', env['MSVS_VERSION'] + assert env['MSVS']['VERSION'] == '7.0', env['MSVS']['VERSION'] + assert v2 == '7.0', v2 def test_get_visual_studio_versions(self): """Test retrieval of the list of visual studio versions""" v1 = get_visualstudio_versions() - assert not v1 or v1[0] == highest_version - assert len(v1) == number_of_versions + assert not v1 or v1[0] == self.highest_version, v1 + assert len(v1) == self.number_of_versions, v1 def test_get_msvs_install_dirs(self): """Test retrieval of the list of visual studio installed locations""" v1 = get_msvs_install_dirs() - v2 = get_msvs_install_dirs('7.0') - assert v1 == install_location1 - assert v2 == install_location2 - -if __name__ == "__main__": - - # only makes sense to test this on win32 - if sys.platform != 'win32': - sys.exit(0) - - 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 :-) - - # try it for each possible setup. - suite = unittest.makeSuite(msvsTestCase, 'test_') - registry = DummyRegistry(regdata_6a) + assert v1 == self.default_install_loc, v1 + for key, loc in self.install_locs.items(): + v2 = get_msvs_install_dirs(key) + assert v2 == loc, key + ': ' + str(v2) + +class msvs6aTestCase(msvsTestCase): + """Test MSVS 6 Registry""" + registry = DummyRegistry(regdata_6a + regdata_cv) default_version = '6.0' highest_version = '6.0' number_of_versions = 1 - install_location1 = {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio\\VC98'} - install_location2 = {} - print "Test MSVS 6 Registry" - # print str(registry.root) - if not unittest.TextTestRunner().run(suite).wasSuccessful(): - sys.exit(1) - - registry = DummyRegistry(regdata_6b) + install_locs = { + '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio\\VC98'}, + '7.0' : {}, + '7.1' : {}, + '8.0' : {}, + '8.0Exp' : {}, + } + default_install_loc = install_locs['6.0'] + +class msvs6bTestCase(msvsTestCase): + """Test Other MSVS 6 Registry""" + registry = DummyRegistry(regdata_6b + regdata_cv) default_version = '6.0' highest_version = '6.0' number_of_versions = 1 - install_location1 = {'VSINSTALLDIR': 'C:\\VS6', 'VCINSTALLDIR': 'C:\\VS6\\VC98'} - install_location2 = {} - print "Test Other MSVS 6 Registry" - # print str(registry.root) - if not unittest.TextTestRunner().run(suite).wasSuccessful(): - sys.exit(1) - - registry = DummyRegistry(regdata_67) + install_locs = { + '6.0' : {'VSINSTALLDIR': 'C:\\VS6', 'VCINSTALLDIR': 'C:\\VS6\\VC98'}, + '7.0' : {}, + '7.1' : {}, + '8.0' : {}, + '8.0Exp' : {}, + } + default_install_loc = install_locs['6.0'] + +class msvs6and7TestCase(msvsTestCase): + """Test MSVS 6 & 7 Registry""" + registry = DummyRegistry(regdata_6b + regdata_7 + regdata_cv) default_version = '7.0' highest_version = '7.0' number_of_versions = 2 - install_location1 = {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'} - install_location2 = {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'} - # print str(registry.root) - print "Test MSVS 6 & 7 Registry" - if not unittest.TextTestRunner().run(suite).wasSuccessful(): - sys.exit(1) - - registry = DummyRegistry(regdata_7) + install_locs = { + '6.0' : {'VSINSTALLDIR': 'C:\\VS6', 'VCINSTALLDIR': 'C:\\VS6\\VC98'}, + '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'}, + '7.1' : {}, + '8.0' : {}, + '8.0Exp' : {}, + } + default_install_loc = install_locs['7.0'] + +class msvs7TestCase(msvsTestCase): + """Test MSVS 7 Registry""" + registry = DummyRegistry(regdata_7 + regdata_cv) default_version = '7.0' highest_version = '7.0' number_of_versions = 1 - install_location1 = {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'} - install_location2 = {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'} - # print str(registry.root) - print "Test MSVS 7 Registry" - if not unittest.TextTestRunner().run(suite).wasSuccessful(): - sys.exit(1) - + install_locs = { + '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, + '7.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\'}, + '7.1' : {}, + '8.0' : {}, + '8.0Exp' : {}, + } + default_install_loc = install_locs['7.0'] + +class msvs71TestCase(msvsTestCase): + """Test MSVS 7.1 Registry""" + registry = DummyRegistry(regdata_7_1 + regdata_cv) + default_version = '7.1' + highest_version = '7.1' + number_of_versions = 1 + install_locs = { + '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, + '7.0' : {}, + '7.1' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\', 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio .NET 2003\\Vc7\\'}, + '8.0' : {}, + '8.0Exp' : {}, + } + default_install_loc = install_locs['7.1'] + +class msvs8ExpTestCase(msvsTestCase): + """Test MSVS 8 Express Registry""" + registry = DummyRegistry(regdata_8exp + regdata_cv) + default_version = '8.0Exp' + highest_version = '8.0Exp' + number_of_versions = 1 + install_locs = { + '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, + '7.0' : {}, + '7.1' : {}, + '8.0' : {'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'] + +class msvsEmptyTestCase(msvsTestCase): + """Test Empty Registry""" registry = DummyRegistry(regdata_none) default_version = '6.0' highest_version = None number_of_versions = 0 - install_location1 = {} - install_location2 = {} - # print str(registry.root) - print "Test Empty Registry" - if not unittest.TextTestRunner().run(suite).wasSuccessful(): - sys.exit(1) + install_locs = { + '6.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio'}, + '7.0' : {}, + '7.1' : {}, + '8.0' : {}, + '8.0Exp' : {}, + } + default_install_loc = install_locs['8.0Exp'] + +if __name__ == "__main__": + + # only makes sense to test this on win32 + if sys.platform != 'win32': + sys.exit(0) + + 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 :-) + + exit_val = 0 + + test_classes = [ + msvs6aTestCase, + msvs6bTestCase, + msvs6and7TestCase, + msvs7TestCase, + msvs71TestCase, + msvs8ExpTestCase, + msvsEmptyTestCase, + ] + + for test_class in test_classes: + print test_class.__doc__ + suite = unittest.makeSuite(test_class, 'test_') + if not unittest.TextTestRunner().run(suite).wasSuccessful(): + exit_val = 1 + + sys.exit(exit_val) |