#!/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. from __future__ import print_function 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 iter(gn_args.items()))) 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 '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 isinstance(exclude, str) and exclude == dep: continue if exclude and isinstance(exclude, list) and dep in exclude: 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 # Some for third_party/vulkanmemoryallocator # Some for Android's '-Wall -Werror' cflags = cflags.union([ "-Wno-implicit-fallthrough", "-Wno-missing-field-initializers", "-Wno-sign-conversion", "-Wno-thread-safety-analysis", "-Wno-unknown-warning-option", "-Wno-unused-parameter", "-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", ]) # Android does not want -Weverything set, it blocks toolchain updates. if "-Weverything" in cflags: cflags.remove("-Weverything") # 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): # Android does not want -Weverything set, it blocks toolchain updates. if "-Weverything" in cflags_cc: cflags_cc.remove("-Weverything") # Only use the generated flags related to warnings. return {s for s in cflags_cc if s.startswith('-W')} 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 = {} with open(opts_file) as f: code = compile(f.read(), opts_file, 'exec') exec(code, 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('// DO NOT MODIFY! This file is autogenerated by gn_to_bp.py.', file=f) print('// If need to change a define, modify SkUserConfigManual.h', file=f) print('#pragma once', file=f) print('#include "SkUserConfigManual.h"', file=f) for define in sorted(defines): print('', file=f) print('#ifndef', define.split('=')[0], file=f) print('#define', define.replace('=', ' ', 1), file=f) print('#endif', file=f)