Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: pylib/gyp/msvs_emulation.py

Issue 406523005: ninja/win: Put common msvs_system_include_dirs into %INCLUDE% (Closed) Base URL: https://chromium.googlesource.com/external/gyp.git@master
Patch Set: . Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright (c) 2012 Google Inc. All rights reserved. 1 # Copyright (c) 2012 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """ 5 """
6 This module helps emulate Visual Studio 2008 behavior on top of other 6 This module helps emulate Visual Studio 2008 behavior on top of other
7 build systems, primarily ninja. 7 build systems, primarily ninja.
8 """ 8 """
9 9
10 import os 10 import os
11 import re 11 import re
12 import subprocess 12 import subprocess
13 import sys 13 import sys
14 14
15 from gyp.common import OrderedSet
15 import gyp.MSVSVersion 16 import gyp.MSVSVersion
16 17
17 windows_quoter_regex = re.compile(r'(\\*)"') 18 windows_quoter_regex = re.compile(r'(\\*)"')
18 19
19 def QuoteForRspFile(arg): 20 def QuoteForRspFile(arg):
20 """Quote a command line argument so that it appears as one argument when 21 """Quote a command line argument so that it appears as one argument when
21 processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for 22 processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for
22 Windows programs).""" 23 Windows programs)."""
23 # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment 24 # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment
24 # threads. This is actually the quoting rules for CommandLineToArgvW, not 25 # threads. This is actually the quoting rules for CommandLineToArgvW, not
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 125 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
125 for line in p.communicate()[0].splitlines(): 126 for line in p.communicate()[0].splitlines():
126 if 'InstallPath' in line: 127 if 'InstallPath' in line:
127 dxsdk_dir = line.split(' ')[3] + "\\" 128 dxsdk_dir = line.split(' ')[3] + "\\"
128 129
129 # Cache return value 130 # Cache return value
130 _FindDirectXInstallation.dxsdk_dir = dxsdk_dir 131 _FindDirectXInstallation.dxsdk_dir = dxsdk_dir
131 return dxsdk_dir 132 return dxsdk_dir
132 133
133 134
135 def GetGlobalVSMacroEnv(vs_version):
136 """Get a dict of variables mapping internal VS macro names to their gyp
137 equivalents. Returns all variables that are independent of the target."""
138 env = {}
139 # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when
140 # Visual Studio is actually installed.
141 if vs_version.Path():
142 env['$(VSInstallDir)'] = vs_version.Path()
143 env['$(VCInstallDir)'] = os.path.join(vs_version.Path(), 'VC') + '\\'
144 # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
145 # set. This happens when the SDK is sync'd via src-internal, rather than
146 # by typical end-user installation of the SDK. If it's not set, we don't
147 # want to leave the unexpanded variable in the path, so simply strip it.
148 dxsdk_dir = _FindDirectXInstallation()
149 env['$(DXSDK_DIR)'] = dxsdk_dir if dxsdk_dir else ''
150 # Try to find an installation location for the Windows DDK by checking
151 # the WDK_DIR environment variable, may be None.
152 env['$(WDK_DIR)'] = os.environ.get('WDK_DIR', '')
153 return env
154
155
156 def ExtractSharedMSVSSystemIncludes(configs, generator_flags):
157 """Finds msvs_system_include_dirs that are common to all targets, removes
158 them from all targets, and returns an OrderedSet containing them."""
159 all_system_includes = OrderedSet(
scottmg 2014/07/20 05:18:10 I'm vaguely uneasy about differing / \ here, but I
160 configs[0].get('msvs_system_include_dirs', []))
161 for config in configs:
scottmg 2014/07/20 05:18:10 configs[1:] maybe would be clearer
Nico 2014/07/20 05:51:02 Done.
162 system_includes = config.get('msvs_system_include_dirs', [])
163 all_system_includes = all_system_includes & OrderedSet(system_includes)
164 if not all_system_includes:
165 return None
166 # Expand macros in all_system_includes.
167 env = GetGlobalVSMacroEnv(GetVSVersion(generator_flags))
168 expanded_system_includes = OrderedSet([ExpandMacros(include, env)
169 for include in all_system_includes])
170 if any(['$' in include for include in expanded_system_includes]):
171 # Some path relies on target-specific variables, bail.
172 return None
173
174 # Remove system includes shared by all targets from the targets.
175 for config in configs:
176 includes = config.get('msvs_system_include_dirs', [])
177 if includes: # Don't insert a msvs_system_include_dirs key if not needed.
178 # This must check the unexpanded includes list:
179 new_includes = [i for i in includes if i not in all_system_includes]
180 config['msvs_system_include_dirs'] = new_includes
181 return expanded_system_includes
182
183
134 class MsvsSettings(object): 184 class MsvsSettings(object):
135 """A class that understands the gyp 'msvs_...' values (especially the 185 """A class that understands the gyp 'msvs_...' values (especially the
136 msvs_settings field). They largely correpond to the VS2008 IDE DOM. This 186 msvs_settings field). They largely correpond to the VS2008 IDE DOM. This
137 class helps map those settings to command line options.""" 187 class helps map those settings to command line options."""
138 188
139 def __init__(self, spec, generator_flags): 189 def __init__(self, spec, generator_flags):
140 self.spec = spec 190 self.spec = spec
141 self.vs_version = GetVSVersion(generator_flags) 191 self.vs_version = GetVSVersion(generator_flags)
142 self.dxsdk_dir = _FindDirectXInstallation()
143
144 # Try to find an installation location for the Windows DDK by checking
145 # the WDK_DIR environment variable, may be None.
146 self.wdk_dir = os.environ.get('WDK_DIR')
147 192
148 supported_fields = [ 193 supported_fields = [
149 ('msvs_configuration_attributes', dict), 194 ('msvs_configuration_attributes', dict),
150 ('msvs_settings', dict), 195 ('msvs_settings', dict),
151 ('msvs_system_include_dirs', list), 196 ('msvs_system_include_dirs', list),
152 ('msvs_disabled_warnings', list), 197 ('msvs_disabled_warnings', list),
153 ('msvs_precompiled_header', str), 198 ('msvs_precompiled_header', str),
154 ('msvs_precompiled_source', str), 199 ('msvs_precompiled_source', str),
155 ('msvs_configuration_platform', str), 200 ('msvs_configuration_platform', str),
156 ('msvs_target_platform', str), 201 ('msvs_target_platform', str),
(...skipping 30 matching lines...) Expand all
187 '$(OutDir)\\': target_dir, 232 '$(OutDir)\\': target_dir,
188 '$(TargetDir)\\': target_dir, 233 '$(TargetDir)\\': target_dir,
189 '$(IntDir)': '$!INTERMEDIATE_DIR', 234 '$(IntDir)': '$!INTERMEDIATE_DIR',
190 '$(InputPath)': '${source}', 235 '$(InputPath)': '${source}',
191 '$(InputName)': '${root}', 236 '$(InputName)': '${root}',
192 '$(ProjectName)': self.spec['target_name'], 237 '$(ProjectName)': self.spec['target_name'],
193 '$(TargetName)': target_name, 238 '$(TargetName)': target_name,
194 '$(PlatformName)': target_platform, 239 '$(PlatformName)': target_platform,
195 '$(ProjectDir)\\': '', 240 '$(ProjectDir)\\': '',
196 } 241 }
197 # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when 242 replacements.update(GetGlobalVSMacroEnv(self.vs_version))
198 # Visual Studio is actually installed.
199 if self.vs_version.Path():
200 replacements['$(VSInstallDir)'] = self.vs_version.Path()
201 replacements['$(VCInstallDir)'] = os.path.join(self.vs_version.Path(),
202 'VC') + '\\'
203 # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
204 # set. This happens when the SDK is sync'd via src-internal, rather than
205 # by typical end-user installation of the SDK. If it's not set, we don't
206 # want to leave the unexpanded variable in the path, so simply strip it.
207 replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else ''
208 replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else ''
209 return replacements 243 return replacements
210 244
211 def ConvertVSMacros(self, s, base_to_build=None, config=None): 245 def ConvertVSMacros(self, s, base_to_build=None, config=None):
212 """Convert from VS macro names to something equivalent.""" 246 """Convert from VS macro names to something equivalent."""
213 env = self.GetVSMacroEnv(base_to_build, config=config) 247 env = self.GetVSMacroEnv(base_to_build, config=config)
214 return ExpandMacros(s, env) 248 return ExpandMacros(s, env)
215 249
216 def AdjustLibraries(self, libraries): 250 def AdjustLibraries(self, libraries):
217 """Strip -l from library if it's specified with that.""" 251 """Strip -l from library if it's specified with that."""
218 libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries] 252 libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries]
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 return block 924 return block
891 925
892 def _ExtractCLPath(output_of_where): 926 def _ExtractCLPath(output_of_where):
893 """Gets the path to cl.exe based on the output of calling the environment 927 """Gets the path to cl.exe based on the output of calling the environment
894 setup batch file, followed by the equivalent of `where`.""" 928 setup batch file, followed by the equivalent of `where`."""
895 # Take the first line, as that's the first found in the PATH. 929 # Take the first line, as that's the first found in the PATH.
896 for line in output_of_where.strip().splitlines(): 930 for line in output_of_where.strip().splitlines():
897 if line.startswith('LOC:'): 931 if line.startswith('LOC:'):
898 return line[len('LOC:'):].strip() 932 return line[len('LOC:'):].strip()
899 933
900 def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out): 934 def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags,
935 system_includes, open_out):
901 """It's not sufficient to have the absolute path to the compiler, linker, 936 """It's not sufficient to have the absolute path to the compiler, linker,
902 etc. on Windows, as those tools rely on .dlls being in the PATH. We also 937 etc. on Windows, as those tools rely on .dlls being in the PATH. We also
903 need to support both x86 and x64 compilers within the same build (to support 938 need to support both x86 and x64 compilers within the same build (to support
904 msvs_target_platform hackery). Different architectures require a different 939 msvs_target_platform hackery). Different architectures require a different
905 compiler binary, and different supporting environment variables (INCLUDE, 940 compiler binary, and different supporting environment variables (INCLUDE,
906 LIB, LIBPATH). So, we extract the environment here, wrap all invocations 941 LIB, LIBPATH). So, we extract the environment here, wrap all invocations
907 of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which 942 of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which
908 sets up the environment, and then we do not prefix the compiler with 943 sets up the environment, and then we do not prefix the compiler with
909 an absolute path, instead preferring something like "cl.exe" in the rule 944 an absolute path, instead preferring something like "cl.exe" in the rule
910 which will then run whichever the environment setup has put in the path. 945 which will then run whichever the environment setup has put in the path.
(...skipping 10 matching lines...) Expand all
921 vs = GetVSVersion(generator_flags) 956 vs = GetVSVersion(generator_flags)
922 cl_paths = {} 957 cl_paths = {}
923 for arch in archs: 958 for arch in archs:
924 # Extract environment variables for subprocesses. 959 # Extract environment variables for subprocesses.
925 args = vs.SetupScript(arch) 960 args = vs.SetupScript(arch)
926 args.extend(('&&', 'set')) 961 args.extend(('&&', 'set'))
927 popen = subprocess.Popen( 962 popen = subprocess.Popen(
928 args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 963 args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
929 variables, _ = popen.communicate() 964 variables, _ = popen.communicate()
930 env = _ExtractImportantEnvironment(variables) 965 env = _ExtractImportantEnvironment(variables)
966
967 # Inject system includes from gyp files into INCLUDE.
968 if system_includes:
969 system_includes = system_includes | OrderedSet(
970 env.get('INCLUDE', '').split(';'))
971 env['INCLUDE'] = ';'.join(system_includes)
972
931 env_block = _FormatAsEnvironmentBlock(env) 973 env_block = _FormatAsEnvironmentBlock(env)
932 f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') 974 f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb')
933 f.write(env_block) 975 f.write(env_block)
934 f.close() 976 f.close()
935 977
936 # Find cl.exe location for this architecture. 978 # Find cl.exe location for this architecture.
937 args = vs.SetupScript(arch) 979 args = vs.SetupScript(arch)
938 args.extend(('&&', 980 args.extend(('&&',
939 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) 981 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i'))
940 popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) 982 popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE)
(...skipping 28 matching lines...) Expand all
969 1011
970 # To determine processor word size on Windows, in addition to checking 1012 # To determine processor word size on Windows, in addition to checking
971 # PROCESSOR_ARCHITECTURE (which reflects the word size of the current 1013 # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
972 # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which 1014 # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
973 # contains the actual word size of the system when running thru WOW64). 1015 # contains the actual word size of the system when running thru WOW64).
974 if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or 1016 if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
975 '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')): 1017 '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
976 default_variables['MSVS_OS_BITS'] = 64 1018 default_variables['MSVS_OS_BITS'] = 64
977 else: 1019 else:
978 default_variables['MSVS_OS_BITS'] = 32 1020 default_variables['MSVS_OS_BITS'] = 32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698