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   if int(os.environ.get('GYP_CHROMIUM_NO_ACTION', 0)):
    122     print 'Skipping gyp_v8 due to GYP_CHROMIUM_NO_ACTION env var.'
    123     sys.exit(0)
    124 
    125   gyp_environment.set_environment()
    126 
    127   # This could give false positives since it doesn't actually do real option
    128   # parsing.  Oh well.
    129   gyp_file_specified = False
    130   for arg in args:
    131     if arg.endswith('.gyp'):
    132       gyp_file_specified = True
    133       break
    134 
    135   # If we didn't get a file, check an env var, and then fall back to
    136   # assuming 'all.gyp' from the same directory as the script.
    137   if not gyp_file_specified:
    138     gyp_file = os.environ.get('V8_GYP_FILE')
    139     if gyp_file:
    140       # Note that V8_GYP_FILE values can't have backslashes as
    141       # path separators even on Windows due to the use of shlex.split().
    142       args.extend(shlex.split(gyp_file))
    143     else:
    144       args.append(os.path.join(script_dir, 'all.gyp'))
    145 
    146   args.extend(['-I' + i for i in additional_include_files(args)])
    147 
    148   # There shouldn't be a circular dependency relationship between .gyp files
    149   args.append('--no-circular-check')
    150 
    151   # Set the GYP DEPTH variable to the root of the V8 project.
    152   args.append('--depth=' + os.path.relpath(v8_root))
    153 
    154   # If V8_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
    155   # to enfore syntax checking.
    156   syntax_check = os.environ.get('V8_GYP_SYNTAX_CHECK')
    157   if syntax_check and int(syntax_check):
    158     args.append('--check')
    159 
    160   print 'Updating projects from gyp files...'
    161   sys.stdout.flush()
    162 
    163   # Generate for the architectures supported on the given platform.
    164   gyp_args = list(args)
    165   gyp_args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
    166   gyp_generators = os.environ.get('GYP_GENERATORS', '')
    167   if platform.system() == 'Linux' and gyp_generators != 'ninja':
    168     # Work around for crbug.com/331475.
    169     for f in glob.glob(os.path.join(v8_root, 'out', 'Makefile.*')):
    170       os.unlink(f)
    171     # --generator-output defines where the Makefile goes.
    172     gyp_args.append('--generator-output=out')
    173     # -Goutput_dir defines where the build output goes, relative to the
    174     # Makefile. Set it to . so that the build output doesn't end up in out/out.
    175     gyp_args.append('-Goutput_dir=.')
    176 
    177   gyp_defines = os.environ.get('GYP_DEFINES', '')
    178 
    179   # Automatically turn on crosscompile support for platforms that need it.
    180   if all(('ninja' in gyp_generators,
    181           'OS=android' in gyp_defines,
    182           'GYP_CROSSCOMPILE' not in os.environ)):
    183     os.environ['GYP_CROSSCOMPILE'] = '1'
    184 
    185   run_gyp(gyp_args)
    186