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 10import argparse 11import json 12import os 13import pprint 14import string 15import subprocess 16import tempfile 17 18parser = argparse.ArgumentParser(description='Process some cmdline flags.') 19parser.add_argument('--gn', dest='gn_cmd', default='gn') 20args = parser.parse_args() 21 22def 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 29def _strip_slash(lst): 30 return {str(p.lstrip('/')) for p in lst} 31 32def 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 45def 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 64def 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 71def _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 77def 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 93def 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