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'))
29 # Assume this file is in a one-level-deep subdirectory of the source root.
30 SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
32 # Add paths so that pymod_do_main(...) can import files.
33 sys.path.insert(1, os.path.join(chrome_src, 'tools'))
34 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
35 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit'))
36 sys.path.insert(1, os.path.join(chrome_src, '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',
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')]
86 def GetGypVars(supplemental_files):
87 """Returns a dictionary of all GYP vars."""
88 # Find the .gyp directory in the user's home directory.
89 home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
91 home_dot_gyp = os.path.expanduser(home_dot_gyp)
94 if sys.platform in ('cygwin', 'win32'):
95 home_vars.append('USERPROFILE')
96 for home_var in home_vars:
97 home = os.getenv(home_var)
99 home_dot_gyp = os.path.join(home, '.gyp')
100 if not os.path.exists(home_dot_gyp):
106 include_gypi = os.path.join(home_dot_gyp, "include.gypi")
107 if os.path.exists(include_gypi):
108 supplemental_files += [include_gypi]
110 # GYP defines from the supplemental.gypi files.
112 for supplement in supplemental_files:
113 with open(supplement, 'r') as f:
115 file_data = eval(f.read(), {'__builtins__': None}, None)
116 except SyntaxError, e:
117 e.filename = os.path.abspath(supplement)
119 variables = file_data.get('variables', [])
121 supp_items += [(v, str(variables[v]))]
123 # GYP defines from the environment.
124 env_items = ProcessGypDefinesItems(
125 shlex.split(os.environ.get('GYP_DEFINES', '')))
127 # GYP defines from the command line. We can't use optparse since we want
128 # to ignore all arguments other than "-D".
129 cmdline_input_items = []
130 for i in range(len(sys.argv))[1:]:
131 if sys.argv[i].startswith('-D'):
132 if sys.argv[i] == '-D' and i + 1 < len(sys.argv):
133 cmdline_input_items += [sys.argv[i + 1]]
134 elif len(sys.argv[i]) > 2:
135 cmdline_input_items += [sys.argv[i][2:]]
136 cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
138 vars_dict = dict(supp_items + env_items + cmdline_items)
141 def GetOutputDirectory():
142 """Returns the output directory that GYP will use."""
143 # GYP generator flags from the command line. We can't use optparse since we
144 # want to ignore all arguments other than "-G".
145 needle = '-Goutput_dir='
146 cmdline_input_items = []
147 for item in sys.argv[1:]:
148 if item.startswith(needle):
149 return item[len(needle):]
151 env_items = shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
152 needle = 'output_dir='
153 for item in env_items:
154 if item.startswith(needle):
155 return item[len(needle):]
160 def additional_include_files(supplemental_files, args=[]):
162 Returns a list of additional (.gypi) files to include, without duplicating
163 ones that are already specified on the command line. The list of supplemental
164 include files is passed in as an argument.
166 # Determine the include files specified on the command line.
167 # This doesn't cover all the different option formats you can use,
168 # but it's mainly intended to avoid duplicating flags on the automatic
169 # makefile regeneration which only uses this format.
170 specified_includes = set()
172 if arg.startswith('-I') and len(arg) > 2:
173 specified_includes.add(os.path.realpath(arg[2:]))
176 def AddInclude(path):
177 if os.path.realpath(path) not in specified_includes:
180 # Include xwalk common.gypi to effect chromium source tree.
181 AddInclude(os.path.join(xwalk_dir, 'build', 'common.gypi'))
183 # Always include common.gypi.
184 AddInclude(os.path.join(chrome_src, 'build', 'common.gypi'))
186 # Optionally add supplemental .gypi files if present.
187 for supplement in supplemental_files:
188 AddInclude(supplement)
193 if __name__ == '__main__':
196 if int(os.environ.get('GYP_CHROMIUM_NO_ACTION', 0)):
197 print 'Skipping gyp_chromium due to GYP_CHROMIUM_NO_ACTION env var.'
200 # Support external media types capability such as MP4/MP3.
201 args = list(set(args))
203 ip_media_codecs = False # Default: no third-party codecs be build in.
205 if arg.startswith('-Dproprietary_codecs') or arg.startswith('-Dffmpeg_branding'):
207 elif arg == '-Dmediacodecs_EULA=1':
208 ip_media_codecs = True # Exception: mediacodecs_EULA be enabled.
213 args.append('-Dproprietary_codecs=1')
215 # Triggering media playback dynamically with third-party codecs by owner.
216 if ip_media_codecs == True:
217 args.append('-Dffmpeg_branding=Chrome')
219 # Use the Psyco JIT if available.
222 print "Enabled Psyco JIT."
224 # Fall back on hermetic python if we happen to get run under cygwin.
225 # TODO(bradnelson): take this out once this issue is fixed:
226 # http://code.google.com/p/gyp/issues/detail?id=177
227 if sys.platform == 'cygwin':
228 import find_depot_tools
229 depot_tools_path = find_depot_tools.add_depot_tools_to_path()
230 python_dir = sorted(glob.glob(os.path.join(depot_tools_path,
231 'python2*_bin')))[-1]
232 env = os.environ.copy()
233 env['PATH'] = python_dir + os.pathsep + env.get('PATH', '')
234 p = subprocess.Popen(
235 [os.path.join(python_dir, 'python.exe')] + sys.argv,
236 env=env, shell=False)
238 sys.exit(p.returncode)
240 gyp_helper.apply_chromium_gyp_env()
242 # This could give false positives since it doesn't actually do real option
244 gyp_file_specified = False
246 if arg.endswith('.gyp'):
247 gyp_file_specified = True
250 # If we didn't get a file, check an env var, and then fall back to
251 # assuming 'all.gyp' from the same directory as the script.
252 if not gyp_file_specified:
253 gyp_file = os.environ.get('CHROMIUM_GYP_FILE')
255 # Note that CHROMIUM_GYP_FILE values can't have backslashes as
256 # path separators even on Windows due to the use of shlex.split().
257 args.extend(shlex.split(gyp_file))
259 args.append(os.path.join(xwalk_dir, 'xwalk.gyp'))
261 # There shouldn't be a circular dependency relationship between .gyp files,
262 # but in Chromium's .gyp files, on non-Mac platforms, circular relationships
263 # currently exist. The check for circular dependencies is currently
264 # bypassed on other platforms, but is left enabled on the Mac, where a
265 # violation of the rule causes Xcode to misbehave badly.
266 # TODO(mark): Find and kill remaining circular dependencies, and remove this
267 # option. http://crbug.com/35878.
268 # TODO(tc): Fix circular dependencies in ChromiumOS then add linux2 to the
270 # TODO(tmpsantos): Make runtime a proper module and enable the circular check
272 args.append('--no-circular-check')
274 # We explicitly don't support the make gyp generator (crbug.com/348686). Be
275 # nice and fail here, rather than choking in gyp.
276 if re.search(r'(^|,|\s)make($|,|\s)', os.environ.get('GYP_GENERATORS', '')):
277 print 'Error: make gyp generator not supported (check GYP_GENERATORS).'
280 # Default to ninja on linux and windows, but only if no generator has
281 # explicitly been set.
282 # Also default to ninja on mac, but only when not building chrome/ios.
283 # . -f / --format has precedence over the env var, no need to check for it
284 # . set the env var only if it hasn't been set yet
285 # . chromium.gyp_env has been applied to os.environ at this point already
286 if sys.platform.startswith(('linux', 'win', 'freebsd')) and \
287 not os.environ.get('GYP_GENERATORS'):
288 os.environ['GYP_GENERATORS'] = 'ninja'
289 elif sys.platform == 'darwin' and not os.environ.get('GYP_GENERATORS') and \
290 not 'OS=ios' in os.environ.get('GYP_DEFINES', []):
291 os.environ['GYP_GENERATORS'] = 'ninja'
293 vs2013_runtime_dll_dirs = vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
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')
301 supplemental_includes = GetSupplementalFiles()
302 gyp_vars_dict = GetGypVars(supplemental_includes)
304 # Automatically turn on crosscompile support for platforms that need it.
305 # (The Chrome OS build sets CC_host / CC_target which implicitly enables
307 if all(('ninja' in os.environ.get('GYP_GENERATORS', ''),
308 gyp_vars_dict.get('OS') in ['android', 'ios'],
309 'GYP_CROSSCOMPILE' not in os.environ)):
310 os.environ['GYP_CROSSCOMPILE'] = '1'
311 if gyp_vars_dict.get('OS') == 'android':
312 args.append('--check')
315 ['-I' + i for i in additional_include_files(supplemental_includes, args)])
317 args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
319 # Enable Web Audio by default on Android x86
320 if gyp_vars_dict.get('OS') == 'android':
321 args.append('-Duse_openmax_dl_fft=1')
323 # Enable Aura by default on all platforms except Android
324 if gyp_vars_dict.get('OS') != 'android' and gyp_vars_dict.get('OS') != 'mac':
325 args.append('-Duse_aura=1')
327 if gyp_vars_dict.get('OS') == 'android':
328 args.append('-Dnotifications=1')
329 args.append('-Drelease_unwind_tables=0')
331 print 'Updating projects from gyp files...'
335 gyp_rc = gyp.main(args)
337 # Check for landmines (reasons to clobber the build). This must be run here,
338 # rather than a separate runhooks step so that any environment modifications
339 # from above are picked up.
340 print 'Running build/landmines.py...'
341 subprocess.check_call(
342 [sys.executable, os.path.join(chrome_src, 'build/landmines.py')])
344 if vs2013_runtime_dll_dirs:
345 x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
346 vs_toolchain.CopyVsRuntimeDlls(
347 os.path.join(chrome_src, GetOutputDirectory()),
348 (x86_runtime, x64_runtime))