| OLD | NEW | 
| (Empty) |  | 
 |    1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
 |    2 # Use of this source code is governed by a BSD-style license that can be | 
 |    3 # found in the LICENSE file. | 
 |    4  | 
 |    5 # This file copies the logic from GYP to find the MSVC configuration. It's not | 
 |    6 # currently used because it is too slow. We will probably build this | 
 |    7 # functionality into the C++ code in the future. | 
 |    8  | 
 |    9 """Handle version information related to Visual Stuio.""" | 
 |   10  | 
 |   11 import errno | 
 |   12 import os | 
 |   13 import re | 
 |   14 import subprocess | 
 |   15 import sys | 
 |   16  | 
 |   17 class VisualStudioVersion(object): | 
 |   18   """Information regarding a version of Visual Studio.""" | 
 |   19  | 
 |   20   def __init__(self, short_name, description, | 
 |   21                solution_version, project_version, flat_sln, uses_vcxproj, | 
 |   22                path, sdk_based, default_toolset=None): | 
 |   23     self.short_name = short_name | 
 |   24     self.description = description | 
 |   25     self.solution_version = solution_version | 
 |   26     self.project_version = project_version | 
 |   27     self.flat_sln = flat_sln | 
 |   28     self.uses_vcxproj = uses_vcxproj | 
 |   29     self.path = path | 
 |   30     self.sdk_based = sdk_based | 
 |   31     self.default_toolset = default_toolset | 
 |   32  | 
 |   33   def ShortName(self): | 
 |   34     return self.short_name | 
 |   35  | 
 |   36   def Description(self): | 
 |   37     """Get the full description of the version.""" | 
 |   38     return self.description | 
 |   39  | 
 |   40   def SolutionVersion(self): | 
 |   41     """Get the version number of the sln files.""" | 
 |   42     return self.solution_version | 
 |   43  | 
 |   44   def ProjectVersion(self): | 
 |   45     """Get the version number of the vcproj or vcxproj files.""" | 
 |   46     return self.project_version | 
 |   47  | 
 |   48   def FlatSolution(self): | 
 |   49     return self.flat_sln | 
 |   50  | 
 |   51   def UsesVcxproj(self): | 
 |   52     """Returns true if this version uses a vcxproj file.""" | 
 |   53     return self.uses_vcxproj | 
 |   54  | 
 |   55   def ProjectExtension(self): | 
 |   56     """Returns the file extension for the project.""" | 
 |   57     return self.uses_vcxproj and '.vcxproj' or '.vcproj' | 
 |   58  | 
 |   59   def Path(self): | 
 |   60     """Returns the path to Visual Studio installation.""" | 
 |   61     return self.path | 
 |   62  | 
 |   63   def ToolPath(self, tool): | 
 |   64     """Returns the path to a given compiler tool. """ | 
 |   65     return os.path.normpath(os.path.join(self.path, "VC/bin", tool)) | 
 |   66  | 
 |   67   def DefaultToolset(self): | 
 |   68     """Returns the msbuild toolset version that will be used in the absence | 
 |   69     of a user override.""" | 
 |   70     return self.default_toolset | 
 |   71  | 
 |   72   def SetupScript(self, target_arch): | 
 |   73     """Returns a command (with arguments) to be used to set up the | 
 |   74     environment.""" | 
 |   75     # Check if we are running in the SDK command line environment and use | 
 |   76     # the setup script from the SDK if so. |target_arch| should be either | 
 |   77     # 'x86' or 'x64'. | 
 |   78     assert target_arch in ('x86', 'x64') | 
 |   79     sdk_dir = os.environ.get('WindowsSDKDir') | 
 |   80     if self.sdk_based and sdk_dir: | 
 |   81       return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')), | 
 |   82               '/' + target_arch] | 
 |   83     else: | 
 |   84       # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls | 
 |   85       # vcvars32, which it can only find if VS??COMNTOOLS is set, which it | 
 |   86       # isn't always. | 
 |   87       if target_arch == 'x86': | 
 |   88         return [os.path.normpath( | 
 |   89           os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))] | 
 |   90       else: | 
 |   91         assert target_arch == 'x64' | 
 |   92         arg = 'x86_amd64' | 
 |   93         if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or | 
 |   94             os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): | 
 |   95           # Use the 64-on-64 compiler if we can. | 
 |   96           arg = 'amd64' | 
 |   97         return [os.path.normpath( | 
 |   98             os.path.join(self.path, 'VC/vcvarsall.bat')), arg] | 
 |   99  | 
 |  100  | 
 |  101 def _RegistryQueryBase(sysdir, key, value): | 
 |  102   """Use reg.exe to read a particular key. | 
 |  103  | 
 |  104   While ideally we might use the win32 module, we would like gyp to be | 
 |  105   python neutral, so for instance cygwin python lacks this module. | 
 |  106  | 
 |  107   Arguments: | 
 |  108     sysdir: The system subdirectory to attempt to launch reg.exe from. | 
 |  109     key: The registry key to read from. | 
 |  110     value: The particular value to read. | 
 |  111   Return: | 
 |  112     stdout from reg.exe, or None for failure. | 
 |  113   """ | 
 |  114   # Skip if not on Windows or Python Win32 setup issue | 
 |  115   if sys.platform not in ('win32', 'cygwin'): | 
 |  116     return None | 
 |  117   # Setup params to pass to and attempt to launch reg.exe | 
 |  118   cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'), | 
 |  119          'query', key] | 
 |  120   if value: | 
 |  121     cmd.extend(['/v', value]) | 
 |  122   p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 
 |  123   # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid | 
 |  124   # Note that the error text may be in [1] in some cases | 
 |  125   text = p.communicate()[0] | 
 |  126   # Check return code from reg.exe; officially 0==success and 1==error | 
 |  127   if p.returncode: | 
 |  128     return None | 
 |  129   return text | 
 |  130  | 
 |  131  | 
 |  132 def _RegistryQuery(key, value=None): | 
 |  133   """Use reg.exe to read a particular key through _RegistryQueryBase. | 
 |  134  | 
 |  135   First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If | 
 |  136   that fails, it falls back to System32.  Sysnative is available on Vista and | 
 |  137   up and available on Windows Server 2003 and XP through KB patch 942589. Note | 
 |  138   that Sysnative will always fail if using 64-bit python due to it being a | 
 |  139   virtual directory and System32 will work correctly in the first place. | 
 |  140  | 
 |  141   KB 942589 - http://support.microsoft.com/kb/942589/en-us. | 
 |  142  | 
 |  143   Arguments: | 
 |  144     key: The registry key. | 
 |  145     value: The particular registry value to read (optional). | 
 |  146   Return: | 
 |  147     stdout from reg.exe, or None for failure. | 
 |  148   """ | 
 |  149   text = None | 
 |  150   try: | 
 |  151     text = _RegistryQueryBase('Sysnative', key, value) | 
 |  152   except OSError, e: | 
 |  153     if e.errno == errno.ENOENT: | 
 |  154       text = _RegistryQueryBase('System32', key, value) | 
 |  155     else: | 
 |  156       raise | 
 |  157   return text | 
 |  158  | 
 |  159  | 
 |  160 def _RegistryGetValue(key, value): | 
 |  161   """Use reg.exe to obtain the value of a registry key. | 
 |  162  | 
 |  163   Args: | 
 |  164     key: The registry key. | 
 |  165     value: The particular registry value to read. | 
 |  166   Return: | 
 |  167     contents of the registry key's value, or None on failure. | 
 |  168   """ | 
 |  169   text = _RegistryQuery(key, value) | 
 |  170   if not text: | 
 |  171     return None | 
 |  172   # Extract value. | 
 |  173   match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text) | 
 |  174   if not match: | 
 |  175     return None | 
 |  176   return match.group(1) | 
 |  177  | 
 |  178  | 
 |  179 def _RegistryKeyExists(key): | 
 |  180   """Use reg.exe to see if a key exists. | 
 |  181  | 
 |  182   Args: | 
 |  183     key: The registry key to check. | 
 |  184   Return: | 
 |  185     True if the key exists | 
 |  186   """ | 
 |  187   if not _RegistryQuery(key): | 
 |  188     return False | 
 |  189   return True | 
 |  190  | 
 |  191  | 
 |  192 def _CreateVersion(name, path, sdk_based=False): | 
 |  193   """Sets up MSVS project generation. | 
 |  194  | 
 |  195   Setup is based off the GYP_MSVS_VERSION environment variable or whatever is | 
 |  196   autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is | 
 |  197   passed in that doesn't match a value in versions python will throw a error. | 
 |  198   """ | 
 |  199   if path: | 
 |  200     path = os.path.normpath(path) | 
 |  201   versions = { | 
 |  202       '2013': VisualStudioVersion('2013', | 
 |  203                                   'Visual Studio 2013', | 
 |  204                                   solution_version='13.00', | 
 |  205                                   project_version='4.0', | 
 |  206                                   flat_sln=False, | 
 |  207                                   uses_vcxproj=True, | 
 |  208                                   path=path, | 
 |  209                                   sdk_based=sdk_based, | 
 |  210                                   default_toolset='v110'), | 
 |  211       '2013e': VisualStudioVersion('2013e', | 
 |  212                                    'Visual Studio 2013', | 
 |  213                                    solution_version='13.00', | 
 |  214                                    project_version='4.0', | 
 |  215                                    flat_sln=True, | 
 |  216                                    uses_vcxproj=True, | 
 |  217                                    path=path, | 
 |  218                                    sdk_based=sdk_based, | 
 |  219                                    default_toolset='v110'), | 
 |  220       '2012': VisualStudioVersion('2012', | 
 |  221                                   'Visual Studio 2012', | 
 |  222                                   solution_version='12.00', | 
 |  223                                   project_version='4.0', | 
 |  224                                   flat_sln=False, | 
 |  225                                   uses_vcxproj=True, | 
 |  226                                   path=path, | 
 |  227                                   sdk_based=sdk_based, | 
 |  228                                   default_toolset='v110'), | 
 |  229       '2012e': VisualStudioVersion('2012e', | 
 |  230                                    'Visual Studio 2012', | 
 |  231                                    solution_version='12.00', | 
 |  232                                    project_version='4.0', | 
 |  233                                    flat_sln=True, | 
 |  234                                    uses_vcxproj=True, | 
 |  235                                    path=path, | 
 |  236                                    sdk_based=sdk_based, | 
 |  237                                    default_toolset='v110'), | 
 |  238       '2010': VisualStudioVersion('2010', | 
 |  239                                   'Visual Studio 2010', | 
 |  240                                   solution_version='11.00', | 
 |  241                                   project_version='4.0', | 
 |  242                                   flat_sln=False, | 
 |  243                                   uses_vcxproj=True, | 
 |  244                                   path=path, | 
 |  245                                   sdk_based=sdk_based), | 
 |  246       '2010e': VisualStudioVersion('2010e', | 
 |  247                                    'Visual Studio 2010', | 
 |  248                                    solution_version='11.00', | 
 |  249                                    project_version='4.0', | 
 |  250                                    flat_sln=True, | 
 |  251                                    uses_vcxproj=True, | 
 |  252                                    path=path, | 
 |  253                                    sdk_based=sdk_based), | 
 |  254       '2008': VisualStudioVersion('2008', | 
 |  255                                   'Visual Studio 2008', | 
 |  256                                   solution_version='10.00', | 
 |  257                                   project_version='9.00', | 
 |  258                                   flat_sln=False, | 
 |  259                                   uses_vcxproj=False, | 
 |  260                                   path=path, | 
 |  261                                   sdk_based=sdk_based), | 
 |  262       '2008e': VisualStudioVersion('2008e', | 
 |  263                                    'Visual Studio 2008', | 
 |  264                                    solution_version='10.00', | 
 |  265                                    project_version='9.00', | 
 |  266                                    flat_sln=True, | 
 |  267                                    uses_vcxproj=False, | 
 |  268                                    path=path, | 
 |  269                                    sdk_based=sdk_based), | 
 |  270       '2005': VisualStudioVersion('2005', | 
 |  271                                   'Visual Studio 2005', | 
 |  272                                   solution_version='9.00', | 
 |  273                                   project_version='8.00', | 
 |  274                                   flat_sln=False, | 
 |  275                                   uses_vcxproj=False, | 
 |  276                                   path=path, | 
 |  277                                   sdk_based=sdk_based), | 
 |  278       '2005e': VisualStudioVersion('2005e', | 
 |  279                                    'Visual Studio 2005', | 
 |  280                                    solution_version='9.00', | 
 |  281                                    project_version='8.00', | 
 |  282                                    flat_sln=True, | 
 |  283                                    uses_vcxproj=False, | 
 |  284                                    path=path, | 
 |  285                                    sdk_based=sdk_based), | 
 |  286   } | 
 |  287   return versions[str(name)] | 
 |  288  | 
 |  289  | 
 |  290 def _ConvertToCygpath(path): | 
 |  291   """Convert to cygwin path if we are using cygwin.""" | 
 |  292   if sys.platform == 'cygwin': | 
 |  293     p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE) | 
 |  294     path = p.communicate()[0].strip() | 
 |  295   return path | 
 |  296  | 
 |  297  | 
 |  298 def _DetectVisualStudioVersions(versions_to_check, force_express): | 
 |  299   """Collect the list of installed visual studio versions. | 
 |  300  | 
 |  301   Returns: | 
 |  302     A list of visual studio versions installed in descending order of | 
 |  303     usage preference. | 
 |  304     Base this on the registry and a quick check if devenv.exe exists. | 
 |  305     Only versions 8-10 are considered. | 
 |  306     Possibilities are: | 
 |  307       2005(e) - Visual Studio 2005 (8) | 
 |  308       2008(e) - Visual Studio 2008 (9) | 
 |  309       2010(e) - Visual Studio 2010 (10) | 
 |  310       2012(e) - Visual Studio 2012 (11) | 
 |  311       2013(e) - Visual Studio 2013 (11) | 
 |  312     Where (e) is e for express editions of MSVS and blank otherwise. | 
 |  313   """ | 
 |  314   version_to_year = { | 
 |  315       '8.0': '2005', | 
 |  316       '9.0': '2008', | 
 |  317       '10.0': '2010', | 
 |  318       '11.0': '2012', | 
 |  319       '12.0': '2013', | 
 |  320   } | 
 |  321   versions = [] | 
 |  322   for version in versions_to_check: | 
 |  323     # Old method of searching for which VS version is installed | 
 |  324     # We don't use the 2010-encouraged-way because we also want to get the | 
 |  325     # path to the binaries, which it doesn't offer. | 
 |  326     keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, | 
 |  327             r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version, | 
 |  328             r'HKLM\Software\Microsoft\VCExpress\%s' % version, | 
 |  329             r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version] | 
 |  330     for index in range(len(keys)): | 
 |  331       path = _RegistryGetValue(keys[index], 'InstallDir') | 
 |  332       if not path: | 
 |  333         continue | 
 |  334       path = _ConvertToCygpath(path) | 
 |  335       # Check for full. | 
 |  336       full_path = os.path.join(path, 'devenv.exe') | 
 |  337       express_path = os.path.join(path, 'vcexpress.exe') | 
 |  338       if not force_express and os.path.exists(full_path): | 
 |  339         # Add this one. | 
 |  340         versions.append(_CreateVersion(version_to_year[version], | 
 |  341             os.path.join(path, '..', '..'))) | 
 |  342       # Check for express. | 
 |  343       elif os.path.exists(express_path): | 
 |  344         # Add this one. | 
 |  345         versions.append(_CreateVersion(version_to_year[version] + 'e', | 
 |  346             os.path.join(path, '..', '..'))) | 
 |  347  | 
 |  348     # The old method above does not work when only SDK is installed. | 
 |  349     keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7', | 
 |  350             r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'] | 
 |  351     for index in range(len(keys)): | 
 |  352       path = _RegistryGetValue(keys[index], version) | 
 |  353       if not path: | 
 |  354         continue | 
 |  355       path = _ConvertToCygpath(path) | 
 |  356       versions.append(_CreateVersion(version_to_year[version] + 'e', | 
 |  357           os.path.join(path, '..'), sdk_based=True)) | 
 |  358  | 
 |  359   return versions | 
 |  360  | 
 |  361  | 
 |  362 def SelectVisualStudioVersion(version='auto'): | 
 |  363   """Select which version of Visual Studio projects to generate. | 
 |  364  | 
 |  365   Arguments: | 
 |  366     version: Hook to allow caller to force a particular version (vs auto). | 
 |  367   Returns: | 
 |  368     An object representing a visual studio project format version. | 
 |  369   """ | 
 |  370   # In auto mode, check environment variable for override. | 
 |  371   if version == 'auto': | 
 |  372     version = os.environ.get('GYP_MSVS_VERSION', 'auto') | 
 |  373   version_map = { | 
 |  374     'auto': ('10.0', '9.0', '8.0', '11.0'), | 
 |  375     '2005': ('8.0',), | 
 |  376     '2005e': ('8.0',), | 
 |  377     '2008': ('9.0',), | 
 |  378     '2008e': ('9.0',), | 
 |  379     '2010': ('10.0',), | 
 |  380     '2010e': ('10.0',), | 
 |  381     '2012': ('11.0',), | 
 |  382     '2012e': ('11.0',), | 
 |  383     '2013': ('12.0',), | 
 |  384     '2013e': ('12.0',), | 
 |  385   } | 
 |  386   override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') | 
 |  387   if override_path: | 
 |  388     msvs_version = os.environ.get('GYP_MSVS_VERSION') | 
 |  389     if not msvs_version or 'e' not in msvs_version: | 
 |  390       raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be ' | 
 |  391                        'set to an "e" version (e.g. 2010e)') | 
 |  392     return _CreateVersion(msvs_version, override_path, sdk_based=True) | 
 |  393   version = str(version) | 
 |  394   versions = _DetectVisualStudioVersions(version_map[version], 'e' in version) | 
 |  395   if not versions: | 
 |  396     if version == 'auto': | 
 |  397       # Default to 2005 if we couldn't find anything | 
 |  398       return _CreateVersion('2005', None) | 
 |  399     else: | 
 |  400       return _CreateVersion(version, None) | 
 |  401   return versions[0] | 
 |  402  | 
 |  403 def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out): | 
 |  404   """It's not sufficient to have the absolute path to the compiler, linker, | 
 |  405   etc. on Windows, as those tools rely on .dlls being in the PATH. We also | 
 |  406   need to support both x86 and x64 compilers within the same build (to support | 
 |  407   msvs_target_platform hackery). Different architectures require a different | 
 |  408   compiler binary, and different supporting environment variables (INCLUDE, | 
 |  409   LIB, LIBPATH). So, we extract the environment here, wrap all invocations | 
 |  410   of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which | 
 |  411   sets up the environment, and then we do not prefix the compiler with | 
 |  412   an absolute path, instead preferring something like "cl.exe" in the rule | 
 |  413   which will then run whichever the environment setup has put in the path. | 
 |  414   When the following procedure to generate environment files does not | 
 |  415   meet your requirement (e.g. for custom toolchains), you can pass | 
 |  416   "-G ninja_use_custom_environment_files" to the gyp to suppress file | 
 |  417   generation and use custom environment files prepared by yourself.""" | 
 |  418   archs = ('x86', 'x64') | 
 |  419   if generator_flags.get('ninja_use_custom_environment_files', 0): | 
 |  420     cl_paths = {} | 
 |  421     for arch in archs: | 
 |  422       cl_paths[arch] = 'cl.exe' | 
 |  423     return cl_paths | 
 |  424   vs = GetVSVersion(generator_flags) | 
 |  425   cl_paths = {} | 
 |  426   for arch in archs: | 
 |  427     # Extract environment variables for subprocesses. | 
 |  428     args = vs.SetupScript(arch) | 
 |  429     args.extend(('&&', 'set')) | 
 |  430     popen = subprocess.Popen( | 
 |  431         args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 
 |  432     variables, _ = popen.communicate() | 
 |  433     env = _ExtractImportantEnvironment(variables) | 
 |  434     env_block = _FormatAsEnvironmentBlock(env) | 
 |  435     f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') | 
 |  436     f.write(env_block) | 
 |  437     f.close() | 
 |  438  | 
 |  439     # Find cl.exe location for this architecture. | 
 |  440     args = vs.SetupScript(arch) | 
 |  441     args.extend(('&&', | 
 |  442       'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) | 
 |  443     popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) | 
 |  444     output, _ = popen.communicate() | 
 |  445     cl_paths[arch] = _ExtractCLPath(output) | 
 |  446   return cl_paths | 
 |  447  | 
 |  448 def OpenOutput(path, mode='w'): | 
 |  449   """Open |path| for writing, creating directories if necessary.""" | 
 |  450   try: | 
 |  451     os.makedirs(os.path.dirname(path)) | 
 |  452   except OSError: | 
 |  453     pass | 
 |  454   return open(path, mode) | 
 |  455  | 
 |  456 vs_version = None | 
 |  457 def GetVSVersion(generator_flags): | 
 |  458   global vs_version | 
 |  459   if not vs_version: | 
 |  460     vs_version = SelectVisualStudioVersion( | 
 |  461         generator_flags.get('msvs_version', 'auto')) | 
 |  462   return vs_version | 
 |  463  | 
 |  464 def _ExtractImportantEnvironment(output_of_set): | 
 |  465   """Extracts environment variables required for the toolchain to run from | 
 |  466   a textual dump output by the cmd.exe 'set' command.""" | 
 |  467   envvars_to_save = ( | 
 |  468       'goma_.*', # TODO(scottmg): This is ugly, but needed for goma. | 
 |  469       'include', | 
 |  470       'lib', | 
 |  471       'libpath', | 
 |  472       'path', | 
 |  473       'pathext', | 
 |  474       'systemroot', | 
 |  475       'temp', | 
 |  476       'tmp', | 
 |  477       ) | 
 |  478   env = {} | 
 |  479   for line in output_of_set.splitlines(): | 
 |  480     for envvar in envvars_to_save: | 
 |  481       if re.match(envvar + '=', line.lower()): | 
 |  482         var, setting = line.split('=', 1) | 
 |  483         if envvar == 'path': | 
 |  484           # Our own rules (for running gyp-win-tool) and other actions in | 
 |  485           # Chromium rely on python being in the path. Add the path to this | 
 |  486           # python here so that if it's not in the path when ninja is run | 
 |  487           # later, python will still be found. | 
 |  488           setting = os.path.dirname(sys.executable) + os.pathsep + setting | 
 |  489         env[var.upper()] = setting | 
 |  490         break | 
 |  491   for required in ('SYSTEMROOT', 'TEMP', 'TMP'): | 
 |  492     if required not in env: | 
 |  493       raise Exception('Environment variable "%s" ' | 
 |  494                       'required to be set to valid path' % required) | 
 |  495   return env | 
 |  496  | 
 |  497 def _FormatAsEnvironmentBlock(envvar_dict): | 
 |  498   """Format as an 'environment block' directly suitable for CreateProcess. | 
 |  499   Briefly this is a list of key=value\0, terminated by an additional \0. See | 
 |  500   CreateProcess documentation for more details.""" | 
 |  501   block = '' | 
 |  502   nul = '\0' | 
 |  503   for key, value in envvar_dict.iteritems(): | 
 |  504     block += key + '=' + value + nul | 
 |  505   block += nul | 
 |  506   return block | 
 |  507  | 
 |  508  | 
 |  509 def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags): | 
 |  510   """It's not sufficient to have the absolute path to the compiler, linker, | 
 |  511   etc. on Windows, as those tools rely on .dlls being in the PATH. We also | 
 |  512   need to support both x86 and x64 compilers within the same build (to support | 
 |  513   msvs_target_platform hackery). Different architectures require a different | 
 |  514   compiler binary, and different supporting environment variables (INCLUDE, | 
 |  515   LIB, LIBPATH). So, we extract the environment here, wrap all invocations | 
 |  516   of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which | 
 |  517   sets up the environment, and then we do not prefix the compiler with | 
 |  518   an absolute path, instead preferring something like "cl.exe" in the rule | 
 |  519   which will then run whichever the environment setup has put in the path. | 
 |  520   When the following procedure to generate environment files does not | 
 |  521   meet your requirement (e.g. for custom toolchains), you can pass | 
 |  522   "-G ninja_use_custom_environment_files" to the gyp to suppress file | 
 |  523   generation and use custom environment files prepared by yourself.""" | 
 |  524   archs = ('x86', 'x64') | 
 |  525   if generator_flags.get('ninja_use_custom_environment_files', 0): | 
 |  526     cl_paths = {} | 
 |  527     for arch in archs: | 
 |  528       cl_paths[arch] = 'cl.exe' | 
 |  529     return cl_paths | 
 |  530   vs = GetVSVersion(generator_flags) | 
 |  531   cl_paths = {} | 
 |  532   for arch in archs: | 
 |  533     # Extract environment variables for subprocesses. | 
 |  534     args = vs.SetupScript(arch) | 
 |  535     args.extend(('&&', 'set')) | 
 |  536     popen = subprocess.Popen( | 
 |  537         args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 
 |  538     variables, _ = popen.communicate() | 
 |  539     env = _ExtractImportantEnvironment(variables) | 
 |  540     env_block = _FormatAsEnvironmentBlock(env) | 
 |  541     f = OpenOutput(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb'
     ) | 
 |  542     f.write(env_block) | 
 |  543     f.close() | 
 |  544  | 
 |  545     # Find cl.exe location for this architecture. | 
 |  546     args = vs.SetupScript(arch) | 
 |  547     args.extend(('&&', | 
 |  548       'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) | 
 |  549     popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) | 
 |  550     output, _ = popen.communicate() | 
 |  551     cl_paths[arch] = _ExtractCLPath(output) | 
 |  552   return cl_paths | 
 |  553  | 
 |  554 def _ExtractCLPath(output_of_where): | 
 |  555   """Gets the path to cl.exe based on the output of calling the environment | 
 |  556   setup batch file, followed by the equivalent of `where`.""" | 
 |  557   # Take the first line, as that's the first found in the PATH. | 
 |  558   for line in output_of_where.strip().splitlines(): | 
 |  559     if line.startswith('LOC:'): | 
 |  560       return line[len('LOC:'):].strip() | 
 |  561  | 
 |  562 #print SelectVisualStudioVersion().DefaultToolset() | 
 |  563 #GenerateEnvironmentFiles("D:\\src\\src1\\src\\out\\gn\\eraseme", {}) | 
 |  564 #print '"', GetVSVersion({}).Path(), '"' | 
 |  565 print '"', GetVSVersion({}).sdk_based, '"' | 
 |  566  | 
 |  567 #------------------------------------------------------------------------------- | 
 |  568  | 
 |  569 version_info = { | 
 |  570   '2010': { | 
 |  571     'includes': [ | 
 |  572       'VC\\atlmfc\\include', | 
 |  573     ], | 
 |  574   }, | 
 |  575 } | 
| OLD | NEW |