1 #!/usr/bin/env python 2 # 3 # Copyright 2012 the V8 project authors. All rights reserved. 4 # Redistribution and use in source and binary forms, with or without 5 # modification, are permitted provided that the following conditions are 6 # met: 7 # 8 # * Redistributions of source code must retain the above copyright 9 # notice, this list of conditions and the following disclaimer. 10 # * Redistributions in binary form must reproduce the above 11 # copyright notice, this list of conditions and the following 12 # disclaimer in the documentation and/or other materials provided 13 # with the distribution. 14 # * Neither the name of Google Inc. nor the names of its 15 # contributors may be used to endorse or promote products derived 16 # from this software without specific prior written permission. 17 # 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 # This script is wrapper for V8 that adds some support for how GYP 31 # is invoked by V8 beyond what can be done in the gclient hooks. 32 33 import glob 34 import os 35 import platform 36 import shlex 37 import sys 38 39 script_dir = os.path.dirname(os.path.realpath(__file__)) 40 v8_root = os.path.abspath(os.path.join(script_dir, os.pardir)) 41 42 sys.path.insert(0, os.path.join(v8_root, 'build', 'gyp', 'pylib')) 43 import gyp 44 45 # Add paths so that pymod_do_main(...) can import files. 46 sys.path.insert( 47 1, os.path.abspath(os.path.join(v8_root, 'tools', 'generate_shim_headers'))) 48 49 50 def apply_gyp_environment(file_path=None): 51 """ 52 Reads in a *.gyp_env file and applies the valid keys to os.environ. 53 """ 54 if not file_path or not os.path.exists(file_path): 55 return 56 file_contents = open(file_path).read() 57 try: 58 file_data = eval(file_contents, {'__builtins__': None}, None) 59 except SyntaxError, e: 60 e.filename = os.path.abspath(file_path) 61 raise 62 supported_vars = ( 'V8_GYP_FILE', 63 'V8_GYP_SYNTAX_CHECK', 64 'GYP_DEFINES', 65 'GYP_GENERATOR_FLAGS', 66 'GYP_GENERATOR_OUTPUT', ) 67 for var in supported_vars: 68 val = file_data.get(var) 69 if val: 70 if var in os.environ: 71 print 'INFO: Environment value for "%s" overrides value in %s.' % ( 72 var, os.path.abspath(file_path) 73 ) 74 else: 75 os.environ[var] = val 76 77 78 def additional_include_files(args=[]): 79 """ 80 Returns a list of additional (.gypi) files to include, without 81 duplicating ones that are already specified on the command line. 82 """ 83 # Determine the include files specified on the command line. 84 # This doesn't cover all the different option formats you can use, 85 # but it's mainly intended to avoid duplicating flags on the automatic 86 # makefile regeneration which only uses this format. 87 specified_includes = set() 88 for arg in args: 89 if arg.startswith('-I') and len(arg) > 2: 90 specified_includes.add(os.path.realpath(arg[2:])) 91 92 result = [] 93 def AddInclude(path): 94 if os.path.realpath(path) not in specified_includes: 95 result.append(path) 96 97 # Always include standalone.gypi 98 AddInclude(os.path.join(v8_root, 'build', 'standalone.gypi')) 99 100 # Optionally add supplemental .gypi files if present. 101 supplements = glob.glob(os.path.join(v8_root, '*', 'supplement.gypi')) 102 for supplement in supplements: 103 AddInclude(supplement) 104 105 return result 106 107 108 def run_gyp(args): 109 rc = gyp.main(args) 110 if rc != 0: 111 print 'Error running GYP' 112 sys.exit(rc) 113 114 115 if __name__ == '__main__': 116 args = sys.argv[1:] 117 118 if 'SKIP_V8_GYP_ENV' not in os.environ: 119 # Update the environment based on v8.gyp_env 120 gyp_env_path = os.path.join(os.path.dirname(v8_root), 'v8.gyp_env') 121 apply_gyp_environment(gyp_env_path) 122 123 # This could give false positives since it doesn't actually do real option 124 # parsing. Oh well. 125 gyp_file_specified = False 126 for arg in args: 127 if arg.endswith('.gyp'): 128 gyp_file_specified = True 129 break 130 131 # If we didn't get a file, check an env var, and then fall back to 132 # assuming 'all.gyp' from the same directory as the script. 133 if not gyp_file_specified: 134 gyp_file = os.environ.get('V8_GYP_FILE') 135 if gyp_file: 136 # Note that V8_GYP_FILE values can't have backslashes as 137 # path separators even on Windows due to the use of shlex.split(). 138 args.extend(shlex.split(gyp_file)) 139 else: 140 args.append(os.path.join(script_dir, 'all.gyp')) 141 142 args.extend(['-I' + i for i in additional_include_files(args)]) 143 144 # There shouldn't be a circular dependency relationship between .gyp files 145 args.append('--no-circular-check') 146 147 # Set the GYP DEPTH variable to the root of the V8 project. 148 args.append('--depth=' + os.path.relpath(v8_root)) 149 150 # If V8_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check 151 # to enfore syntax checking. 152 syntax_check = os.environ.get('V8_GYP_SYNTAX_CHECK') 153 if syntax_check and int(syntax_check): 154 args.append('--check') 155 156 print 'Updating projects from gyp files...' 157 sys.stdout.flush() 158 159 # Generate for the architectures supported on the given platform. 160 gyp_args = list(args) 161 gyp_generators = os.environ.get('GYP_GENERATORS') 162 if platform.system() == 'Linux' and gyp_generators != 'ninja': 163 # Work around for crbug.com/331475. 164 for f in glob.glob(os.path.join(v8_root, 'out', 'Makefile.*')): 165 os.unlink(f) 166 # --generator-output defines where the Makefile goes. 167 gyp_args.append('--generator-output=out') 168 # -Goutput_dir defines where the build output goes, relative to the 169 # Makefile. Set it to . so that the build output doesn't end up in out/out. 170 gyp_args.append('-Goutput_dir=.') 171 run_gyp(gyp_args) 172