aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Derek Sollenberger <djsollen@google.com>2018-02-01 09:22:53 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-02 15:12:20 +0000
commit5d3f7704bf9f3b4a075dc55b6951eec6f574c333 (patch)
treebab3cf7aa4bb7a2d270600d0a5481a338ff59352
parenta3ca5f857a36ec16ce666c56adfa5c5800bb979a (diff)
Add gn_to_bp script for SkQP.
This refactors the current gn_to_bp script and moves the common components into a utils class. Both gn_to_bp scripts now also accept an optional param (--gn <gn_path>) to make it easier to run within the Android tree where we don't have the DEPS synced. Change-Id: Idc4de7b3993e63e21a5b7137b1873d82a8e1843e Reviewed-on: https://skia-review.googlesource.com/102184 Commit-Queue: Derek Sollenberger <djsollen@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
-rw-r--r--gn/gn_to_bp.py109
-rw-r--r--gn/gn_to_bp_utils.py107
-rw-r--r--tools/skqp/gn_to_bp.py213
3 files changed, 342 insertions, 87 deletions
diff --git a/gn/gn_to_bp.py b/gn/gn_to_bp.py
index 5b6b3c7021..3d5dcb6c94 100644
--- a/gn/gn_to_bp.py
+++ b/gn/gn_to_bp.py
@@ -14,6 +14,8 @@ import string
import subprocess
import tempfile
+import gn_to_bp_utils
+
# First we start off with a template for Android.bp,
# with holes for source lists and include directories.
bp = string.Template('''// This file is autogenerated by gn_to_bp.py.
@@ -213,12 +215,8 @@ gn_args = {
'target_os': '"android"',
'skia_vulkan_header': '"Skia_Vulkan_Android.h"',
}
-gn_args = ' '.join(sorted('%s=%s' % (k,v) for (k,v) in gn_args.iteritems()))
-
-tmp = tempfile.mkdtemp()
-subprocess.check_call(['gn', 'gen', tmp, '--args=%s' % gn_args, '--ide=json'])
-js = json.load(open(os.path.join(tmp, 'project.json')))
+js = gn_to_bp_utils.GenerateJSONFromGN(gn_args)
def strip_slashes(lst):
return {str(p.lstrip('/')) for p in lst}
@@ -228,6 +226,7 @@ cflags = strip_slashes(js['targets']['//:skia']['cflags'])
cflags_cc = strip_slashes(js['targets']['//:skia']['cflags_cc'])
local_includes = strip_slashes(js['targets']['//:skia']['include_dirs'])
export_includes = strip_slashes(js['targets']['//:public']['include_dirs'])
+defines = [str(d) for d in js['targets']['//:skia']['defines']]
dm_srcs = strip_slashes(js['targets']['//:dm']['sources'])
dm_includes = strip_slashes(js['targets']['//:dm']['include_dirs'])
@@ -236,81 +235,28 @@ nanobench_target = js['targets']['//:nanobench']
nanobench_srcs = strip_slashes(nanobench_target['sources'])
nanobench_includes = strip_slashes(nanobench_target['include_dirs'])
-def GrabDependentSrcs(name, srcs_to_extend, exclude):
- # Grab the sources 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 exclude in dep:
- continue
- srcs_to_extend.update(strip_slashes(js['targets'][dep].get('sources', [])))
- GrabDependentSrcs(dep, srcs_to_extend, exclude)
-
-GrabDependentSrcs('//:skia', srcs, None)
-GrabDependentSrcs('//:dm', dm_srcs, 'skia')
-GrabDependentSrcs('//:nanobench', nanobench_srcs, 'skia')
+gn_to_bp_utils.GrabDependentValues(js, '//:skia', 'sources', srcs, None)
+gn_to_bp_utils.GrabDependentValues(js, '//:dm', 'sources', dm_srcs, 'skia')
+gn_to_bp_utils.GrabDependentValues(js, '//:nanobench', 'sources',
+ nanobench_srcs, 'skia')
# No need to list headers.
srcs = {s for s in srcs if not s.endswith('.h')}
dm_srcs = {s for s in dm_srcs if not s.endswith('.h')}
nanobench_srcs = {s for s in nanobench_srcs if not s.endswith('.h')}
-# Only use the generated flags related to warnings.
-cflags = {s for s in cflags if s.startswith('-W')}
-cflags_cc = {s for s in cflags_cc if s.startswith('-W')}
-# 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",
-])
-cflags_cc.add("-fexceptions")
-
-# 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")
+cflags = gn_to_bp_utils.CleanupCFlags(cflags)
+cflags_cc = gn_to_bp_utils.CleanupCCFlags(cflags_cc)
# We need to add the include path to the vulkan defines and header file set in
# then skia_vulkan_header gn arg that is used for framework builds.
local_includes.add("platform_tools/android/vulkan")
export_includes.add("platform_tools/android/vulkan")
-# Most defines go into SkUserConfig.h, where they're seen by Skia and its users.
-defines = [str(d) for d in js['targets']['//:skia']['defines']]
-defines.remove('NDEBUG') # Let the Android build control this.
-defines.remove('SKIA_IMPLEMENTATION=1') # Only libskia should have this define.
-
-# 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.
-
-def get_path_info(path, kind):
- assert kind == "abspath"
- # While we want absolute paths in GN, relative paths work best here.
- return path
-
-builtins = { 'get_path_info': get_path_info }
-defs = {}
here = os.path.dirname(__file__)
-execfile(os.path.join(here, 'opts.gni'), builtins, defs)
+defs = gn_to_bp_utils.GetArchSources(os.path.join(here, 'opts.gni'))
-# Turn paths from opts.gni into paths relative to external/skia.
-def scrub(lst):
- # Perform any string substitutions.
- for var in defs:
- if type(defs[var]) is str:
- lst = [ p.replace('$'+var, defs[var]) for p in lst ]
- # Relativize paths to top-level skia/ directory.
- return [os.path.relpath(p, '..') for p in lst]
+gn_to_bp_utils.WriteUserConfig('include/config/SkUserConfig.h', defines)
# Turn a list of strings into the style bpfmt outputs.
def bpfmt(indent, lst, sort=True):
@@ -327,16 +273,16 @@ with open('Android.bp', 'w') as f:
'cflags': bpfmt(8, cflags, False),
'cflags_cc': bpfmt(8, cflags_cc),
- 'arm_srcs': bpfmt(16, scrub(defs['armv7'])),
- 'arm_neon_srcs': bpfmt(20, scrub(defs['neon'])),
- 'arm64_srcs': bpfmt(16, scrub(defs['arm64'] +
- defs['crc32'])),
- 'none_srcs': bpfmt(16, scrub(defs['none'])),
- 'x86_srcs': bpfmt(16, scrub(defs['sse2'] +
- defs['ssse3'] +
- defs['sse41'] +
- defs['sse42'] +
- defs['avx' ])),
+ 'arm_srcs': bpfmt(16, defs['armv7']),
+ 'arm_neon_srcs': bpfmt(20, defs['neon']),
+ 'arm64_srcs': bpfmt(16, defs['arm64'] +
+ defs['crc32']),
+ 'none_srcs': bpfmt(16, defs['none']),
+ 'x86_srcs': bpfmt(16, defs['sse2'] +
+ defs['ssse3'] +
+ defs['sse41'] +
+ defs['sse42'] +
+ defs['avx' ]),
'dm_includes' : bpfmt(8, dm_includes),
'dm_srcs' : bpfmt(8, dm_srcs),
@@ -344,14 +290,3 @@ with open('Android.bp', 'w') as f:
'nanobench_includes' : bpfmt(8, nanobench_includes),
'nanobench_srcs' : bpfmt(8, nanobench_srcs),
})
-
-#... and all the #defines we want to put in SkUserConfig.h.
-with open('include/config/SkUserConfig.h', '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, '#ifndef SkUserConfig_DEFINED'
- print >>f, '#define SkUserConfig_DEFINED'
- print >>f, '#include "SkUserConfigManual.h"'
- for define in sorted(defines):
- print >>f, ' #define', define.replace('=', ' ')
- print >>f, '#endif//SkUserConfig_DEFINED'
diff --git a/gn/gn_to_bp_utils.py b/gn/gn_to_bp_utils.py
new file mode 100644
index 0000000000..65456408cd
--- /dev/null
+++ b/gn/gn_to_bp_utils.py
@@ -0,0 +1,107 @@
+#!/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 '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 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.
+
+ #... 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, '#ifndef SkUserConfig_DEFINED'
+ print >>f, '#define SkUserConfig_DEFINED'
+ print >>f, '#include "SkUserConfigManual.h"'
+ for define in sorted(defines):
+ print >>f, ' #define', define.replace('=', ' ')
+ print >>f, '#endif//SkUserConfig_DEFINED'
diff --git a/tools/skqp/gn_to_bp.py b/tools/skqp/gn_to_bp.py
new file mode 100644
index 0000000000..5f0ac9a26b
--- /dev/null
+++ b/tools/skqp/gn_to_bp.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python
+#
+# Copyright 2016 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 sys
+import tempfile
+
+root_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ os.pardir, os.pardir)
+skia_gn_dir = os.path.join(root_dir, 'gn')
+sys.path.insert(0, skia_gn_dir)
+
+import gn_to_bp_utils
+
+# First we start off with a template for Android.bp,
+# with holes for source lists and include directories.
+bp = string.Template('''// This file is autogenerated by tools/skqp/gn_to_bp.py.
+
+cc_library_shared {
+ name: "libskqp_app",
+ sdk_version: "26",
+ stl: "libc++_static",
+ tags: ["tests", "optional"],
+
+ cflags: [
+ $cflags
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
+ ],
+
+ cppflags:[
+ $cflags_cc
+ ],
+
+ local_include_dirs: [
+ $local_includes
+ ],
+
+ srcs: [
+ $srcs
+ ],
+
+ arch: {
+ arm: {
+ srcs: [
+ $arm_srcs
+ ],
+
+ neon: {
+ srcs: [
+ $arm_neon_srcs
+ ],
+ },
+ },
+
+ arm64: {
+ srcs: [
+ $arm64_srcs
+ ],
+ },
+
+ mips: {
+ srcs: [
+ $none_srcs
+ ],
+ },
+
+ mips64: {
+ srcs: [
+ $none_srcs
+ ],
+ },
+
+ x86: {
+ srcs: [
+ $x86_srcs
+ ],
+ cflags: [
+ // Clang seems to think new/malloc will only be 4-byte aligned
+ // on x86 Android. We're pretty sure it's actually 8-byte
+ // alignment. tests/OverAlignedTest.cpp has more information,
+ // and should fail if we're wrong.
+ "-Wno-over-aligned"
+ ],
+ },
+
+ x86_64: {
+ srcs: [
+ $x86_srcs
+ ],
+ },
+ },
+
+ shared_libs: [
+ "libandroid",
+ "libEGL",
+ "libGLESv2",
+ "liblog",
+ "libvulkan",
+ "libz",
+ ],
+ static_libs: [
+ "libjpeg_static_ndk",
+ "libjsoncpp",
+ "libpng_ndk",
+ "libwebp-decode",
+ "libwebp-encode",
+ ]
+}''')
+
+# We'll run GN to get the main source lists and include directories for Skia.
+gn_args = {
+ 'is_debug': 'false',
+ 'target_cpu': '"none"',
+ 'target_os': '"android"',
+ 'ndk_api': '26',
+
+ # setup vulkan
+ 'skia_use_vulkan': 'true',
+ 'skia_vulkan_header': '"Skia_Vulkan_Android.h"',
+
+ # enable/disable skia subsystems
+ 'skia_enable_fontmgr_empty': 'true',
+ 'skia_enable_pdf': 'false',
+ 'skia_use_expat': 'false',
+ 'skia_use_dng_sdk': 'false',
+ 'skia_use_icu': 'false',
+ 'skia_use_lua': 'false',
+ 'skia_use_piex': 'false',
+ 'skia_use_skcms': 'false',
+
+ # specify that the Android.bp will supply the necessary components
+ 'skia_use_system_expat': 'true', # removed this when gn is fixed
+ 'skia_use_system_libpng': 'true',
+ 'skia_use_system_jsoncpp': 'true',
+ 'skia_use_system_libwebp': 'true',
+ 'skia_use_system_libjpeg_turbo': 'true',
+ 'skia_use_system_zlib': 'true',
+}
+
+js = gn_to_bp_utils.GenerateJSONFromGN(gn_args)
+
+def strip_slashes(lst):
+ return {str(p.lstrip('/')) for p in lst}
+
+srcs = strip_slashes(js['targets']['//:libskqp_app']['sources'])
+cflags = strip_slashes(js['targets']['//:libskqp_app']['cflags'])
+cflags_cc = strip_slashes(js['targets']['//:libskqp_app']['cflags_cc'])
+local_includes = strip_slashes(js['targets']['//:libskqp_app']['include_dirs'])
+defines = {str(d) for d in js['targets']['//:libskqp_app']['defines']}
+
+gn_to_bp_utils.GrabDependentValues(js, '//:libskqp_app', 'sources', srcs, None)
+gn_to_bp_utils.GrabDependentValues(js, '//:libskqp_app', 'include_dirs',
+ local_includes, 'freetype')
+gn_to_bp_utils.GrabDependentValues(js, '//:libskqp_app', 'defines',
+ defines, None)
+
+# No need to list headers or other extra flags.
+srcs = {s for s in srcs if not s.endswith('.h')}
+cflags = gn_to_bp_utils.CleanupCFlags(cflags)
+cflags_cc = gn_to_bp_utils.CleanupCCFlags(cflags_cc)
+
+# We need to add the include path to the vulkan defines and header file set in
+# then skia_vulkan_header gn arg that is used for framework builds.
+local_includes.add("platform_tools/android/vulkan")
+
+# Get architecture specific source files
+defs = gn_to_bp_utils.GetArchSources(os.path.join(skia_gn_dir, 'opts.gni'))
+
+# Add source file until fix lands in
+# https://skia-review.googlesource.com/c/skia/+/101820
+srcs.add("src/ports/SkFontMgr_empty_factory.cpp")
+
+# Turn a list of strings into the style bpfmt outputs.
+def bpfmt(indent, lst, sort=True):
+ if sort:
+ lst = sorted(lst)
+ return ('\n' + ' '*indent).join('"%s",' % v for v in lst)
+
+# Most defines go into SkUserConfig.h, where they're seen by Skia and its users.
+gn_to_bp_utils.WriteUserConfig('include/config/SkUserConfig.h', defines)
+
+# OK! We have everything to fill in Android.bp...
+with open('Android.bp', 'w') as f:
+ print >>f, bp.substitute({
+ 'local_includes': bpfmt(8, local_includes),
+ 'srcs': bpfmt(8, srcs),
+ 'cflags': bpfmt(8, cflags, False),
+ 'cflags_cc': bpfmt(8, cflags_cc),
+
+ 'arm_srcs': bpfmt(16, defs['armv7']),
+ 'arm_neon_srcs': bpfmt(20, defs['neon']),
+ 'arm64_srcs': bpfmt(16, defs['arm64'] +
+ defs['crc32']),
+ 'none_srcs': bpfmt(16, defs['none']),
+ 'x86_srcs': bpfmt(16, defs['sse2'] +
+ defs['ssse3'] +
+ defs['sse41'] +
+ defs['sse42'] +
+ defs['avx' ]),
+ })
+