15d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger#!/usr/bin/env python 25d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger# 35d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger# Copyright 2018 Google Inc. 45d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger# 55d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger# Use of this source code is governed by a BSD-style license that can be 65d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger# found in the LICENSE file. 75d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 85d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger# Generate Android.bp for Skia from GN configuration. 95d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 105d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerimport argparse 115d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerimport json 125d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerimport os 135d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerimport pprint 145d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerimport string 155d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerimport subprocess 165d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerimport tempfile 175d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 185d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerparser = argparse.ArgumentParser(description='Process some cmdline flags.') 195d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerparser.add_argument('--gn', dest='gn_cmd', default='gn') 205d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerargs = parser.parse_args() 215d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 225d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef GenerateJSONFromGN(gn_args): 235d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger gn_args = ' '.join(sorted('%s=%s' % (k,v) for (k,v) in gn_args.iteritems())) 245d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger tmp = tempfile.mkdtemp() 255d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger subprocess.check_call([args.gn_cmd, 'gen', tmp, '--args=%s' % gn_args, 265d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger '--ide=json']) 275d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger return json.load(open(os.path.join(tmp, 'project.json'))) 285d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 295d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef _strip_slash(lst): 305d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger return {str(p.lstrip('/')) for p in lst} 315d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 325d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef GrabDependentValues(js, name, value_type, list_to_extend, exclude): 335d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Grab the values from other targets that $name depends on (e.g. optional 345d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Skia components, gms, tests, etc). 355d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger for dep in js['targets'][name]['deps']: 365d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger if 'third_party' in dep: 375d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger continue # We've handled all third-party DEPS as static or shared_libs. 385d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger if 'none' in dep: 395d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger continue # We'll handle all cpu-specific sources manually later. 405d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger if exclude and exclude in dep: 415d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger continue 425d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger list_to_extend.update(_strip_slash(js['targets'][dep].get(value_type, []))) 435d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger GrabDependentValues(js, dep, value_type, list_to_extend, exclude) 445d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 455d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef CleanupCFlags(cflags): 465d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Only use the generated flags related to warnings. 475d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger cflags = {s for s in cflags if s.startswith('-W')} 485d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Add the rest of the flags we want. 495d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger cflags = cflags.union([ 505d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger "-fvisibility=hidden", 515d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger "-D_FORTIFY_SOURCE=1", 525d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger "-DSKIA_DLL", 535d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger "-DSKIA_IMPLEMENTATION=1", 545d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger "-DATRACE_TAG=ATRACE_TAG_VIEW", 555d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger "-DSK_PRINT_CODEC_MESSAGES", 565d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger ]) 575d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 585d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # We need to undefine FORTIFY_SOURCE before we define it. Insert it at the 595d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # beginning after sorting. 605d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger cflags = sorted(cflags) 615d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger cflags.insert(0, "-U_FORTIFY_SOURCE") 625d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger return cflags 635d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 645d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef CleanupCCFlags(cflags_cc): 655d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Only use the generated flags related to warnings. 665d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger cflags_cc = {s for s in cflags_cc if s.startswith('-W')} 675d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Add the rest of the flags we want. 685d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger cflags_cc.add("-fexceptions") 695d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger return cflags_cc 705d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 715d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef _get_path_info(path, kind): 725d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger assert path == "../src" 735d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger assert kind == "abspath" 745d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # While we want absolute paths in GN, relative paths work best here. 755d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger return "src" 765d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 775d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef GetArchSources(opts_file): 785d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # For architecture specific files, it's easier to just read the same source 795d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # that GN does (opts.gni) rather than re-run GN once for each architecture. 805d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 815d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # This .gni file we want to read is close enough to Python syntax 825d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # that we can use execfile() if we supply definitions for GN builtins. 835d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger builtins = { 'get_path_info': _get_path_info } 845d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger defs = {} 855d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger execfile(opts_file, builtins, defs) 865d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 875d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Perform any string substitutions. 885d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger for arch in defs: 895d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger defs[arch] = [ p.replace('$_src', 'src') for p in defs[arch]] 905d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 915d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger return defs 925d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 935d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenbergerdef WriteUserConfig(userConfigPath, defines): 945d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger # Most defines go into SkUserConfig.h 955d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger defines.remove('NDEBUG') # Controlled by the Android build 965d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger defines.remove('SKIA_IMPLEMENTATION=1') # don't export this define. 975d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger 985d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger #... and all the #defines we want to put in SkUserConfig.h. 995d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger with open(userConfigPath, 'w') as f: 1005d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger print >>f, '// DO NOT MODIFY! This file is autogenerated by gn_to_bp.py.' 1015d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger print >>f, '// If need to change a define, modify SkUserConfigManual.h' 1025d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger print >>f, '#ifndef SkUserConfig_DEFINED' 1035d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger print >>f, '#define SkUserConfig_DEFINED' 1045d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger print >>f, '#include "SkUserConfigManual.h"' 1055d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger for define in sorted(defines): 1065d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger print >>f, ' #define', define.replace('=', ' ') 1075d3f7704bf9f3b4a075dc55b6951eec6f574c333Derek Sollenberger print >>f, '#endif//SkUserConfig_DEFINED' 108