Commits

Gary Oberbrunner committed f45059a

Integrated patch for issue 2571, various fixes for MSVS project generation. From Jean-Franois Colson.

Comments (0)

Files changed (9)

QMTest/TestSConsMSVS.py

 
 expected_slnfile_7_0 = """\
 Microsoft Visual Studio Solution File, Format Version 7.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "{E5466E26-0003-F18B-8F8A-BCD76C86388D}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "<PROJECT_GUID>"
 EndProject
 Global
+<SCC_SLN_INFO>
 \tGlobalSection(SolutionConfiguration) = preSolution
 \t\tConfigName.0 = Release
 \tEndGlobalSection
 \tGlobalSection(ProjectDependencies) = postSolution
 \tEndGlobalSection
 \tGlobalSection(ProjectConfiguration) = postSolution
-\t\t{E5466E26-0003-F18B-8F8A-BCD76C86388D}.Release.ActiveCfg = Release|Win32
-\t\t{E5466E26-0003-F18B-8F8A-BCD76C86388D}.Release.Build.0 = Release|Win32
+\t\t<PROJECT_GUID>.Release.ActiveCfg = Release|Win32
+\t\t<PROJECT_GUID>.Release.Build.0 = Release|Win32
 \tEndGlobalSection
 \tGlobalSection(ExtensibilityGlobals) = postSolution
 \tEndGlobalSection
 """
 
 expected_vcprojfile_7_0 = """\
-<?xml version="1.0" encoding = "Windows-1252"?>
+<?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 \tProjectType="Visual C++"
 \tVersion="7.00"
 \tName="Test"
-\tProjectGUID=""
-\tSccProjectName=""
-\tSccLocalPath=""
+\tProjectGUID="<PROJECT_GUID>"
+<SCC_VCPROJ_INFO>
 \tKeyword="MakeFileProj">
 \t<Platforms>
 \t\t<Platform
 \t\t\t<Tool
 \t\t\t\tName="VCNMakeTool"
 \t\t\t\tBuildCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct &quot;Test.exe&quot;"
+\t\t\t\tReBuildCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct &quot;Test.exe&quot;"
 \t\t\t\tCleanCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct -c &quot;Test.exe&quot;"
-\t\t\t\tRebuildCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct &quot;Test.exe&quot;"
 \t\t\t\tOutput="Test.exe"/>
 \t\t</Configuration>
 \t</Configurations>
 
 expected_slnfile_7_1 = """\
 Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "{E5466E26-0003-F18B-8F8A-BCD76C86388D}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "<PROJECT_GUID>"
 \tProjectSection(ProjectDependencies) = postProject
 \tEndProjectSection
 EndProject
 Global
+<SCC_SLN_INFO>
 \tGlobalSection(SolutionConfiguration) = preSolution
 \t\tConfigName.0 = Release
 \tEndGlobalSection
+\tGlobalSection(ProjectDependencies) = postSolution
+\tEndGlobalSection
 \tGlobalSection(ProjectConfiguration) = postSolution
-\t\t{E5466E26-0003-F18B-8F8A-BCD76C86388D}.Release.ActiveCfg = Release|Win32
-\t\t{E5466E26-0003-F18B-8F8A-BCD76C86388D}.Release.Build.0 = Release|Win32
+\t\t<PROJECT_GUID>.Release.ActiveCfg = Release|Win32
+\t\t<PROJECT_GUID>.Release.Build.0 = Release|Win32
 \tEndGlobalSection
 \tGlobalSection(ExtensibilityGlobals) = postSolution
 \tEndGlobalSection
 """
 
 expected_vcprojfile_7_1 = """\
-<?xml version="1.0" encoding = "Windows-1252"?>
+<?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 \tProjectType="Visual C++"
 \tVersion="7.10"
 \tName="Test"
-\tProjectGUID=""
-\tSccProjectName=""
-\tSccLocalPath=""
+\tProjectGUID="<PROJECT_GUID>"
+<SCC_VCPROJ_INFO>
 \tKeyword="MakeFileProj">
 \t<Platforms>
 \t\t<Platform
 \t\t\t<Tool
 \t\t\t\tName="VCNMakeTool"
 \t\t\t\tBuildCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct &quot;Test.exe&quot;"
+\t\t\t\tReBuildCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct &quot;Test.exe&quot;"
 \t\t\t\tCleanCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct -c &quot;Test.exe&quot;"
-\t\t\t\tRebuildCommandLine="echo Starting SCons &amp;&amp; &quot;<PYTHON>&quot; -c &quot;<SCONS_SCRIPT_MAIN_XML>&quot; -C &quot;<WORKPATH>&quot; -f SConstruct &quot;Test.exe&quot;"
 \t\t\t\tOutput="Test.exe"/>
 \t\t</Configuration>
 \t</Configurations>
 expected_slnfile_8_0 = """\
 Microsoft Visual Studio Solution File, Format Version 9.00
 # Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "{E5466E26-0003-F18B-8F8A-BCD76C86388D}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.vcproj", "<PROJECT_GUID>"
 EndProject
 Global
+<SCC_SLN_INFO>
 \tGlobalSection(SolutionConfigurationPlatforms) = preSolution
 \t\tRelease|Win32 = Release|Win32
 \tEndGlobalSection
 \tGlobalSection(ProjectConfigurationPlatforms) = postSolution
-\t\t{E5466E26-0003-F18B-8F8A-BCD76C86388D}.Release|Win32.ActiveCfg = Release|Win32
-\t\t{E5466E26-0003-F18B-8F8A-BCD76C86388D}.Release|Win32.Build.0 = Release|Win32
+\t\t<PROJECT_GUID>.Release|Win32.ActiveCfg = Release|Win32
+\t\t<PROJECT_GUID>.Release|Win32.Build.0 = Release|Win32
 \tEndGlobalSection
 \tGlobalSection(SolutionProperties) = preSolution
 \t\tHideSolutionNode = FALSE
 \tVersion="8.00"
 \tName="Test"
 \tProjectGUID="<PROJECT_GUID>"
-\tSccProjectName=""
-\tSccLocalPath=""
 \tRootNamespace="Test"
+<SCC_VCPROJ_INFO>
 \tKeyword="MakeFileProj">
 \t<Platforms>
 \t\t<Platform
     def msvs_substitute(self, input, msvs_ver,
                         subdir=None, sconscript=None,
                         python=None,
-                        project_guid=None):
+                        project_guid=None,
+                        vcproj_sccinfo='', sln_sccinfo=''):
         if not hasattr(self, '_msvs_versions'):
             self.msvs_versions()
 
         result = result.replace(r'<SCONS_SCRIPT_MAIN>', exec_script_main)
         result = result.replace(r'<SCONS_SCRIPT_MAIN_XML>', exec_script_main_xml)
         result = result.replace(r'<PROJECT_GUID>', project_guid)
+        result = result.replace('<SCC_VCPROJ_INFO>\n', vcproj_sccinfo)
+        result = result.replace('<SCC_SLN_INFO>\n', sln_sccinfo)
         return result
 
     def get_msvs_executable(self, version):
 
 RELEASE 2.1.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE
 
+  From Jean-Fran�ois Colson:
+
+    - Improve Microsoft Visual Studio Solution generation, and fix
+      various errors in the generated solutions especially when using
+      MSVS_SCC_PROVIDER, and when generating multiple projects.  The
+      construction variable MSVS_SCC_PROJECT_BASE_PATH, which never
+      worked properly, is removed.  Users can use the new variable
+      MSVS_SCC_CONNECTION_ROOT instead if desired.
+
   From Anatoly Techtonik:
 
-    - use subprocess in bootstrap.py instead of os.execve to avoid
+    - Use subprocess in bootstrap.py instead of os.execve to avoid
       losing output control on Windows (http://bugs.python.org/issue9148)
 
   From Alexander Goomenyuk:

src/engine/SCons/Tool/msvs.py

     num, suite = version_re.match(s).groups()
     return float(num), suite
 
+# os.path.relpath has been introduced in Python 2.6
+# We define it locally for earlier versions of Python
+def relpath(path, start=os.path.curdir):
+    """Return a relative version of a path"""
+    import sys
+    if not path:
+        raise ValueError("no path specified")
+    start_list = os.path.abspath(start).split(os.sep)
+    path_list = os.path.abspath(path).split(os.sep)
+    if 'posix' in sys.builtin_module_names:
+        # Work out how much of the filepath is shared by start and path.
+        i = len(os.path.commonprefix([start_list, path_list]))
+    else:
+        if start_list[0].lower() != path_list[0].lower():
+            unc_path, rest = os.path.splitunc(path)
+            unc_start, rest = os.path.splitunc(start)
+            if bool(unc_path) ^ bool(unc_start):
+                raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+                                                                    % (path, start))
+            else:
+                raise ValueError("path is on drive %s, start on drive %s"
+                                                    % (path_list[0], start_list[0]))
+        # Work out how much of the filepath is shared by start and path.
+        for i in range(min(len(start_list), len(path_list))):
+            if start_list[i].lower() != path_list[i].lower():
+                break
+        else:
+            i += 1
+    rel_list = [os.pardir] * (len(start_list)-i) + path_list[i:]
+    if not rel_list:
+        return os.path.curdir
+    return os.path.join(*rel_list)
+
+if not "relpath" in os.path.__all__:
+    os.path.relpath = relpath
+
 # 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
             self.file.close()
 
 V7DSPHeader = """\
-<?xml version="1.0" encoding = "%(encoding)s"?>
+<?xml version="1.0" encoding="%(encoding)s"?>
 <VisualStudioProject
 \tProjectType="Visual C++"
 \tVersion="%(versionstr)s"
 \tName="%(name)s"
+\tProjectGUID="%(project_guid)s"
 %(scc_attrs)s
 \tKeyword="MakeFileProj">
 """
 \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\tRebuildCommandLine="%(rebuildcmd)s"
 \t\t\t\tOutput="%(runfile)s"/>
 \t\t</Configuration>
 """
 \tProjectType="Visual C++"
 \tVersion="%(versionstr)s"
 \tName="%(name)s"
+\tProjectGUID="%(project_guid)s"
+\tRootNamespace="%(name)s"
 %(scc_attrs)s
-\tRootNamespace="%(name)s"
 \tKeyword="MakeFileProj">
 """
 
         scc_provider = env.get('MSVS_SCC_PROVIDER', '')
         scc_project_name = env.get('MSVS_SCC_PROJECT_NAME', '')
         scc_aux_path = env.get('MSVS_SCC_AUX_PATH', '')
-        scc_local_path = env.get('MSVS_SCC_LOCAL_PATH', '')
+        # MSVS_SCC_LOCAL_PATH is kept  for backwards compatibility purpose and should
+        # be deprecated as soon as possible.
+        scc_local_path_legacy = env.get('MSVS_SCC_LOCAL_PATH', '')
+        scc_connection_root = env.get('MSVS_SCC_CONNECTION_ROOT', os.curdir)
+        scc_local_path = os.path.relpath(scc_connection_root, os.path.dirname(self.dspabs))
         project_guid = env.get('MSVS_PROJECT_GUID', '')
-        if self.version_num >= 8.0 and not project_guid:
+        if not project_guid:
             project_guid = _generateGUID(self.dspfile, '')
         if scc_provider != '':
-            scc_attrs = ('\tProjectGUID="%s"\n'
-                         '\tSccProjectName="%s"\n'
-                         '\tSccAuxPath="%s"\n'
-                         '\tSccLocalPath="%s"\n'
-                         '\tSccProvider="%s"' % (project_guid, scc_project_name, scc_aux_path, scc_local_path, scc_provider))
+            scc_attrs = '\tSccProjectName="%s"\n' % scc_project_name
+            if scc_aux_path != '':
+                scc_attrs += '\tSccAuxPath="%s"\n' % scc_aux_path
+            scc_attrs += ('\tSccLocalPath="%s"\n'
+                          '\tSccProvider="%s"' % (scc_local_path, scc_provider))
+        elif scc_local_path_legacy != '':
+            # This case is kept for backwards compatibility purpose and should
+            # be deprecated as soon as possible.
+            scc_attrs = ('\tSccProjectName="%s"\n'
+                         '\tSccLocalPath="%s"' % (scc_project_name, scc_local_path_legacy))
         else:
-            scc_attrs = ('\tProjectGUID="%s"\n'
-                         '\tSccProjectName="%s"\n'
-                         '\tSccLocalPath="%s"' % (project_guid, scc_project_name, scc_local_path))
+            self.dspheader = self.dspheader.replace('%(scc_attrs)s\n', '')
 
         self.file.write(self.dspheader % locals())
 
     """ Base class for DSW generators """
     def __init__(self, dswfile, source, env):
         self.dswfile = os.path.normpath(str(dswfile))
+        self.dsw_folder_path = os.path.dirname(os.path.abspath(self.dswfile))
         self.env = env
 
         if 'projects' not in env:
             if not platform in self.platforms:
                 self.platforms.append(platform)
 
+        def GenerateProjectFilesInfo(self):
+            for dspfile in self.dspfiles:
+                dsp_folder_path, name = os.path.split(dspfile)
+                dsp_folder_path = os.path.abspath(dsp_folder_path)
+                dsp_relative_folder_path = os.path.relpath(dsp_folder_path, self.dsw_folder_path)
+                if dsp_relative_folder_path == os.curdir:
+                    dsp_relative_file_path = name
+                else:
+                    dsp_relative_file_path = os.path.join(dsp_relative_folder_path, name)
+                dspfile_info = {'NAME': name,
+                                'GUID': _generateGUID(dspfile, ''),
+                                'FOLDER_PATH': dsp_folder_path,
+                                'FILE_PATH': dspfile,
+                                'SLN_RELATIVE_FOLDER_PATH': dsp_relative_folder_path,
+                                'SLN_RELATIVE_FILE_PATH': dsp_relative_file_path}
+                self.dspfiles_info.append(dspfile_info)
+                
+        self.dspfiles_info = []
+        GenerateProjectFilesInfo(self)
+
     def Parse(self):
         try:
             dswfile = open(self.dswfile,'r')
         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)
+        for dspinfo in self.dspfiles_info:
+            name = dspinfo['NAME']
             base, suffix = SCons.Util.splitext(name)
             if suffix == '.vcproj':
                 name = base
-            guid = _generateGUID(p, '')
             self.file.write('Project("%s") = "%s", "%s", "%s"\n'
-                            % ( external_makefile_guid, name, p, guid ) )
+                            % (external_makefile_guid, name, dspinfo['SLN_RELATIVE_FILE_PATH'], dspinfo['GUID']))
             if self.version_num >= 7.1 and self.version_num < 8.0:
                 self.file.write('\tProjectSection(ProjectDependencies) = postProject\n'
                                 '\tEndProjectSection\n')
 
         env = self.env
         if 'MSVS_SCC_PROVIDER' in env:
-            dspfile_base = os.path.basename(self.dspfile)
+            scc_number_of_projects = len(self.dspfiles) + 1
             slnguid = self.slnguid
-            scc_provider = env.get('MSVS_SCC_PROVIDER', '')
-            scc_provider = scc_provider.replace(' ', r'\u0020')
-            scc_project_name = env.get('MSVS_SCC_PROJECT_NAME', '')
-            # scc_aux_path = env.get('MSVS_SCC_AUX_PATH', '')
-            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', '')
-
+            scc_provider = env.get('MSVS_SCC_PROVIDER', '').replace(' ', r'\u0020')
+            scc_project_name = env.get('MSVS_SCC_PROJECT_NAME', '').replace(' ', r'\u0020')
+            scc_connection_root = env.get('MSVS_SCC_CONNECTION_ROOT', os.curdir)
+            scc_local_path = os.path.relpath(scc_connection_root, self.dsw_folder_path).replace('\\', '\\\\')
             self.file.write('\tGlobalSection(SourceCodeControl) = preSolution\n'
-                            '\t\tSccNumberOfProjects = 2\n'
-                            '\t\tSccProjectUniqueName0 = %(dspfile_base)s\n'
+                            '\t\tSccNumberOfProjects = %(scc_number_of_projects)d\n'
+                            '\t\tSccProjectName0 = %(scc_project_name)s\n'
                             '\t\tSccLocalPath0 = %(scc_local_path)s\n'
-                            '\t\tCanCheckoutShared = true\n'
-                            '\t\tSccProjectFilePathRelativizedFromConnection0 = %(scc_project_base_path)s\n'
-                            '\t\tSccProjectName1 = %(scc_project_name)s\n'
-                            '\t\tSccLocalPath1 = %(scc_local_path)s\n'
-                            '\t\tSccProvider1 = %(scc_provider)s\n'
-                            '\t\tCanCheckoutShared = true\n'
-                            '\t\tSccProjectFilePathRelativizedFromConnection1 = %(scc_project_base_path)s\n'
-                            '\t\tSolutionUniqueID = %(slnguid)s\n'
-                            '\tEndGlobalSection\n' % locals())
-
+                            '\t\tSccProvider0 = %(scc_provider)s\n'
+                            '\t\tCanCheckoutShared = true\n'  % locals())
+            sln_relative_path_from_scc = os.path.relpath(self.dsw_folder_path, scc_connection_root)
+            if sln_relative_path_from_scc != os.curdir:
+                self.file.write('\t\tSccProjectFilePathRelativizedFromConnection0 = %s\\\\\n'
+                                % sln_relative_path_from_scc.replace('\\', '\\\\'))
+            if self.version_num < 8.0:
+                # When present, SolutionUniqueID is automatically removed by VS 2005
+                # TODO: check for Visual Studio versions newer than 2005
+                self.file.write('\t\tSolutionUniqueID = %s\n' % slnguid)
+            for dspinfo in self.dspfiles_info:
+                i = self.dspfiles_info.index(dspinfo) + 1
+                dsp_relative_file_path = dspinfo['SLN_RELATIVE_FILE_PATH'].replace('\\', '\\\\')
+                dsp_scc_relative_folder_path = os.path.relpath(dspinfo['FOLDER_PATH'], scc_connection_root).replace('\\', '\\\\')
+                self.file.write('\t\tSccProjectUniqueName%(i)s = %(dsp_relative_file_path)s\n'
+                                '\t\tSccLocalPath%(i)d = %(scc_local_path)s\n'
+                                '\t\tCanCheckoutShared = true\n'
+                                '\t\tSccProjectFilePathRelativizedFromConnection%(i)s = %(dsp_scc_relative_folder_path)s\\\\\n'
+                                % locals())
+            self.file.write('\tEndGlobalSection\n')
         if self.version_num >= 8.0:
             self.file.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
         else:
                 self.file.write('\t\tConfigName.%d = %s\n' % (cnt, variant))
             cnt = cnt + 1
         self.file.write('\tEndGlobalSection\n')
-        if self.version_num < 7.1:
+        if self.version_num <= 7.1:
             self.file.write('\tGlobalSection(ProjectDependencies) = postSolution\n'
                             '\tEndGlobalSection\n')
         if self.version_num >= 8.0:
             variant = self.configs[name].variant
             platform = self.configs[name].platform
             if self.version_num >= 8.0:
-                for p in self.dspfiles:
-                    guid = _generateGUID(p, '')
+                for dspinfo in self.dspfiles_info:
+                    guid = dspinfo['GUID']
                     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:
-                for p in self.dspfiles:
-                    guid = _generateGUID(p, '')
+                for dspinfo in self.dspfiles_info:
+                    guid = dspinfo['GUID']
                     self.file.write('\t\t%s.%s.ActiveCfg = %s|%s\n'
                                     '\t\t%s.%s.Build.0 = %s|%s\n'  %(guid,variant,variant,platform,guid,variant,variant,platform))
 
     def PrintWorkspace(self):
         """ writes a DSW file """
         name = self.name
-        dspfile = self.dspfiles[0]
+        dspfile = os.path.relpath(self.dspfiles[0], self.dsw_folder_path)
         self.file.write(V6DSWHeader % locals())
 
     def Build(self):
 ##############################################################################
 
 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.
     sourcelist = source
 
     if env.get('auto_build_solution', 1):
-        env['projects'] = targetlist
+        env['projects'] = [env.File(t).srcnode() for t in targetlist]
         t, s = solutionEmitter(target, target, env)
         targetlist = targetlist + t
 

src/engine/SCons/Tool/msvs.xml

 </summary>
 </cvar>
 
-<cvar name="MSVS_PROJECT_BASE_PATH">
-<summary>
-The string
-placed in a generated Microsoft Visual Studio solution file
-as the value of the
-<literal>SccProjectFilePathRelativizedFromConnection0</literal>
-and
-<literal>SccProjectFilePathRelativizedFromConnection1</literal>
-attributes of the
-<literal>GlobalSection(SourceCodeControl)</literal>
-section.
-There is no default value.
-</summary>
-</cvar>
-
 <cvar name="MSVS_PROJECT_GUID">
 <summary>
 The string
 as the value of the
 <literal>ProjectGUID</literal>
 attribute.
-The string is also placed in the
-<literal>SolutionUniqueID</literal>
-attribute of the
-<literal>GlobalSection(SourceCodeControl)</literal>
-section of the Microsoft Visual Studio solution file.
-There is no default value.
+There is no default value. If not defined, a new GUID is generated.
 </summary>
 </cvar>
 
 </summary>
 </cvar>
 
-<cvar name="MSVS_SCC_LOCAL_PATH">
+<cvar name="MSVS_SCC_CONNECTION_ROOT">
 <summary>
-The path name
-placed in a generated Microsoft Visual Studio project file
-as the value of the
+The root path of projects in your SCC workspace, i.e the path under which
+all project and solution files will be generated. It is used as a
+reference path from which the relative paths of the generated
+Microsoft Visual Studio project and solution files are computed.
+The relative project file path is placed as the value of the
 <literal>SccLocalPath</literal>
 attribute
+of the project file
+and as the values of the
+<literal>SccProjectFilePathRelativizedFromConnection[i]</literal>
+(where [i] ranges from 0 to the number of projects in the solution)
+attributes of the
+<literal>GlobalSection(SourceCodeControl)</literal>
+section of the Microsoft Visual Studio solution file.
+Similarly the relative solution file path is placed as the values of the
+<literal>SccLocalPath[i]</literal>
+(where [i] ranges from 0 to the number of projects in the solution)
+attributes of the
+<literal>GlobalSection(SourceCodeControl)</literal>
+section of the Microsoft Visual Studio solution file.
+This is used only
 if the
 <envar>MSVS_SCC_PROVIDER</envar>
 construction variable is also set.
-The path name is also placed in the
-<literal>SccLocalPath0</literal>
-and
-<literal>SccLocalPath1</literal>
-attributes of the
-<literal>GlobalSection(SourceCodeControl)</literal>
-section of the Microsoft Visual Studio solution file.
-There is no default value.
+The default value is the current working directory.
 </summary>
 </cvar>
 
 placed in a generated Microsoft Visual Studio project file
 as the value of the
 <literal>SccProjectName</literal>
-attribute.
+attribute
+if the
+<envar>MSVS_SCC_PROVIDER</envar>
+construction variable is also set.
+In this case the string is also placed in the
+<literal>SccProjectName0</literal>
+attribute of the
+<literal>GlobalSection(SourceCodeControl)</literal>
+section of the Microsoft Visual Studio solution file.
 There is no default value.
 </summary>
 </cvar>
 <literal>SccProvider</literal>
 attribute.
 The string is also placed in the
-<literal>SccProvider1</literal>
+<literal>SccProvider0</literal>
 attribute of the
 <literal>GlobalSection(SourceCodeControl)</literal>
 section of the Microsoft Visual Studio solution file.

test/MSVS/common-prefix.py

 \tVersion="8.00"
 \tName="Test"
 \tProjectGUID="<PROJECT_GUID>"
-\tSccProjectName=""
-\tSccLocalPath=""
 \tRootNamespace="Test"
 \tKeyword="MakeFileProj">
 \t<Platforms>

test/MSVS/runfile.py

 \tVersion="8.00"
 \tName="Test"
 \tProjectGUID="<PROJECT_GUID>"
-\tSccProjectName=""
-\tSccLocalPath=""
 \tRootNamespace="Test"
 \tKeyword="MakeFileProj">
 \t<Platforms>

test/MSVS/vs-7.0-variant_dir.py

 
 test.run(arguments=".")
 
+project_guid = "{25F6CE89-8E22-2910-8B6E-FFE6DC1E2792}"
 vcproj = test.read(['src', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.0', None, 'SConstruct')
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', None, 'SConstruct',
+                              project_guid=project_guid)
 # don't compare the pickled data
 assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
 
 test.must_exist(test.workpath('src', 'Test.sln'))
 sln = test.read(['src', 'Test.sln'], 'r')
-expect = test.msvs_substitute(expected_slnfile, '7.0', 'src')
+expect = test.msvs_substitute(expected_slnfile, '7.0', 'src',
+                              project_guid=project_guid)
 # don't compare the pickled data
 assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
 

test/MSVS/vs-7.1-variant_dir.py

 
 test.run(arguments=".")
 
+project_guid = "{25F6CE89-8E22-2910-8B6E-FFE6DC1E2792}"
 vcproj = test.read(['src', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile, '7.0', None, 'SConstruct')
+expect = test.msvs_substitute(expected_vcprojfile, '7.0', None, 'SConstruct',
+                              project_guid=project_guid)
 # don't compare the pickled data
 assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
 
 test.must_exist(test.workpath('src', 'Test.sln'))
 sln = test.read(['src', 'Test.sln'], 'r')
-expect = test.msvs_substitute(expected_slnfile, '7.0', 'src')
+expect = test.msvs_substitute(expected_slnfile, '7.0', 'src',
+                              project_guid=project_guid)
 # don't compare the pickled data
 assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)
 

test/MSVS/vs-8.0-variant_dir.py

 
 test.run(arguments=".")
 
+project_guid = "{25F6CE89-8E22-2910-8B6E-FFE6DC1E2792}"
 vcproj = test.read(['src', 'Test.vcproj'], 'r')
-expect = test.msvs_substitute(expected_vcprojfile,
-                              '8.0',
-                              None,
-                              'SConstruct',
-                              project_guid="{25F6CE89-8E22-2910-8B6E-FFE6DC1E2792}")
+expect = test.msvs_substitute(expected_vcprojfile, '8.0', None, 'SConstruct',
+                              project_guid=project_guid)
 # don't compare the pickled data
 assert vcproj[:len(expect)] == expect, test.diff_substr(expect, vcproj)
 
 test.must_exist(test.workpath('src', 'Test.sln'))
 sln = test.read(['src', 'Test.sln'], 'r')
-expect = test.msvs_substitute(expected_slnfile, '8.0', 'src')
+expect = test.msvs_substitute(expected_slnfile, '8.0', 'src',
+                              project_guid=project_guid)
 # don't compare the pickled data
 assert sln[:len(expect)] == expect, test.diff_substr(expect, sln)