diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-24 09:57:09 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2019-07-24 09:57:09 +0200 | 
| commit | c7665433b2004d2b404d6fb9d6fd064998486f63 (patch) | |
| tree | 8525ef6d24f7c6ceb238945ebb2cc997c7afc905 /src/engine/SCons/Tool/msvs.py | |
| parent | e48d2727885efda8369c7edbc2e3929a59532adc (diff) | |
| parent | 6e228c305122f0564eda1e67d56651f8386d24d7 (diff) | |
Merge branch 'release/debian/3.1.0+repack-1'debian/3.1.0+repack-1
Diffstat (limited to 'src/engine/SCons/Tool/msvs.py')
| -rw-r--r-- | src/engine/SCons/Tool/msvs.py | 209 | 
1 files changed, 144 insertions, 65 deletions
diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 05531c6..38965e3 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -9,7 +9,7 @@ selection method.  """  # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method.  from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/msvs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvs.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan"  import SCons.compat @@ -70,10 +70,14 @@ def xmlify(s):      s = s.replace('\n', '
')      return s -# Process a CPPPATH list in includes, given the env, target and source. -# Returns a tuple of nodes.  def processIncludes(includes, env, target, source): -    return SCons.PathList.PathList(includes).subst_path(env, target, source) +    """ +    Process a CPPPATH list in includes, given the env, target and source. +    Returns a list of directory paths. These paths are absolute so we avoid +    putting pound-prefixed paths in a Visual Studio project file. +    """ +    return [env.Dir(i).abspath for i in +            SCons.PathList.PathList(includes).subst_path(env, target, source)]  external_makefile_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' @@ -149,9 +153,9 @@ def splitFully(path):      return [base]  def makeHierarchy(sources): -    '''Break a list of files into a hierarchy; for each value, if it is a string, +    """Break a list of files into a hierarchy; for each value, if it is a string,         then it is a file.  If it is a dictionary, it is a folder.  The string is -       the original path of the file.''' +       the original path of the file."""      hierarchy = {}      for file in sources: @@ -189,7 +193,7 @@ class _UserGenerator(object):          elif SCons.Util.is_List(env['variant']):              variants = env['variant'] -        if 'DebugSettings' not in env or env['DebugSettings'] == None: +        if 'DebugSettings' not in env or env['DebugSettings'] is None:              dbg_settings = []          elif SCons.Util.is_Dict(env['DebugSettings']):              dbg_settings = [env['DebugSettings']] @@ -348,10 +352,20 @@ V10DebugSettings = {  }  class _GenerateV10User(_UserGenerator): -    """Generates a Project'user file for MSVS 2010""" +    """Generates a Project'user file for MSVS 2010 or later"""      def __init__(self, dspfile, source, env): -        self.versionstr = '4.0' +        version_num, suite = msvs_parse_version(env['MSVS_VERSION']) +        if version_num >= 14.2: +            # Visual Studio 2019 is considered to be version 16. +            self.versionstr = '16.0' +        elif version_num >= 14.1: +            # Visual Studio 2017 is considered to be version 15. +            self.versionstr = '15.0' +        elif version_num == 14.0: +            self.versionstr = '14.0' +        else: +            self.versionstr = '4.0'          self.usrhead = V10UserHeader          self.usrconf = V10UserConfiguration          self.usrdebg = V10DebugSettings @@ -397,7 +411,7 @@ class _DSPGenerator(object):          elif SCons.Util.is_List(env['variant']):              variants = env['variant'] -        if 'buildtarget' not in env or env['buildtarget'] == None: +        if 'buildtarget' not in env or env['buildtarget'] is None:              buildtarget = ['']          elif SCons.Util.is_String(env['buildtarget']):              buildtarget = [env['buildtarget']] @@ -418,7 +432,7 @@ class _DSPGenerator(object):              for _ in variants:                  buildtarget.append(bt) -        if 'outdir' not in env or env['outdir'] == None: +        if 'outdir' not in env or env['outdir'] is None:              outdir = ['']          elif SCons.Util.is_String(env['outdir']):              outdir = [env['outdir']] @@ -439,7 +453,7 @@ class _DSPGenerator(object):              for v in variants:                  outdir.append(s) -        if 'runfile' not in env or env['runfile'] == None: +        if 'runfile' not in env or env['runfile'] is None:              runfile = buildtarget[-1:]          elif SCons.Util.is_String(env['runfile']):              runfile = [env['runfile']] @@ -462,15 +476,41 @@ class _DSPGenerator(object):          self.sconscript = env['MSVSSCONSCRIPT'] -        if 'cmdargs' not in env or env['cmdargs'] == None: -            cmdargs = [''] * len(variants) -        elif SCons.Util.is_String(env['cmdargs']): -            cmdargs = [env['cmdargs']] * len(variants) -        elif SCons.Util.is_List(env['cmdargs']): -            if len(env['cmdargs']) != len(variants): -                raise SCons.Errors.InternalError("Sizes of 'cmdargs' and 'variant' lists must be the same.") +        def GetKeyFromEnv(env, key, variants): +            """ +            Retrieves a specific key from the environment. If the key is +            present, it is expected to either be a string or a list with length +            equal to the number of variants. The function returns a list of +            the desired value (e.g. cpp include paths) guaranteed to be of +            length equal to the length of the variants list. +            """ +            if key not in env or env[key] is None: +                return [''] * len(variants) +            elif SCons.Util.is_String(env[key]): +                return [env[key]] * len(variants) +            elif SCons.Util.is_List(env[key]): +                if len(env[key]) != len(variants): +                    raise SCons.Errors.InternalError("Sizes of '%s' and 'variant' lists must be the same." % key) +                else: +                    return env[key]              else: -                cmdargs = env['cmdargs'] +                raise SCons.Errors.InternalError("Unsupported type for key '%s' in environment: %s" % +                                                 (key, type(env[key]))) + +        cmdargs = GetKeyFromEnv(env, 'cmdargs', variants) + +        # The caller is allowed to put 'cppdefines' and/or 'cpppaths' in the +        # environment, which is useful if they want to provide per-variant +        # values for these. Otherwise, we fall back to using the global +        # 'CPPDEFINES' and 'CPPPATH' functions. +        if 'cppdefines' in env: +            cppdefines = GetKeyFromEnv(env, 'cppdefines', variants) +        else: +            cppdefines = [env.get('CPPDEFINES', [])] * len(variants) +        if 'cpppaths' in env: +            cpppaths = GetKeyFromEnv(env, 'cpppaths', variants) +        else: +            cpppaths = [env.get('CPPPATH', [])] * len(variants)          self.env = env @@ -513,14 +553,18 @@ class _DSPGenerator(object):          for n in sourcenames:              self.sources[n].sort(key=lambda a: a.lower()) -        def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, dspfile=dspfile): +        def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, cppdefines, cpppaths, dspfile=dspfile, env=env):              config = Config()              config.buildtarget = buildtarget              config.outdir = outdir              config.cmdargs = cmdargs +            config.cppdefines = cppdefines              config.runfile = runfile -            match = re.match('(.*)\|(.*)', variant) +            # Dir objects can't be pickled, so we need an absolute path here. +            config.cpppaths = processIncludes(cpppaths, env, None, None) + +            match = re.match(r'(.*)\|(.*)', variant)              if match:                  config.variant = match.group(1)                  config.platform = match.group(2) @@ -532,12 +576,12 @@ class _DSPGenerator(object):              print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'")          for i in range(len(variants)): -            AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i]) +            AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i])          self.platforms = []          for key in list(self.configs.keys()):              platform = self.configs[key].platform -            if not platform in self.platforms: +            if platform not in self.platforms:                  self.platforms.append(platform)      def Build(self): @@ -553,16 +597,16 @@ V6DSPHeader = """\  CFG=%(name)s - Win32 %(confkey)s  !MESSAGE This is not a valid makefile. To build this project using NMAKE,  !MESSAGE use the Export Makefile command and run -!MESSAGE  +!MESSAGE  !MESSAGE NMAKE /f "%(name)s.mak". -!MESSAGE  +!MESSAGE  !MESSAGE You can specify a configuration when running NMAKE  !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE  +!MESSAGE  !MESSAGE NMAKE /f "%(name)s.mak" CFG="%(name)s - Win32 %(confkey)s" -!MESSAGE  +!MESSAGE  !MESSAGE Possible choices for configuration are: -!MESSAGE  +!MESSAGE  """  class _GenerateV6DSP(_DSPGenerator): @@ -580,7 +624,7 @@ class _GenerateV6DSP(_DSPGenerator):          for kind in confkeys:              self.file.write('!MESSAGE "%s - Win32 %s" (based on "Win32 (x86) External Target")\n' % (name, kind)) -        self.file.write('!MESSAGE \n\n') +        self.file.write('!MESSAGE\n\n')      def PrintProject(self):          name = self.name @@ -637,7 +681,7 @@ class _GenerateV6DSP(_DSPGenerator):                  first = 1              else:                  self.file.write('!ELSEIF  "$(CFG)" == "%s - Win32 %s"\n\n' % (name,kind)) -        self.file.write('!ENDIF \n\n') +        self.file.write('!ENDIF\n\n')          self.PrintSourceFiles()          self.file.write('# End Target\n'                          '# End Project\n') @@ -645,10 +689,10 @@ class _GenerateV6DSP(_DSPGenerator):          if self.nokeep == 0:              # now we pickle some data and add it to the file -- MSDEV will ignore it.              pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) -            pdata = base64.encodestring(pdata).decode() +            pdata = base64.b64encode(pdata).decode()              self.file.write(pdata + '\n')              pdata = pickle.dumps(self.sources,PICKLE_PROTOCOL) -            pdata = base64.encodestring(pdata).decode() +            pdata = base64.b64encode(pdata).decode()              self.file.write(pdata + '\n')      def PrintSourceFiles(self): @@ -685,11 +729,13 @@ class _GenerateV6DSP(_DSPGenerator):              return # doesn't exist yet, so can't add anything to configs.          line = dspfile.readline() +        # skip until marker          while line:              if line.find("# End Project") > -1:                  break              line = dspfile.readline() +        # read to get configs          line = dspfile.readline()          datas = line          while line and line != '\n': @@ -707,12 +753,14 @@ class _GenerateV6DSP(_DSPGenerator):          self.configs.update(data) +        # keep reading to get sources          data = None          line = dspfile.readline()          datas = line          while line and line != '\n':              line = dspfile.readline()              datas = datas + line +        dspfile.close()          # OK, we've found our little pickled cache of data.          # it has a "# " in front of it, so we strip that. @@ -878,6 +926,8 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User):              buildtarget = self.configs[kind].buildtarget              runfile     = self.configs[kind].runfile              cmdargs = self.configs[kind].cmdargs +            cpppaths = self.configs[kind].cpppaths +            cppdefines = self.configs[kind].cppdefines              env_has_buildtarget = 'MSVSBUILDTARGET' in self.env              if not env_has_buildtarget: @@ -895,9 +945,8 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User):              # This isn't perfect; CPPDEFINES and CPPPATH can contain $TARGET and $SOURCE,              # so they could vary depending on the command being generated.  This code              # assumes they don't. -            preprocdefs = xmlify(';'.join(processDefines(self.env.get('CPPDEFINES', [])))) -            includepath_Dirs = processIncludes(self.env.get('CPPPATH', []), self.env, None, None) -            includepath = xmlify(';'.join([str(x) for x in includepath_Dirs])) +            preprocdefs = xmlify(';'.join(processDefines(cppdefines))) +            includepath = xmlify(';'.join(processIncludes(cpppaths, self.env, None, None)))              if not env_has_buildtarget:                  del self.env['MSVSBUILDTARGET'] @@ -917,10 +966,10 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User):          if self.nokeep == 0:              # now we pickle some data and add it to the file -- MSDEV will ignore it.              pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) -            pdata = base64.encodestring(pdata).decode() +            pdata = base64.b64encode(pdata).decode()              self.file.write('<!-- SCons Data:\n' + pdata + '\n')              pdata = pickle.dumps(self.sources,PICKLE_PROTOCOL) -            pdata = base64.encodestring(pdata).decode() +            pdata = base64.b64encode(pdata).decode()              self.file.write(pdata + '-->\n')      def printSources(self, hierarchy, commonprefix): @@ -998,11 +1047,13 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User):              return # doesn't exist yet, so can't add anything to configs.          line = dspfile.readline() +        # skip until marker          while line:              if line.find('<!-- SCons Data:') > -1:                  break              line = dspfile.readline() +        # read to get configs          line = dspfile.readline()          datas = line          while line and line != '\n': @@ -1020,12 +1071,14 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User):          self.configs.update(data) +        # keep reading to get sources          data = None          line = dspfile.readline()          datas = line          while line and line != '\n':              line = dspfile.readline()              datas = datas + line +        dspfile.close()          # OK, we've found our little pickled cache of data.          try: @@ -1052,7 +1105,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User):  V10DSPHeader = """\  <?xml version="1.0" encoding="%(encoding)s"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="%(versionstr)s" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  """  V10DSPProjectConfiguration = """\ @@ -1067,6 +1120,7 @@ V10DSPGlobals = """\  \t\t<ProjectGuid>%(project_guid)s</ProjectGuid>  %(scc_attrs)s\t\t<RootNamespace>%(name)s</RootNamespace>  \t\t<Keyword>MakeFileProj</Keyword> +\t\t<VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>  \t</PropertyGroup>  """ @@ -1080,7 +1134,7 @@ V10DSPPropertyGroupCondition = """\  V10DSPImportGroupCondition = """\  \t<ImportGroup Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'" Label="PropertySheets"> -\t\t<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +\t\t<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />  \t</ImportGroup>  """ @@ -1096,6 +1150,11 @@ V10DSPCommandLine = """\  \t\t<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>  """ +V15DSPHeader = """\ +<?xml version="1.0" encoding="%(encoding)s"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +""" +  class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):      """Generates a Project file for MSVS 2010""" @@ -1110,6 +1169,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):      def PrintHeader(self):          env = self.env          name = self.name +        versionstr = self.versionstr          encoding = env.subst('$MSVSENCODING')          project_guid = env.get('MSVS_PROJECT_GUID', '')          scc_provider = env.get('MSVS_SCC_PROVIDER', '') @@ -1154,7 +1214,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):          name = self.name          confkeys = sorted(self.configs.keys()) -        self.file.write('\t<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\n') +        self.file.write('\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />\n')          toolset = ''          if 'MSVC_VERSION' in self.env: @@ -1165,7 +1225,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):              platform = self.configs[kind].platform              self.file.write(V10DSPPropertyGroupCondition % locals()) -        self.file.write('\t<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\n') +        self.file.write('\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />\n')          self.file.write('\t<ImportGroup Label="ExtensionSettings">\n')          self.file.write('\t</ImportGroup>\n') @@ -1185,6 +1245,8 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):              buildtarget = self.configs[kind].buildtarget              runfile     = self.configs[kind].runfile              cmdargs = self.configs[kind].cmdargs +            cpppaths = self.configs[kind].cpppaths +            cppdefines = self.configs[kind].cppdefines              env_has_buildtarget = 'MSVSBUILDTARGET' in self.env              if not env_has_buildtarget: @@ -1202,9 +1264,8 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):              # This isn't perfect; CPPDEFINES and CPPPATH can contain $TARGET and $SOURCE,              # so they could vary depending on the command being generated.  This code              # assumes they don't. -            preprocdefs = xmlify(';'.join(processDefines(self.env.get('CPPDEFINES', [])))) -            includepath_Dirs = processIncludes(self.env.get('CPPPATH', []), self.env, None, None) -            includepath = xmlify(';'.join([str(x) for x in includepath_Dirs])) +            preprocdefs = xmlify(';'.join(processDefines(cppdefines))) +            includepath = xmlify(';'.join(processIncludes(cpppaths, self.env, None, None)))              if not env_has_buildtarget:                  del self.env['MSVSBUILDTARGET'] @@ -1221,14 +1282,15 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):              raise SCons.Errors.InternalError('Unable to open "' + self.filtersabs + '" for writing:' + str(detail))          self.filters_file.write('<?xml version="1.0" encoding="utf-8"?>\n' -                                '<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n') +                                '<Project ToolsVersion="%s" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n' % +                                self.versionstr)          self.PrintSourceFiles()          self.filters_file.write('</Project>')          self.filters_file.close() -        self.file.write('\t<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n' +        self.file.write('\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />\n'                          '\t<ImportGroup Label="ExtensionTargets">\n'                          '\t</ImportGroup>\n'                          '</Project>\n') @@ -1236,10 +1298,10 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):          if self.nokeep == 0:              # now we pickle some data and add it to the file -- MSDEV will ignore it.              pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) -            pdata = base64.encodestring(pdata).decode() +            pdata = base64.b64encode(pdata).decode()              self.file.write('<!-- SCons Data:\n' + pdata + '\n')              pdata = pickle.dumps(self.sources,PICKLE_PROTOCOL) -            pdata = base64.encodestring(pdata).decode() +            pdata = base64.b64encode(pdata).decode()              self.file.write(pdata + '-->\n')      def printFilters(self, hierarchy, name): @@ -1287,7 +1349,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):                        'Other Files': ''}          cats = sorted([k for k in list(categories.keys()) if self.sources[k]], -		              key = lambda a: a.lower()) +                      key = lambda a: a.lower())          # print vcxproj.filters file first          self.filters_file.write('\t<ItemGroup>\n') @@ -1423,7 +1485,7 @@ class _GenerateV7DSW(_DSWGenerator):          def AddConfig(self, variant, dswfile=dswfile):              config = Config() -            match = re.match('(.*)\|(.*)', variant) +            match = re.match(r'(.*)\|(.*)', variant)              if match:                  config.variant = match.group(1)                  config.platform = match.group(2) @@ -1446,13 +1508,16 @@ class _GenerateV7DSW(_DSWGenerator):          self.platforms = []          for key in list(self.configs.keys()):              platform = self.configs[key].platform -            if not platform in self.platforms: +            if platform not 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) +                if SCons.Util.splitext(name)[1] == '.filters': +                    # Ignore .filters project files +                    continue                  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 @@ -1486,6 +1551,7 @@ class _GenerateV7DSW(_DSWGenerator):          while line:              line = dswfile.readline()              datas = datas + line +        dswfile.close()          # OK, we've found our little pickled cache of data.          try: @@ -1501,7 +1567,13 @@ class _GenerateV7DSW(_DSWGenerator):      def PrintSolution(self):          """Writes a solution file"""          self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n' % self.versionstr) -        if self.version_num >= 12.0: +        if self.version_num >= 14.2: +            # Visual Studio 2019 is considered to be version 16. +            self.file.write('# Visual Studio 16\n') +        elif self.version_num > 14.0: +            # Visual Studio 2015 and 2017 are both considered to be version 15. +            self.file.write('# Visual Studio 15\n') +        elif self.version_num >= 12.0:              self.file.write('# Visual Studio 14\n')          elif self.version_num >= 11.0:              self.file.write('# Visual Studio 11\n') @@ -1519,7 +1591,7 @@ class _GenerateV7DSW(_DSWGenerator):                  name = base              self.file.write('Project("%s") = "%s", "%s", "%s"\n'                              % (external_makefile_guid, name, dspinfo['SLN_RELATIVE_FILE_PATH'], dspinfo['GUID'])) -            if self.version_num >= 7.1 and self.version_num < 8.0: +            if 7.1 <= self.version_num < 8.0:                  self.file.write('\tProjectSection(ProjectDependencies) = postProject\n'                                  '\tEndProjectSection\n')              self.file.write('EndProject\n') @@ -1610,7 +1682,7 @@ class _GenerateV7DSW(_DSWGenerator):          self.file.write('EndGlobal\n')          if self.nokeep == 0:              pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) -            pdata = base64.encodestring(pdata).decode() +            pdata = base64.b64encode(pdata).decode()              self.file.write(pdata)              self.file.write('\n') @@ -1720,7 +1792,7 @@ def GenerateProject(target, source, env):      dspfile = builddspfile.srcnode()      # this detects whether or not we're using a VariantDir -    if not dspfile is builddspfile: +    if dspfile is not builddspfile:          try:              bdsp = open(str(builddspfile), "w+")          except IOError as detail: @@ -1728,6 +1800,7 @@ def GenerateProject(target, source, env):              raise          bdsp.write("This is just a placeholder file.\nThe real project file is here:\n%s\n" % dspfile.get_abspath()) +        bdsp.close()      GenerateDSP(dspfile, source, env) @@ -1735,7 +1808,7 @@ def GenerateProject(target, source, env):          builddswfile = target[1]          dswfile = builddswfile.srcnode() -        if not dswfile is builddswfile: +        if dswfile is not builddswfile:              try:                  bdsw = open(str(builddswfile), "w+") @@ -1744,6 +1817,7 @@ def GenerateProject(target, source, env):                  raise              bdsw.write("This is just a placeholder file.\nThe real workspace file is here:\n%s\n" % dswfile.get_abspath()) +            bdsw.close()          GenerateDSW(dswfile, source, env) @@ -1771,11 +1845,10 @@ def projectEmitter(target, source, env):          # Project file depends on CPPDEFINES and CPPPATH          preprocdefs = xmlify(';'.join(processDefines(env.get('CPPDEFINES', [])))) -        includepath_Dirs = processIncludes(env.get('CPPPATH', []), env, None, None) -        includepath = xmlify(';'.join([str(x) for x in includepath_Dirs])) +        includepath = xmlify(';'.join(processIncludes(env.get('CPPPATH', []), env, None, None)))          source = source + "; ppdefs:%s incpath:%s"%(preprocdefs, includepath) -        if 'buildtarget' in env and env['buildtarget'] != None: +        if 'buildtarget' in env and env['buildtarget'] is not None:              if SCons.Util.is_String(env['buildtarget']):                  source = source + ' "%s"' % env['buildtarget']              elif SCons.Util.is_List(env['buildtarget']): @@ -1789,7 +1862,7 @@ def projectEmitter(target, source, env):                  try: source = source + ' "%s"' % env['buildtarget'].get_abspath()                  except AttributeError: raise SCons.Errors.InternalError("buildtarget can be a string, a node, a list of strings or nodes, or None") -        if 'outdir' in env and env['outdir'] != None: +        if 'outdir' in env and env['outdir'] is not None:              if SCons.Util.is_String(env['outdir']):                  source = source + ' "%s"' % env['outdir']              elif SCons.Util.is_List(env['outdir']): @@ -1952,8 +2025,14 @@ def generate(env):              default_MSVS_SConscript = env.File('SConstruct')          env['MSVSSCONSCRIPT'] = default_MSVS_SConscript -    env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, getExecScriptMain(env)) -    env['MSVSSCONSFLAGS'] = '-C "${MSVSSCONSCRIPT.dir.get_abspath()}" -f ${MSVSSCONSCRIPT.name}' +    # Allow consumers to provide their own versions of MSVSSCONS and +    # MSVSSCONSFLAGS. This helps support consumers who use wrapper scripts to +    # invoke scons. +    if 'MSVSSCONS' not in env: +        env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, getExecScriptMain(env)) +    if 'MSVSSCONSFLAGS' not in env: +        env['MSVSSCONSFLAGS'] = '-C "${MSVSSCONSCRIPT.dir.get_abspath()}" -f ${MSVSSCONSCRIPT.name}' +      env['MSVSSCONSCOM'] = '$MSVSSCONS $MSVSSCONSFLAGS'      env['MSVSBUILDCOM'] = '$MSVSSCONSCOM "$MSVSBUILDTARGET"'      env['MSVSREBUILDCOM'] = '$MSVSSCONSCOM "$MSVSBUILDTARGET"' @@ -1990,7 +2069,7 @@ def generate(env):      env['SCONS_HOME'] = os.environ.get('SCONS_HOME')  def exists(env): -    return msvc_exists() +    return msvc_exists(env)  # Local Variables:  # tab-width:4  | 
