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

Side by Side Diff: build/gyp_chromium.py

Issue 2355673003: Gut gyp_chromium, common.gypi. (Closed)
Patch Set: linting Created 4 years, 3 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
« no previous file with comments | « build/common.gypi ('k') | build/gyp_chromium_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. 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 """This script is wrapper for Chromium that adds some support for how GYP 5 """This script is now only used by the closure_compilation builders."""
6 is invoked by Chromium beyond what can be done in the gclient hooks.
7 """
8 6
9 import argparse 7 import argparse
10 import gc
11 import glob 8 import glob
12 import gyp_environment 9 import gyp_environment
13 import mac_toolchain
14 import os 10 import os
15 import re
16 import shlex 11 import shlex
17 import subprocess
18 import string
19 import sys 12 import sys
20 import vs_toolchain
21 13
22 script_dir = os.path.dirname(os.path.realpath(__file__)) 14 script_dir = os.path.dirname(os.path.realpath(__file__))
23 chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir)) 15 chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
24 16
25 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib')) 17 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
26 import gyp 18 import gyp
27 19
28 # Assume this file is in a one-level-deep subdirectory of the source root.
29 SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
30
31 # Add paths so that pymod_do_main(...) can import files.
32 sys.path.insert(1, os.path.join(chrome_src, 'android_webview', 'tools'))
33 sys.path.insert(1, os.path.join(chrome_src, 'build', 'android', 'gyp'))
34 sys.path.insert(1, os.path.join(chrome_src, 'chrome', 'tools', 'build'))
35 sys.path.insert(1, os.path.join(chrome_src, 'chromecast', 'tools', 'build'))
36 sys.path.insert(1, os.path.join(chrome_src, 'ios', 'chrome', 'tools', 'build'))
37 sys.path.insert(1, os.path.join(chrome_src, 'native_client', 'build'))
38 sys.path.insert(1, os.path.join(chrome_src, 'native_client_sdk', 'src',
39 'build_tools'))
40 sys.path.insert(1, os.path.join(chrome_src, 'remoting', 'tools', 'build'))
41 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'liblouis'))
42 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit',
43 'Source', 'build', 'scripts'))
44 sys.path.insert(1, os.path.join(chrome_src, 'build'))
45 sys.path.insert(1, os.path.join(chrome_src, 'tools'))
46 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
47 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
48
49 # On Windows, Psyco shortens warm runs of build/gyp_chromium by about
50 # 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70
51 # seconds. Conversely, memory usage of build/gyp_chromium with Psyco
52 # maxes out at about 158 MB vs. 132 MB without it.
53 #
54 # Psyco uses native libraries, so we need to load a different
55 # installation depending on which OS we are running under. It has not
56 # been tested whether using Psyco on our Mac and Linux builds is worth
57 # it (the GYP running time is a lot shorter, so the JIT startup cost
58 # may not be worth it).
59 if sys.platform == 'win32':
60 try:
61 sys.path.insert(0, os.path.join(chrome_src, 'third_party', 'psyco_win32'))
62 import psyco
63 except:
64 psyco = None
65 else:
66 psyco = None
67
68
69 def GetSupplementalFiles():
70 """Returns a list of the supplemental files that are included in all GYP
71 sources."""
72 return glob.glob(os.path.join(chrome_src, '*', 'supplement.gypi'))
73
74 20
75 def ProcessGypDefinesItems(items): 21 def ProcessGypDefinesItems(items):
76 """Converts a list of strings to a list of key-value pairs.""" 22 """Converts a list of strings to a list of key-value pairs."""
77 result = [] 23 result = []
78 for item in items: 24 for item in items:
79 tokens = item.split('=', 1) 25 tokens = item.split('=', 1)
80 # Some GYP variables have hyphens, which we don't support. 26 # Some GYP variables have hyphens, which we don't support.
81 if len(tokens) == 2: 27 if len(tokens) == 2:
82 result += [(tokens[0], tokens[1])] 28 result += [(tokens[0], tokens[1])]
83 else: 29 else:
84 # No value supplied, treat it as a boolean and set it. Note that we 30 # No value supplied, treat it as a boolean and set it. Note that we
85 # use the string '1' here so we have a consistent definition whether 31 # use the string '1' here so we have a consistent definition whether
86 # you do 'foo=1' or 'foo'. 32 # you do 'foo=1' or 'foo'.
87 result += [(tokens[0], '1')] 33 result += [(tokens[0], '1')]
88 return result 34 return result
89 35
90 36
91 def GetGypVars(supplemental_files): 37 def GetSupplementalFiles():
38 return []
39
40
41 def GetGypVars(_):
92 """Returns a dictionary of all GYP vars.""" 42 """Returns a dictionary of all GYP vars."""
93 # Find the .gyp directory in the user's home directory.
94 home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
95 if home_dot_gyp:
96 home_dot_gyp = os.path.expanduser(home_dot_gyp)
97 if not home_dot_gyp:
98 home_vars = ['HOME']
99 if sys.platform in ('cygwin', 'win32'):
100 home_vars.append('USERPROFILE')
101 for home_var in home_vars:
102 home = os.getenv(home_var)
103 if home != None:
104 home_dot_gyp = os.path.join(home, '.gyp')
105 if not os.path.exists(home_dot_gyp):
106 home_dot_gyp = None
107 else:
108 break
109
110 if home_dot_gyp:
111 include_gypi = os.path.join(home_dot_gyp, "include.gypi")
112 if os.path.exists(include_gypi):
113 supplemental_files += [include_gypi]
114
115 # GYP defines from the supplemental.gypi files.
116 supp_items = []
117 for supplement in supplemental_files:
118 with open(supplement, 'r') as f:
119 try:
120 file_data = eval(f.read(), {'__builtins__': None}, None)
121 except SyntaxError, e:
122 e.filename = os.path.abspath(supplement)
123 raise
124 variables = file_data.get('variables', [])
125 for v in variables:
126 supp_items += [(v, str(variables[v]))]
127
128 # GYP defines from the environment. 43 # GYP defines from the environment.
129 env_items = ProcessGypDefinesItems( 44 env_items = ProcessGypDefinesItems(
130 shlex.split(os.environ.get('GYP_DEFINES', ''))) 45 shlex.split(os.environ.get('GYP_DEFINES', '')))
131 46
132 # GYP defines from the command line. 47 # GYP defines from the command line.
133 parser = argparse.ArgumentParser() 48 parser = argparse.ArgumentParser()
134 parser.add_argument('-D', dest='defines', action='append', default=[]) 49 parser.add_argument('-D', dest='defines', action='append', default=[])
135 cmdline_input_items = parser.parse_known_args()[0].defines 50 cmdline_input_items = parser.parse_known_args()[0].defines
136 cmdline_items = ProcessGypDefinesItems(cmdline_input_items) 51 cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
137 52
138 vars_dict = dict(supp_items + env_items + cmdline_items) 53 return dict(env_items + cmdline_items)
139 return vars_dict
140
141
142 def GetOutputDirectory():
143 """Returns the output directory that GYP will use."""
144
145 # Handle command line generator flags.
146 parser = argparse.ArgumentParser()
147 parser.add_argument('-G', dest='genflags', default=[], action='append')
148 genflags = parser.parse_known_args()[0].genflags
149
150 # Handle generator flags from the environment.
151 genflags += shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
152
153 needle = 'output_dir='
154 for item in genflags:
155 if item.startswith(needle):
156 return item[len(needle):]
157
158 return 'out'
159
160
161 def additional_include_files(supplemental_files, args=[]):
162 """
163 Returns a list of additional (.gypi) files to include, without duplicating
164 ones that are already specified on the command line. The list of supplemental
165 include files is passed in as an argument.
166 """
167 # Determine the include files specified on the command line.
168 # This doesn't cover all the different option formats you can use,
169 # but it's mainly intended to avoid duplicating flags on the automatic
170 # makefile regeneration which only uses this format.
171 specified_includes = set()
172 for arg in args:
173 if arg.startswith('-I') and len(arg) > 2:
174 specified_includes.add(os.path.realpath(arg[2:]))
175
176 result = []
177 def AddInclude(path):
178 if os.path.realpath(path) not in specified_includes:
179 result.append(path)
180
181 if os.environ.get('GYP_INCLUDE_FIRST') != None:
182 AddInclude(os.path.join(chrome_src, os.environ.get('GYP_INCLUDE_FIRST')))
183
184 # Always include common.gypi.
185 AddInclude(os.path.join(script_dir, 'common.gypi'))
186
187 # Optionally add supplemental .gypi files if present.
188 for supplement in supplemental_files:
189 AddInclude(supplement)
190
191 if os.environ.get('GYP_INCLUDE_LAST') != None:
192 AddInclude(os.path.join(chrome_src, os.environ.get('GYP_INCLUDE_LAST')))
193
194 return result
195 54
196 55
197 def main(): 56 def main():
198 # Disabling garbage collection saves about 1 second out of 16 on a Linux
199 # z620 workstation. Since this is a short-lived process it's not a problem to
200 # leak a few cyclyc references in order to spare the CPU cycles for
201 # scanning the heap.
202 gc.disable()
203
204 args = sys.argv[1:]
205
206 use_analyzer = len(args) and args[0] == '--analyzer'
207 if use_analyzer:
208 args.pop(0)
209 os.environ['GYP_GENERATORS'] = 'analyzer'
210 args.append('-Gconfig_path=' + args.pop(0))
211 args.append('-Ganalyzer_output_path=' + args.pop(0))
212
213 gyp_chromium_no_action = os.environ.get('GYP_CHROMIUM_NO_ACTION')
214 if gyp_chromium_no_action == '1':
215 print 'Skipping gyp_chromium due to GYP_CHROMIUM_NO_ACTION env var.'
216 sys.exit(0)
217
218 # Use the Psyco JIT if available.
219 if psyco:
220 psyco.profile()
221 print "Enabled Psyco JIT."
222
223 # Fall back on hermetic python if we happen to get run under cygwin.
224 # TODO(bradnelson): take this out once this issue is fixed:
225 # http://code.google.com/p/gyp/issues/detail?id=177
226 if sys.platform == 'cygwin':
227 import find_depot_tools
228 depot_tools_path = find_depot_tools.add_depot_tools_to_path()
229 python_dir = sorted(glob.glob(os.path.join(depot_tools_path,
230 'python2*_bin')))[-1]
231 env = os.environ.copy()
232 env['PATH'] = python_dir + os.pathsep + env.get('PATH', '')
233 cmd = [os.path.join(python_dir, 'python.exe')] + sys.argv
234 sys.exit(subprocess.call(cmd, env=env))
235
236 # This could give false positives since it doesn't actually do real option
237 # parsing. Oh well.
238 gyp_file_specified = any(arg.endswith('.gyp') for arg in args)
239
240 gyp_environment.SetEnvironment() 57 gyp_environment.SetEnvironment()
241 58
242 # If we didn't get a file, check an env var, and then fall back to 59 print 'Updating projects from gyp files...'
243 # assuming 'all.gyp' from the same directory as the script. 60 sys.stdout.flush()
244 if not gyp_file_specified: 61 sys.exit(gyp.main(sys.argv[1:] + [
245 gyp_file = os.environ.get('CHROMIUM_GYP_FILE') 62 '--check',
246 if gyp_file: 63 '--no-circular-check',
247 # Note that CHROMIUM_GYP_FILE values can't have backslashes as 64 '-I', os.path.join(script_dir, 'common.gypi'),
248 # path separators even on Windows due to the use of shlex.split(). 65 '-D', 'gyp_output_dir=out']))
249 args.extend(shlex.split(gyp_file))
250 else:
251 args.append(os.path.join(script_dir, 'all.gyp'))
252
253 supplemental_includes = GetSupplementalFiles()
254 gyp_vars_dict = GetGypVars(supplemental_includes)
255 # There shouldn't be a circular dependency relationship between .gyp files,
256 # but in Chromium's .gyp files, on non-Mac platforms, circular relationships
257 # currently exist. The check for circular dependencies is currently
258 # bypassed on other platforms, but is left enabled on iOS, where a violation
259 # of the rule causes Xcode to misbehave badly.
260 # TODO(mark): Find and kill remaining circular dependencies, and remove this
261 # option. http://crbug.com/35878.
262 # TODO(tc): Fix circular dependencies in ChromiumOS then add linux2 to the
263 # list.
264 if gyp_vars_dict.get('OS') != 'ios':
265 args.append('--no-circular-check')
266
267 # libtool on Mac warns about duplicate basenames in static libraries, so
268 # they're disallowed in general by gyp. We are lax on this point, so disable
269 # this check other than on Mac. GN does not use static libraries as heavily,
270 # so over time this restriction will mostly go away anyway, even on Mac.
271 # https://code.google.com/p/gyp/issues/detail?id=384
272 if sys.platform != 'darwin':
273 args.append('--no-duplicate-basename-check')
274
275 # We explicitly don't support the make gyp generator (crbug.com/348686). Be
276 # nice and fail here, rather than choking in gyp.
277 if re.search(r'(^|,|\s)make($|,|\s)', os.environ.get('GYP_GENERATORS', '')):
278 print 'Error: make gyp generator not supported (check GYP_GENERATORS).'
279 sys.exit(1)
280
281 # We explicitly don't support the native msvs gyp generator. Be nice and
282 # fail here, rather than generating broken projects.
283 if re.search(r'(^|,|\s)msvs($|,|\s)', os.environ.get('GYP_GENERATORS', '')):
284 print 'Error: msvs gyp generator not supported (check GYP_GENERATORS).'
285 print 'Did you mean to use the `msvs-ninja` generator?'
286 sys.exit(1)
287
288 # We explicitly don't support the native xcode gyp generator. Be nice and
289 # fail here, rather than generating broken projects.
290 if re.search(r'(^|,|\s)xcode($|,|\s)', os.environ.get('GYP_GENERATORS', '')):
291 print 'Error: xcode gyp generator not supported (check GYP_GENERATORS).'
292 print 'Did you mean to use the `xcode-ninja` generator?'
293 sys.exit(1)
294
295 # If CHROMIUM_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
296 # to enfore syntax checking.
297 syntax_check = os.environ.get('CHROMIUM_GYP_SYNTAX_CHECK')
298 if syntax_check and int(syntax_check):
299 args.append('--check')
300
301 # TODO(dmikurube): Remove these checks and messages after a while.
302 if ('linux_use_tcmalloc' in gyp_vars_dict or
303 'android_use_tcmalloc' in gyp_vars_dict):
304 print '*****************************************************************'
305 print '"linux_use_tcmalloc" and "android_use_tcmalloc" are deprecated!'
306 print '-----------------------------------------------------------------'
307 print 'You specify "linux_use_tcmalloc" or "android_use_tcmalloc" in'
308 print 'your GYP_DEFINES. Please switch them into "use_allocator" now.'
309 print 'See http://crbug.com/345554 for the details.'
310 print '*****************************************************************'
311
312 # Automatically turn on crosscompile support for platforms that need it.
313 # (The Chrome OS build sets CC_host / CC_target which implicitly enables
314 # this mode.)
315 if all(('ninja' in os.environ.get('GYP_GENERATORS', ''),
316 gyp_vars_dict.get('OS') in ['android', 'ios'],
317 'GYP_CROSSCOMPILE' not in os.environ)):
318 os.environ['GYP_CROSSCOMPILE'] = '1'
319 if gyp_vars_dict.get('OS') == 'android':
320 args.append('--check')
321
322 args.extend(
323 ['-I' + i for i in additional_include_files(supplemental_includes, args)])
324
325 args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
326
327 mac_toolchain_dir = mac_toolchain.GetToolchainDirectory()
328 if mac_toolchain_dir:
329 args.append('-Gmac_toolchain_dir=' + mac_toolchain_dir)
330 mac_toolchain.SetToolchainEnvironment()
331
332 running_as_hook = '--running-as-hook'
333 if running_as_hook in args and gyp_chromium_no_action != '0':
334 print 'GYP is now disabled by default in runhooks.\n'
335 print 'If you really want to run this, either run '
336 print '`python build/gyp_chromium.py` explicitly by hand'
337 print 'or set the environment variable GYP_CHROMIUM_NO_ACTION=0.'
338 sys.exit(0)
339
340 if running_as_hook in args:
341 args.remove(running_as_hook)
342
343 if not use_analyzer:
344 print 'Updating projects from gyp files...'
345 sys.stdout.flush()
346
347 # Off we go...
348 gyp_rc = gyp.main(args)
349
350 if gyp_rc == 0 and not use_analyzer:
351 vs2013_runtime_dll_dirs = vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
352 if vs2013_runtime_dll_dirs:
353 x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
354 vs_toolchain.CopyVsRuntimeDlls(
355 os.path.join(chrome_src, GetOutputDirectory()),
356 (x86_runtime, x64_runtime))
357
358 sys.exit(gyp_rc)
359 66
360 if __name__ == '__main__': 67 if __name__ == '__main__':
361 sys.exit(main()) 68 sys.exit(main())
OLDNEW
« no previous file with comments | « build/common.gypi ('k') | build/gyp_chromium_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698