Home | History | Annotate | Download | only in gypfiles
      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 argparse
     34 import glob
     35 import gyp_environment
     36 import os
     37 import platform
     38 import shlex
     39 import subprocess
     40 import sys
     41 import vs_toolchain
     42 
     43 script_dir = os.path.dirname(os.path.realpath(__file__))
     44 v8_root = os.path.abspath(os.path.join(script_dir, os.pardir))
     45 
     46 sys.path.insert(0, os.path.join(v8_root, 'tools', 'gyp', 'pylib'))
     47 import gyp
     48 
     49 # Add paths so that pymod_do_main(...) can import files.
     50 sys.path.insert(
     51     1, os.path.abspath(os.path.join(v8_root, 'tools', 'generate_shim_headers')))
     52 
     53 
     54 def GetOutputDirectory():
     55   """Returns the output directory that GYP will use."""
     56 
     57   # Handle command line generator flags.
     58   parser = argparse.ArgumentParser()
     59   parser.add_argument('-G', dest='genflags', default=[], action='append')
     60   genflags = parser.parse_known_args()[0].genflags
     61 
     62   # Handle generator flags from the environment.
     63   genflags += shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
     64 
     65   needle = 'output_dir='
     66   for item in genflags:
     67     if item.startswith(needle):
     68       return item[len(needle):]
     69 
     70   return 'out'
     71 
     72 
     73 def additional_include_files(args=[]):
     74   """
     75   Returns a list of additional (.gypi) files to include, without
     76   duplicating ones that are already specified on the command line.
     77   """
     78   # Determine the include files specified on the command line.
     79   # This doesn't cover all the different option formats you can use,
     80   # but it's mainly intended to avoid duplicating flags on the automatic
     81   # makefile regeneration which only uses this format.
     82   specified_includes = set()
     83   for arg in args:
     84     if arg.startswith('-I') and len(arg) > 2:
     85       specified_includes.add(os.path.realpath(arg[2:]))
     86 
     87   result = []
     88   def AddInclude(path):
     89     if os.path.realpath(path) not in specified_includes:
     90       result.append(path)
     91 
     92   # Always include standalone.gypi
     93   AddInclude(os.path.join(v8_root, 'gypfiles', 'standalone.gypi'))
     94 
     95   # Optionally add supplemental .gypi files if present.
     96   supplements = glob.glob(os.path.join(v8_root, '*', 'supplement.gypi'))
     97   for supplement in supplements:
     98     AddInclude(supplement)
     99 
    100   return result
    101 
    102 
    103 def run_gyp(args):
    104   rc = gyp.main(args)
    105 
    106   vs2013_runtime_dll_dirs = vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
    107   if vs2013_runtime_dll_dirs:
    108     x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
    109     vs_toolchain.CopyVsRuntimeDlls(
    110       os.path.join(v8_root, GetOutputDirectory()),
    111       (x86_runtime, x64_runtime))
    112 
    113   if rc != 0:
    114     print 'Error running GYP'
    115     sys.exit(rc)
    116 
    117 
    118 if __name__ == '__main__':
    119   args = sys.argv[1:]
    120 
    121   gyp_chromium_no_action = os.environ.get('GYP_CHROMIUM_NO_ACTION')
    122   if gyp_chromium_no_action == '1':
    123     print 'Skipping gyp_v8 due to GYP_CHROMIUM_NO_ACTION env var.'
    124     sys.exit(0)
    125 
    126   running_as_hook = '--running-as-hook'
    127   if running_as_hook in args and gyp_chromium_no_action != '0':
    128     print 'GYP is now disabled by default in runhooks.\n'
    129     print 'If you really want to run this, either run '
    130     print '`python gypfiles/gyp_v8` explicitly by hand '
    131     print 'or set the environment variable GYP_CHROMIUM_NO_ACTION=0.'
    132     sys.exit(0)
    133 
    134   if running_as_hook in args:
    135     args.remove(running_as_hook)
    136 
    137   gyp_environment.set_environment()
    138 
    139   # This could give false positives since it doesn't actually do real option
    140   # parsing.  Oh well.
    141   gyp_file_specified = False
    142   for arg in args:
    143     if arg.endswith('.gyp'):
    144       gyp_file_specified = True
    145       break
    146 
    147   # If we didn't get a file, check an env var, and then fall back to
    148   # assuming 'all.gyp' from the same directory as the script.
    149   if not gyp_file_specified:
    150     gyp_file = os.environ.get('V8_GYP_FILE')
    151     if gyp_file:
    152       # Note that V8_GYP_FILE values can't have backslashes as
    153       # path separators even on Windows due to the use of shlex.split().
    154       args.extend(shlex.split(gyp_file))
    155     else:
    156       args.append(os.path.join(script_dir, 'all.gyp'))
    157 
    158   args.extend(['-I' + i for i in additional_include_files(args)])
    159 
    160   # There shouldn't be a circular dependency relationship between .gyp files
    161   args.append('--no-circular-check')
    162 
    163   # Set the GYP DEPTH variable to the root of the V8 project.
    164   args.append('--depth=' + os.path.relpath(v8_root))
    165 
    166   # If V8_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
    167   # to enfore syntax checking.
    168   syntax_check = os.environ.get('V8_GYP_SYNTAX_CHECK')
    169   if syntax_check and int(syntax_check):
    170     args.append('--check')
    171 
    172   print 'Updating projects from gyp files...'
    173   sys.stdout.flush()
    174 
    175   # Generate for the architectures supported on the given platform.
    176   gyp_args = list(args)
    177   gyp_args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
    178   gyp_generators = os.environ.get('GYP_GENERATORS', '')
    179   if platform.system() == 'Linux' and gyp_generators != 'ninja':
    180     # Work around for crbug.com/331475.
    181     for f in glob.glob(os.path.join(v8_root, 'out', 'Makefile.*')):
    182       os.unlink(f)
    183     # --generator-output defines where the Makefile goes.
    184     gyp_args.append('--generator-output=out')
    185     # -Goutput_dir defines where the build output goes, relative to the
    186     # Makefile. Set it to . so that the build output doesn't end up in out/out.
    187     gyp_args.append('-Goutput_dir=.')
    188 
    189   gyp_defines = os.environ.get('GYP_DEFINES', '')
    190 
    191   # Automatically turn on crosscompile support for platforms that need it.
    192   if all(('ninja' in gyp_generators,
    193           'OS=android' in gyp_defines,
    194           'GYP_CROSSCOMPILE' not in os.environ)):
    195     os.environ['GYP_CROSSCOMPILE'] = '1'
    196 
    197   run_gyp(gyp_args)
    198