|  | #!/usr/bin/env python | 
|  | # | 
|  | # Copyright 2018 Google Inc. | 
|  | # | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | # Generate Android.bp for Skia from GN configuration. | 
|  |  | 
|  | import argparse | 
|  | import json | 
|  | import os | 
|  | import pprint | 
|  | import string | 
|  | import subprocess | 
|  | import tempfile | 
|  |  | 
|  | parser = argparse.ArgumentParser(description='Process some cmdline flags.') | 
|  | parser.add_argument('--gn', dest='gn_cmd', default='gn') | 
|  | args = parser.parse_args() | 
|  |  | 
|  | def GenerateJSONFromGN(gn_args): | 
|  | gn_args = ' '.join(sorted('%s=%s' % (k,v) for (k,v) in gn_args.iteritems())) | 
|  | tmp = tempfile.mkdtemp() | 
|  | subprocess.check_call([args.gn_cmd, 'gen', tmp, '--args=%s' % gn_args, | 
|  | '--ide=json']) | 
|  | return json.load(open(os.path.join(tmp, 'project.json'))) | 
|  |  | 
|  | def _strip_slash(lst): | 
|  | return {str(p.lstrip('/')) for p in lst} | 
|  |  | 
|  | def GrabDependentValues(js, name, value_type, list_to_extend, exclude): | 
|  | # Grab the values from other targets that $name depends on (e.g. optional | 
|  | # Skia components, gms, tests, etc). | 
|  | for dep in js['targets'][name]['deps']: | 
|  | if 'modules' in dep: | 
|  | continue   # Modules require special handling -- skip for now. | 
|  | if 'third_party' in dep: | 
|  | continue   # We've handled all third-party DEPS as static or shared_libs. | 
|  | if 'none' in dep: | 
|  | continue   # We'll handle all cpu-specific sources manually later. | 
|  | if exclude and exclude in dep: | 
|  | continue | 
|  | list_to_extend.update(_strip_slash(js['targets'][dep].get(value_type, []))) | 
|  | GrabDependentValues(js, dep, value_type, list_to_extend, exclude) | 
|  |  | 
|  | def CleanupCFlags(cflags): | 
|  | # Only use the generated flags related to warnings. | 
|  | cflags = {s for s in cflags if s.startswith('-W')} | 
|  | # Add additional warning suppressions so we can build | 
|  | # third_party/vulkanmemoryallocator | 
|  | cflags = cflags.union([ | 
|  | "-Wno-implicit-fallthrough", | 
|  | "-Wno-missing-field-initializers", | 
|  | "-Wno-thread-safety-analysis", | 
|  | "-Wno-unused-variable", | 
|  | ]) | 
|  | # Add the rest of the flags we want. | 
|  | cflags = cflags.union([ | 
|  | "-fvisibility=hidden", | 
|  | "-D_FORTIFY_SOURCE=1", | 
|  | "-DSKIA_DLL", | 
|  | "-DSKIA_IMPLEMENTATION=1", | 
|  | "-DATRACE_TAG=ATRACE_TAG_VIEW", | 
|  | "-DSK_PRINT_CODEC_MESSAGES", | 
|  | ]) | 
|  |  | 
|  | # We need to undefine FORTIFY_SOURCE before we define it. Insert it at the | 
|  | # beginning after sorting. | 
|  | cflags = sorted(cflags) | 
|  | cflags.insert(0, "-U_FORTIFY_SOURCE") | 
|  | return cflags | 
|  |  | 
|  | def CleanupCCFlags(cflags_cc): | 
|  | # Only use the generated flags related to warnings. | 
|  | cflags_cc       = {s for s in cflags_cc      if s.startswith('-W')} | 
|  | # Add the rest of the flags we want. | 
|  | cflags_cc.add("-fexceptions") | 
|  | return cflags_cc | 
|  |  | 
|  | def _get_path_info(path, kind): | 
|  | assert path == "../src" | 
|  | assert kind == "abspath" | 
|  | # While we want absolute paths in GN, relative paths work best here. | 
|  | return "src" | 
|  |  | 
|  | def GetArchSources(opts_file): | 
|  | # For architecture specific files, it's easier to just read the same source | 
|  | # that GN does (opts.gni) rather than re-run GN once for each architecture. | 
|  |  | 
|  | # This .gni file we want to read is close enough to Python syntax | 
|  | # that we can use execfile() if we supply definitions for GN builtins. | 
|  | builtins = { 'get_path_info': _get_path_info } | 
|  | defs = {} | 
|  | execfile(opts_file, builtins, defs) | 
|  |  | 
|  | # Perform any string substitutions. | 
|  | for arch in defs: | 
|  | defs[arch] = [ p.replace('$_src', 'src') for p in defs[arch]] | 
|  |  | 
|  | return defs | 
|  |  | 
|  | def WriteUserConfig(userConfigPath, defines): | 
|  | # Most defines go into SkUserConfig.h | 
|  | defines.remove('NDEBUG')                 # Controlled by the Android build | 
|  | defines.remove('SKIA_IMPLEMENTATION=1')  # don't export this define. | 
|  | if 'WIN32_LEAN_AND_MEAN' in defines:     # Controlled by the Android build | 
|  | defines.remove('WIN32_LEAN_AND_MEAN') | 
|  | if '_HAS_EXCEPTIONS=0' in defines:       # Controlled by the Android build | 
|  | defines.remove('_HAS_EXCEPTIONS=0') | 
|  |  | 
|  | #... and all the #defines we want to put in SkUserConfig.h. | 
|  | with open(userConfigPath, 'w') as f: | 
|  | print >>f, '// DO NOT MODIFY! This file is autogenerated by gn_to_bp.py.' | 
|  | print >>f, '// If need to change a define, modify SkUserConfigManual.h' | 
|  | print >>f, '#pragma once' | 
|  | print >>f, '#include "SkUserConfigManual.h"' | 
|  | for define in sorted(defines): | 
|  | print >>f, '' | 
|  | print >>f, '#ifndef', define.split('=')[0] | 
|  | print >>f, '#define', define.replace('=', ' ', 1) | 
|  | print >>f, '#endif' |