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

Side by Side Diff: build/gyp_chromium.py

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

Powered by Google App Engine
This is Rietveld 408576698