blob: 40d5a66f0b754ca7601ee192c819bd5f8ba330f5 [file] [log] [blame]
#!/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,
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:
if exclude and isinstance(exclude, list) and dep in exclude:
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([
# Add the rest of the flags we want.
cflags = cflags.union([
# Android does not want -Weverything set, it blocks toolchain updates.
if "-Weverything" in cflags:
# 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:
# 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(, 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
if '_HAS_EXCEPTIONS=0' in defines: # Controlled by the Android build
#... 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', 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)