2018-02-01 14:22:53 +00:00
|
|
|
#!/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']:
|
2018-06-10 05:18:28 +00:00
|
|
|
if 'modules' in dep:
|
|
|
|
continue # Modules require special handling -- skip for now.
|
2018-02-01 14:22:53 +00:00
|
|
|
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')}
|
2018-05-29 14:46:51 +00:00
|
|
|
# Add additional warning suppressions so we can build
|
|
|
|
# third_party/vulkanmemoryallocator
|
|
|
|
cflags = cflags.union([
|
2018-09-11 18:48:36 +00:00
|
|
|
"-Wno-implicit-fallthrough",
|
2018-05-29 14:46:51 +00:00
|
|
|
"-Wno-missing-field-initializers",
|
2018-09-11 18:48:36 +00:00
|
|
|
"-Wno-thread-safety-analysis",
|
2018-05-29 14:46:51 +00:00
|
|
|
"-Wno-unused-variable",
|
|
|
|
])
|
2018-02-01 14:22:53 +00:00
|
|
|
# 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
|
2019-04-29 15:45:14 +00:00
|
|
|
defines.remove('SKIA_IMPLEMENTATION=1') # don't export this define.
|
2019-02-27 15:59:11 +00:00
|
|
|
if 'WIN32_LEAN_AND_MEAN' in defines: # Controlled by the Android build
|
|
|
|
defines.remove('WIN32_LEAN_AND_MEAN')
|
2019-03-04 18:54:02 +00:00
|
|
|
if '_HAS_EXCEPTIONS=0' in defines: # Controlled by the Android build
|
|
|
|
defines.remove('_HAS_EXCEPTIONS=0')
|
2018-02-01 14:22:53 +00:00
|
|
|
|
|
|
|
#... 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'
|
2018-11-15 20:54:59 +00:00
|
|
|
print >>f, '#pragma once'
|
2018-02-01 14:22:53 +00:00
|
|
|
print >>f, '#include "SkUserConfigManual.h"'
|
|
|
|
for define in sorted(defines):
|
2019-08-19 19:04:24 +00:00
|
|
|
print >>f, ''
|
|
|
|
print >>f, '#ifndef', define.split('=')[0]
|
|
|
|
print >>f, '#define', define.replace('=', ' ', 1)
|
|
|
|
print >>f, '#endif'
|