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 Chromium 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 gyp_helper 12 import os 13 import shlex 14 import subprocess 15 import sys 16 17 script_dir = os.path.dirname(os.path.realpath(__file__)) 18 chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir)) 19 20 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib')) 21 import gyp 22 23 # Add paths so that pymod_do_main(...) can import files. 24 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers')) 25 sys.path.insert(1, os.path.join(chrome_src, 'tools', 'grit')) 26 sys.path.insert(1, os.path.join(chrome_src, 'chrome', 'tools', 'build')) 27 sys.path.insert(1, os.path.join(chrome_src, 'native_client', 'build')) 28 sys.path.insert(1, os.path.join(chrome_src, 'remoting', 'tools', 'build')) 29 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit', 30 'Source', 'core', 'scripts')) 31 # TODO(adamk): Remove this line once core.gyp is no longer a directory 32 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit', 33 'Source', 'core', 'core.gyp', 'scripts')) 34 35 36 # On Windows, Psyco shortens warm runs of build/gyp_chromium by about 37 # 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70 38 # seconds. Conversely, memory usage of build/gyp_chromium with Psyco 39 # maxes out at about 158 MB vs. 132 MB without it. 40 # 41 # Psyco uses native libraries, so we need to load a different 42 # installation depending on which OS we are running under. It has not 43 # been tested whether using Psyco on our Mac and Linux builds is worth 44 # it (the GYP running time is a lot shorter, so the JIT startup cost 45 # may not be worth it). 46 if sys.platform == 'win32': 47 try: 48 sys.path.insert(0, os.path.join(chrome_src, 'third_party', 'psyco_win32')) 49 import psyco 50 except: 51 psyco = None 52 else: 53 psyco = None 54 55 def additional_include_files(args=[]): 56 """ 57 Returns a list of additional (.gypi) files to include, without 58 duplicating ones that are already specified on the command line. 59 """ 60 # Determine the include files specified on the command line. 61 # This doesn't cover all the different option formats you can use, 62 # but it's mainly intended to avoid duplicating flags on the automatic 63 # makefile regeneration which only uses this format. 64 specified_includes = set() 65 for arg in args: 66 if arg.startswith('-I') and len(arg) > 2: 67 specified_includes.add(os.path.realpath(arg[2:])) 68 69 result = [] 70 def AddInclude(path): 71 if os.path.realpath(path) not in specified_includes: 72 result.append(path) 73 74 # Always include common.gypi. 75 AddInclude(os.path.join(script_dir, 'common.gypi')) 76 77 # Optionally add supplemental .gypi files if present. 78 supplements = glob.glob(os.path.join(chrome_src, '*', 'supplement.gypi')) 79 for supplement in supplements: 80 AddInclude(supplement) 81 82 return result 83 84 if __name__ == '__main__': 85 args = sys.argv[1:] 86 87 # Use the Psyco JIT if available. 88 if psyco: 89 psyco.profile() 90 print "Enabled Psyco JIT." 91 92 # Fall back on hermetic python if we happen to get run under cygwin. 93 # TODO(bradnelson): take this out once this issue is fixed: 94 # http://code.google.com/p/gyp/issues/detail?id=177 95 if sys.platform == 'cygwin': 96 python_dir = os.path.join(chrome_src, 'third_party', 'python_26') 97 env = os.environ.copy() 98 env['PATH'] = python_dir + os.pathsep + env.get('PATH', '') 99 p = subprocess.Popen( 100 [os.path.join(python_dir, 'python.exe')] + sys.argv, 101 env=env, shell=False) 102 p.communicate() 103 sys.exit(p.returncode) 104 105 gyp_helper.apply_chromium_gyp_env() 106 107 # This could give false positives since it doesn't actually do real option 108 # parsing. Oh well. 109 gyp_file_specified = False 110 for arg in args: 111 if arg.endswith('.gyp'): 112 gyp_file_specified = True 113 break 114 115 # If we didn't get a file, check an env var, and then fall back to 116 # assuming 'all.gyp' from the same directory as the script. 117 if not gyp_file_specified: 118 gyp_file = os.environ.get('CHROMIUM_GYP_FILE') 119 if gyp_file: 120 # Note that CHROMIUM_GYP_FILE values can't have backslashes as 121 # path separators even on Windows due to the use of shlex.split(). 122 args.extend(shlex.split(gyp_file)) 123 else: 124 args.append(os.path.join(script_dir, 'all.gyp')) 125 126 args.extend(['-I' + i for i in additional_include_files(args)]) 127 128 # There shouldn't be a circular dependency relationship between .gyp files, 129 # but in Chromium's .gyp files, on non-Mac platforms, circular relationships 130 # currently exist. The check for circular dependencies is currently 131 # bypassed on other platforms, but is left enabled on the Mac, where a 132 # violation of the rule causes Xcode to misbehave badly. 133 # TODO(mark): Find and kill remaining circular dependencies, and remove this 134 # option. http://crbug.com/35878. 135 # TODO(tc): Fix circular dependencies in ChromiumOS then add linux2 to the 136 # list. 137 if sys.platform not in ('darwin',): 138 args.append('--no-circular-check') 139 140 # Default to ninja on linux, but only if no generator has explicitly been set. 141 # . -f / --format has precedence over the env var, no need to check for it 142 # . set the env var only if it hasn't been set yet 143 # . chromium.gyp_env has been applied to os.environ at this point already 144 if sys.platform.startswith('linux') and not os.environ.get('GYP_GENERATORS'): 145 os.environ['GYP_GENERATORS'] = 'ninja' 146 147 # If CHROMIUM_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check 148 # to enfore syntax checking. 149 syntax_check = os.environ.get('CHROMIUM_GYP_SYNTAX_CHECK') 150 if syntax_check and int(syntax_check): 151 args.append('--check') 152 153 print 'Updating projects from gyp files...' 154 sys.stdout.flush() 155 156 # Off we go... 157 sys.exit(gyp.main(args)) 158