Home | History | Annotate | Download | only in gn
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2018 Google Inc.
      4 #
      5 # Use of this source code is governed by a BSD-style license that can be
      6 # found in the LICENSE file.
      7 
      8 # Generate Android.bp for Skia from GN configuration.
      9 
     10 import argparse
     11 import json
     12 import os
     13 import pprint
     14 import string
     15 import subprocess
     16 import tempfile
     17 
     18 parser = argparse.ArgumentParser(description='Process some cmdline flags.')
     19 parser.add_argument('--gn', dest='gn_cmd', default='gn')
     20 args = parser.parse_args()
     21 
     22 def GenerateJSONFromGN(gn_args):
     23   gn_args = ' '.join(sorted('%s=%s' % (k,v) for (k,v) in gn_args.iteritems()))
     24   tmp = tempfile.mkdtemp()
     25   subprocess.check_call([args.gn_cmd, 'gen', tmp, '--args=%s' % gn_args,
     26                          '--ide=json'])
     27   return json.load(open(os.path.join(tmp, 'project.json')))
     28 
     29 def _strip_slash(lst):
     30   return {str(p.lstrip('/')) for p in lst}
     31 
     32 def GrabDependentValues(js, name, value_type, list_to_extend, exclude):
     33   # Grab the values from other targets that $name depends on (e.g. optional
     34   # Skia components, gms, tests, etc).
     35   for dep in js['targets'][name]['deps']:
     36     if 'third_party' in dep:
     37       continue   # We've handled all third-party DEPS as static or shared_libs.
     38     if 'none' in dep:
     39       continue   # We'll handle all cpu-specific sources manually later.
     40     if exclude and exclude in dep:
     41       continue
     42     list_to_extend.update(_strip_slash(js['targets'][dep].get(value_type, [])))
     43     GrabDependentValues(js, dep, value_type, list_to_extend, exclude)
     44 
     45 def CleanupCFlags(cflags):
     46   # Only use the generated flags related to warnings.
     47   cflags = {s for s in cflags if s.startswith('-W')}
     48   # Add the rest of the flags we want.
     49   cflags = cflags.union([
     50     "-fvisibility=hidden",
     51     "-D_FORTIFY_SOURCE=1",
     52     "-DSKIA_DLL",
     53     "-DSKIA_IMPLEMENTATION=1",
     54     "-DATRACE_TAG=ATRACE_TAG_VIEW",
     55     "-DSK_PRINT_CODEC_MESSAGES",
     56   ])
     57 
     58   # We need to undefine FORTIFY_SOURCE before we define it. Insert it at the
     59   # beginning after sorting.
     60   cflags = sorted(cflags)
     61   cflags.insert(0, "-U_FORTIFY_SOURCE")
     62   return cflags
     63 
     64 def CleanupCCFlags(cflags_cc):
     65   # Only use the generated flags related to warnings.
     66   cflags_cc       = {s for s in cflags_cc      if s.startswith('-W')}
     67   # Add the rest of the flags we want.
     68   cflags_cc.add("-fexceptions")
     69   return cflags_cc
     70 
     71 def _get_path_info(path, kind):
     72   assert path == "../src"
     73   assert kind == "abspath"
     74   # While we want absolute paths in GN, relative paths work best here.
     75   return "src"
     76 
     77 def GetArchSources(opts_file):
     78   # For architecture specific files, it's easier to just read the same source
     79   # that GN does (opts.gni) rather than re-run GN once for each architecture.
     80 
     81   # This .gni file we want to read is close enough to Python syntax
     82   # that we can use execfile() if we supply definitions for GN builtins.
     83   builtins = { 'get_path_info': _get_path_info }
     84   defs = {}
     85   execfile(opts_file, builtins, defs)
     86 
     87   # Perform any string substitutions.
     88   for arch in defs:
     89     defs[arch] = [ p.replace('$_src', 'src') for p in defs[arch]]
     90 
     91   return defs
     92 
     93 def WriteUserConfig(userConfigPath, defines):
     94   # Most defines go into SkUserConfig.h
     95   defines.remove('NDEBUG')                 # Controlled by the Android build
     96   defines.remove('SKIA_IMPLEMENTATION=1')  # don't export this define.
     97 
     98   #... and all the #defines we want to put in SkUserConfig.h.
     99   with open(userConfigPath, 'w') as f:
    100     print >>f, '// DO NOT MODIFY! This file is autogenerated by gn_to_bp.py.'
    101     print >>f, '// If need to change a define, modify SkUserConfigManual.h'
    102     print >>f, '#ifndef SkUserConfig_DEFINED'
    103     print >>f, '#define SkUserConfig_DEFINED'
    104     print >>f, '#include "SkUserConfigManual.h"'
    105     for define in sorted(defines):
    106       print >>f, '  #define', define.replace('=', ' ')
    107     print >>f, '#endif//SkUserConfig_DEFINED'
    108