Home | History | Annotate | Download | only in build
      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