3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 # This script is wrapper for Crosswalk that adds some support for how GYP
8 # is invoked by Chromium beyond what can be done in the gclient hooks.
18 xwalk_dir = os.path.dirname(os.path.realpath(__file__))
19 chrome_src = os.path.abspath(os.path.join(xwalk_dir, os.pardir))
21 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
24 sys.path.insert(0, os.path.join(chrome_src, 'build'))
25 import gyp_environment
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__)))
31 # Add paths so that pymod_do_main(...) can import files.
32 sys.path.insert(1, os.path.join(chrome_src, 'tools'))
33 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
34 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
35 sys.path.insert(1, os.path.join(chrome_src, 'chrome', 'tools', 'build'))
36 sys.path.insert(1, os.path.join(chrome_src, 'chromecast', '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',
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'))
45 # On Windows, Psyco shortens warm runs of build/gyp_chromium by about
46 # 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70
47 # seconds. Conversely, memory usage of build/gyp_chromium with Psyco
48 # maxes out at about 158 MB vs. 132 MB without it.
50 # Psyco uses native libraries, so we need to load a different
51 # installation depending on which OS we are running under. It has not
52 # been tested whether using Psyco on our Mac and Linux builds is worth
53 # it (the GYP running time is a lot shorter, so the JIT startup cost
54 # may not be worth it).
55 if sys.platform == 'win32':
57 sys.path.insert(0, os.path.join(chrome_src, 'third_party', 'psyco_win32'))
65 def GetSupplementalFiles():
66 """Returns a list of the supplemental files that are included in all GYP
68 return glob.glob(os.path.join(chrome_src, '*', 'supplement.gypi'))
71 def ProcessGypDefinesItems(items):
72 """Converts a list of strings to a list of key-value pairs."""
75 tokens = item.split('=', 1)
76 # Some GYP variables have hyphens, which we don't support.
78 result += [(tokens[0], tokens[1])]
80 # No value supplied, treat it as a boolean and set it. Note that we
81 # use the string '1' here so we have a consistent definition whether
82 # you do 'foo=1' or 'foo'.
83 result += [(tokens[0], '1')]
87 def GetGypVars(supplemental_files):
88 """Returns a dictionary of all GYP vars."""
89 # Find the .gyp directory in the user's home directory.
90 home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
92 home_dot_gyp = os.path.expanduser(home_dot_gyp)
95 if sys.platform in ('cygwin', 'win32'):
96 home_vars.append('USERPROFILE')
97 for home_var in home_vars:
98 home = os.getenv(home_var)
100 home_dot_gyp = os.path.join(home, '.gyp')
101 if not os.path.exists(home_dot_gyp):
107 include_gypi = os.path.join(home_dot_gyp, "include.gypi")
108 if os.path.exists(include_gypi):
109 supplemental_files += [include_gypi]
111 # GYP defines from the supplemental.gypi files.
113 for supplement in supplemental_files:
114 with open(supplement, 'r') as f:
116 file_data = eval(f.read(), {'__builtins__': None}, None)
117 except SyntaxError, e:
118 e.filename = os.path.abspath(supplement)
120 variables = file_data.get('variables', [])
122 supp_items += [(v, str(variables[v]))]
124 # GYP defines from the environment.
125 env_items = ProcessGypDefinesItems(
126 shlex.split(os.environ.get('GYP_DEFINES', '')))
128 # GYP defines from the command line. We can't use optparse since we want
129 # to ignore all arguments other than "-D".
130 cmdline_input_items = []
131 for i in range(len(sys.argv))[1:]:
132 if sys.argv[i].startswith('-D'):
133 if sys.argv[i] == '-D' and i + 1 < len(sys.argv):
134 cmdline_input_items += [sys.argv[i + 1]]
135 elif len(sys.argv[i]) > 2:
136 cmdline_input_items += [sys.argv[i][2:]]
137 cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
139 vars_dict = dict(supp_items + env_items + cmdline_items)
143 def GetOutputDirectory():
144 """Returns the output directory that GYP will use."""
145 # GYP generator flags from the command line. We can't use optparse since we
146 # want to ignore all arguments other than "-G".
147 needle = '-Goutput_dir='
148 cmdline_input_items = []
149 for item in sys.argv[1:]:
150 if item.startswith(needle):
151 return item[len(needle):]
153 env_items = shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
154 needle = 'output_dir='
155 for item in env_items:
156 if item.startswith(needle):
157 return item[len(needle):]
162 def additional_include_files(supplemental_files, args=[]):
164 Returns a list of additional (.gypi) files to include, without duplicating
165 ones that are already specified on the command line. The list of supplemental
166 include files is passed in as an argument.
168 # Determine the include files specified on the command line.
169 # This doesn't cover all the different option formats you can use,
170 # but it's mainly intended to avoid duplicating flags on the automatic
171 # makefile regeneration which only uses this format.
172 specified_includes = set()
174 if arg.startswith('-I') and len(arg) > 2:
175 specified_includes.add(os.path.realpath(arg[2:]))
178 def AddInclude(path):
179 if os.path.realpath(path) not in specified_includes:
182 # Include xwalk common.gypi to effect chromium source tree.
183 AddInclude(os.path.join(xwalk_dir, 'build', 'common.gypi'))
185 # Always include common.gypi.
186 AddInclude(os.path.join(chrome_src, 'build', 'common.gypi'))
188 # Optionally add supplemental .gypi files if present.
189 for supplement in supplemental_files:
190 AddInclude(supplement)
195 if __name__ == '__main__':
198 use_analyzer = len(args) and args[0] == '--analyzer'
201 os.environ['GYP_GENERATORS'] = 'analyzer'
202 args.append('-Gconfig_path=' + args.pop(0))
203 args.append('-Ganalyzer_output_path=' + args.pop(0))
205 if int(os.environ.get('GYP_CHROMIUM_NO_ACTION', 0)):
206 print 'Skipping gyp_chromium due to GYP_CHROMIUM_NO_ACTION env var.'
209 # Support external media types capability such as MP4/MP3.
210 args = list(set(args))
212 ip_media_codecs = False # Default: no third-party codecs be build in.
214 if arg.startswith('-Dproprietary_codecs') or arg.startswith('-Dffmpeg_branding'):
216 elif arg == '-Dmediacodecs_EULA=1':
217 ip_media_codecs = True # Exception: mediacodecs_EULA be enabled.
222 args.append('-Dproprietary_codecs=1')
224 # Triggering media playback dynamically with third-party codecs by owner.
225 if ip_media_codecs == True:
226 args.append('-Dffmpeg_branding=Chrome')
228 # Use the Psyco JIT if available.
231 print "Enabled Psyco JIT."
233 # Fall back on hermetic python if we happen to get run under cygwin.
234 # TODO(bradnelson): take this out once this issue is fixed:
235 # http://code.google.com/p/gyp/issues/detail?id=177
236 if sys.platform == 'cygwin':
237 import find_depot_tools
238 depot_tools_path = find_depot_tools.add_depot_tools_to_path()
239 python_dir = sorted(glob.glob(os.path.join(depot_tools_path,
240 'python2*_bin')))[-1]
241 env = os.environ.copy()
242 env['PATH'] = python_dir + os.pathsep + env.get('PATH', '')
243 p = subprocess.Popen(
244 [os.path.join(python_dir, 'python.exe')] + sys.argv,
245 env=env, shell=False)
247 sys.exit(p.returncode)
249 # This could give false positives since it doesn't actually do real option
251 gyp_file_specified = False
253 if arg.endswith('.gyp'):
254 gyp_file_specified = True
257 gyp_environment.SetEnvironment()
259 # If we didn't get a file, check an env var, and then fall back to
260 # assuming 'all.gyp' from the same directory as the script.
261 if not gyp_file_specified:
262 gyp_file = os.environ.get('CHROMIUM_GYP_FILE')
264 # Note that CHROMIUM_GYP_FILE values can't have backslashes as
265 # path separators even on Windows due to the use of shlex.split().
266 args.extend(shlex.split(gyp_file))
268 args.append(os.path.join(xwalk_dir, 'xwalk.gyp'))
270 # There shouldn't be a circular dependency relationship between .gyp files,
271 # but in Chromium's .gyp files, on non-Mac platforms, circular relationships
272 # currently exist. The check for circular dependencies is currently
273 # bypassed on other platforms, but is left enabled on the Mac, where a
274 # violation of the rule causes Xcode to misbehave badly.
275 # TODO(mark): Find and kill remaining circular dependencies, and remove this
276 # option. http://crbug.com/35878.
277 # TODO(tc): Fix circular dependencies in ChromiumOS then add linux2 to the
279 # TODO(tmpsantos): Make runtime a proper module and enable the circular check
281 args.append('--no-circular-check')
283 # We explicitly don't support the make gyp generator (crbug.com/348686). Be
284 # nice and fail here, rather than choking in gyp.
285 if re.search(r'(^|,|\s)make($|,|\s)', os.environ.get('GYP_GENERATORS', '')):
286 print 'Error: make gyp generator not supported (check GYP_GENERATORS).'
289 # If CHROMIUM_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
290 # to enfore syntax checking.
291 syntax_check = os.environ.get('CHROMIUM_GYP_SYNTAX_CHECK')
292 if syntax_check and int(syntax_check):
293 args.append('--check')
295 supplemental_includes = GetSupplementalFiles()
296 gyp_vars_dict = GetGypVars(supplemental_includes)
298 # TODO(dmikurube): Remove these checks and messages after a while.
299 if ('linux_use_tcmalloc' in gyp_vars_dict or
300 'android_use_tcmalloc' in gyp_vars_dict):
301 print '*****************************************************************'
302 print '"linux_use_tcmalloc" and "android_use_tcmalloc" are deprecated!'
303 print '-----------------------------------------------------------------'
304 print 'You specify "linux_use_tcmalloc" or "android_use_tcmalloc" in'
305 print 'your GYP_DEFINES. Please switch them into "use_allocator" now.'
306 print 'See http://crbug.com/345554 for the details.'
307 print '*****************************************************************'
309 # Automatically turn on crosscompile support for platforms that need it.
310 # (The Chrome OS build sets CC_host / CC_target which implicitly enables
312 if all(('ninja' in os.environ.get('GYP_GENERATORS', ''),
313 gyp_vars_dict.get('OS') in ['android', 'ios'],
314 'GYP_CROSSCOMPILE' not in os.environ)):
315 os.environ['GYP_CROSSCOMPILE'] = '1'
316 if gyp_vars_dict.get('OS') == 'android':
317 args.append('--check')
320 ['-I' + i for i in additional_include_files(supplemental_includes, args)])
322 args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
324 # Enable Web Audio by default on Android x86
325 if gyp_vars_dict.get('OS') == 'android':
326 args.append('-Duse_openmax_dl_fft=1')
328 # Enable Aura by default on all platforms except Android and Mac.
329 if gyp_vars_dict.get('OS') != 'android' and sys.platform not in ('darwin',):
330 args.append('-Duse_aura=1')
332 if gyp_vars_dict.get('OS') == 'android':
333 args.append('-Dnotifications=1')
334 args.append('-Drelease_unwind_tables=0')
337 print 'Updating projects from gyp files...'
341 gyp_rc = gyp.main(args)
344 vs2013_runtime_dll_dirs = vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
345 if vs2013_runtime_dll_dirs:
346 x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
347 vs_toolchain.CopyVsRuntimeDlls(
348 os.path.join(chrome_src, GetOutputDirectory()),
349 (x86_runtime, x64_runtime))