Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / xwalk / gyp_xwalk
1 #!/usr/bin/env python
2
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.
6
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.
9
10 import glob
11 import os
12 import re
13 import shlex
14 import subprocess
15 import string
16 import sys
17
18 xwalk_dir = os.path.dirname(os.path.realpath(__file__))
19 chrome_src = os.path.abspath(os.path.join(xwalk_dir, os.pardir))
20
21 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
22 import gyp
23
24 sys.path.insert(0, os.path.join(chrome_src, 'build'))
25 import gyp_environment
26 import vs_toolchain
27
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, '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',
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
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.
49 #
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':
56   try:
57     sys.path.insert(0, os.path.join(chrome_src, 'third_party', 'psyco_win32'))
58     import psyco
59   except:
60     psyco = None
61 else:
62   psyco = None
63
64
65 def GetSupplementalFiles():
66   """Returns a list of the supplemental files that are included in all GYP
67   sources."""
68   return glob.glob(os.path.join(chrome_src, '*', 'supplement.gypi'))
69
70
71 def ProcessGypDefinesItems(items):
72   """Converts a list of strings to a list of key-value pairs."""
73   result = []
74   for item in items:
75     tokens = item.split('=', 1)
76     # Some GYP variables have hyphens, which we don't support.
77     if len(tokens) == 2:
78       result += [(tokens[0], tokens[1])]
79     else:
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')]
84   return result
85
86
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)
91   if home_dot_gyp:
92     home_dot_gyp = os.path.expanduser(home_dot_gyp)
93   if not home_dot_gyp:
94     home_vars = ['HOME']
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)
99       if home != None:
100         home_dot_gyp = os.path.join(home, '.gyp')
101         if not os.path.exists(home_dot_gyp):
102           home_dot_gyp = None
103         else:
104           break
105
106   if 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]
110
111   # GYP defines from the supplemental.gypi files.
112   supp_items = []
113   for supplement in supplemental_files:
114     with open(supplement, 'r') as f:
115       try:
116         file_data = eval(f.read(), {'__builtins__': None}, None)
117       except SyntaxError, e:
118         e.filename = os.path.abspath(supplement)
119         raise
120       variables = file_data.get('variables', [])
121       for v in variables:
122         supp_items += [(v, str(variables[v]))]
123
124   # GYP defines from the environment.
125   env_items = ProcessGypDefinesItems(
126       shlex.split(os.environ.get('GYP_DEFINES', '')))
127
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)
138
139   vars_dict = dict(supp_items + env_items + cmdline_items)
140   return vars_dict
141
142
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):]
152
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):]
158
159   return "out"
160
161
162 def additional_include_files(supplemental_files, args=[]):
163   """
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.
167   """
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()
173   for arg in args:
174     if arg.startswith('-I') and len(arg) > 2:
175       specified_includes.add(os.path.realpath(arg[2:]))
176
177   result = []
178   def AddInclude(path):
179     if os.path.realpath(path) not in specified_includes:
180       result.append(path)
181
182   # Include xwalk common.gypi to effect chromium source tree.
183   AddInclude(os.path.join(xwalk_dir, 'build', 'common.gypi'))
184
185   # Always include common.gypi.
186   AddInclude(os.path.join(chrome_src, 'build', 'common.gypi'))
187
188   # Optionally add supplemental .gypi files if present.
189   for supplement in supplemental_files:
190     AddInclude(supplement)
191
192   return result
193
194
195 if __name__ == '__main__':
196   args = sys.argv[1:]
197
198   use_analyzer = len(args) and args[0] == '--analyzer'
199   if use_analyzer:
200     args.pop(0)
201     os.environ['GYP_GENERATORS'] = 'analyzer'
202     args.append('-Gconfig_path=' + args.pop(0))
203     args.append('-Ganalyzer_output_path=' + args.pop(0))
204
205   if int(os.environ.get('GYP_CHROMIUM_NO_ACTION', 0)):
206     print 'Skipping gyp_chromium due to GYP_CHROMIUM_NO_ACTION env var.'
207     sys.exit(0)
208
209   # Support external media types capability such as MP4/MP3.
210   args = list(set(args))
211   delist = []
212   ip_media_codecs = False # Default: no third-party codecs be build in.
213   for arg in args:
214     if arg.startswith('-Dproprietary_codecs') or arg.startswith('-Dffmpeg_branding'):
215       continue
216     elif arg == '-Dmediacodecs_EULA=1':
217       ip_media_codecs = True  # Exception: mediacodecs_EULA be enabled.
218     else:
219       delist.append(arg)
220
221   args = delist
222   args.append('-Dproprietary_codecs=1')
223
224   # Triggering media playback dynamically with third-party codecs by owner.
225   if ip_media_codecs == True:
226       args.append('-Dffmpeg_branding=Chrome')
227
228   # Use the Psyco JIT if available.
229   if psyco:
230     psyco.profile()
231     print "Enabled Psyco JIT."
232
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)
246     p.communicate()
247     sys.exit(p.returncode)
248
249   # This could give false positives since it doesn't actually do real option
250   # parsing.  Oh well.
251   gyp_file_specified = False
252   for arg in args:
253     if arg.endswith('.gyp'):
254       gyp_file_specified = True
255       break
256
257   gyp_environment.SetEnvironment()
258
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')
263     if 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))
267     else:
268       args.append(os.path.join(xwalk_dir, 'xwalk.gyp'))
269
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
278   # list.
279   # TODO(tmpsantos): Make runtime a proper module and enable the circular check
280   # back for Mac.
281   args.append('--no-circular-check')
282
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).'
287     sys.exit(1)
288
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')
294
295   supplemental_includes = GetSupplementalFiles()
296   gyp_vars_dict = GetGypVars(supplemental_includes)
297
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 '*****************************************************************'
308
309   # Automatically turn on crosscompile support for platforms that need it.
310   # (The Chrome OS build sets CC_host / CC_target which implicitly enables
311   # this mode.)
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')
318
319   args.extend(
320       ['-I' + i for i in additional_include_files(supplemental_includes, args)])
321
322   args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
323
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')
327
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')
331
332   if gyp_vars_dict.get('OS') == 'android':
333     args.append('-Dnotifications=1')
334     args.append('-Drelease_unwind_tables=0')
335
336   if not use_analyzer:
337     print 'Updating projects from gyp files...'
338     sys.stdout.flush()
339
340   # Off we go...
341   gyp_rc = gyp.main(args)
342
343   if not use_analyzer:
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))
350
351   sys.exit(gyp_rc)