aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2016-12-06 16:03:52 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-12-06 23:10:34 +0000
commit308b5ac681d5423ddafd208e3d90179e6dc9502e (patch)
tree589e1d5d5c8f4141a84b563947def316099f19d7
parent75b5718d2054b2545a42303a47f5aaf200787c71 (diff)
Add gn_to_bp.py.
The general idea here is, run GN in --ide=json mode to get most information. Then, read a couple .gni files to get the rest (platform specific source lists, Android framework defines). For now, I'm generating Android.bp and SkUserConfig.h. I figure we can do DM and nanobench once these work? Change-Id: I8e7f60d6572f2d4769760cf872895518a15d841b Reviewed-on: https://skia-review.googlesource.com/5554 Reviewed-by: Leon Scroggins <scroggo@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
-rw-r--r--BUILD.gn5
-rw-r--r--gn/gn_to_bp.py183
2 files changed, 188 insertions, 0 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 790dd21a23..29acd54dec 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -697,6 +697,11 @@ component("skia") {
# Targets guarded by skia_enable_tools may use //third_party freely.
if (skia_enable_tools) {
+ # Used by gn_to_bp.py to list our public include dirs.
+ source_set("public") {
+ configs += [ ":skia_public" ]
+ }
+
config("skia.h_config") {
include_dirs = [ "$target_gen_dir" ]
}
diff --git a/gn/gn_to_bp.py b/gn/gn_to_bp.py
new file mode 100644
index 0000000000..170cfb017b
--- /dev/null
+++ b/gn/gn_to_bp.py
@@ -0,0 +1,183 @@
+#!/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 json
+import os
+import pprint
+import string
+import subprocess
+import sys
+import tempfile
+
+# 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.
+
+cc_library {
+ name: "libskia",
+ cflags: [
+ "-fexceptions",
+ "-Wno-unused-parameter",
+ "-U_FORTIFY_SOURCE",
+ "-D_FORTIFY_SOURCE=1",
+ "-DSKIA_IMPLEMENTATION=1",
+ ],
+
+ export_include_dirs: $export_includes,
+ local_include_dirs: $local_includes,
+ srcs: $srcs,
+
+ arch: {
+ arm: {
+ srcs: $arm_srcs,
+ armv7_a_neon: {
+ srcs: $arm_neon_srcs,
+ },
+ },
+ arm64: {
+ srcs: $arm64_srcs,
+ },
+
+ mips: {
+ srcs: $mips_srcs,
+ },
+ mips64: {
+ srcs: $mips64_srcs,
+ },
+
+ x86: {
+ srcs: $x86_srcs,
+ },
+ x86_64: {
+ srcs: $x86_srcs,
+ },
+ }
+
+ shared_libs: [
+ "libEGL",
+ "libGLESv2",
+ "libdng_sdk",
+ "libexpat",
+ "libft2",
+ "libicui18n",
+ "libicuuc",
+ "libjpeg",
+ "liblog",
+ "libpiex",
+ "libpng",
+ "libvulkan",
+ "libz",
+ ],
+ static_libs: [
+ "cpufeatures", // TODO: use this for CRC32 detection
+ "libsfntly",
+ "libwebp-decode",
+ "libwebp-encode",
+ ],
+}
+''')
+
+# We'll run GN to get the main source lists and include directories for Skia.
+gn_args = {
+ 'skia_enable_vulkan_debug_layers': 'false',
+ 'skia_use_vulkan': 'true',
+ 'target_os': '"android"',
+}
+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')))
+
+def strip_slashes(lst):
+ return [p.lstrip('/') for p in lst]
+srcs = strip_slashes(js['targets']['//:skia']['sources'])
+local_includes = strip_slashes(js['targets']['//:skia']['include_dirs'])
+export_includes = strip_slashes(js['targets']['//:public']['include_dirs'])
+
+# Most defines go into SkUserConfig.h, where they're seen by Skia and its users.
+# Start with the defines :skia uses, minus a couple. We'll add more in a bit.
+defines = [str(d) for d in js['targets']['//:skia']['defines']]
+defines.remove('SKIA_IMPLEMENTATION=1') # Only libskia should have this define.
+defines.remove('XML_STATIC') # On Android, libexpat is dynamically linked.
+
+# 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.
+# While we're at it, grab defines specific to Android Framework the same way.
+
+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(sys.argv[0])
+execfile(os.path.join(here, 'opts.gni'), builtins, defs)
+execfile(os.path.join(here, 'android_framework_defines.gni'), builtins, defs)
+
+# This should finish off the defines.
+defines += defs['android_framework_defines']
+defines.extend([
+ 'GR_GL_CUSTOM_SETUP_HEADER "gl/GrGLConfig_chrome.h"',
+ 'SKIA_DLL',
+ 'SK_BUILD_FOR_ANDROID_FRAMEWORK',
+ 'SK_DEFAULT_FONT_CACHE_LIMIT (768 * 1024)',
+ 'SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE (512 * 1024)',
+ 'SK_IGNORE_ETC1_SUPPORT',
+ 'SK_USE_FREETYPE_EMBOLDEN',
+])
+defines.sort()
+
+# Turns 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]
+
+# Turn a list of strings into a pretty string version of a list of strings.
+def pretty(lst):
+ return pprint.pformat(lst).replace("'", '"')
+
+# OK! We have everything to fill in Android.bp...
+with open('Android.bp', 'w') as f:
+ print >>f, bp.substitute({
+ 'export_includes': pretty(export_includes),
+ 'local_includes': pretty(local_includes),
+ 'srcs': pretty(srcs),
+
+ 'arm_srcs': pretty(scrub(defs['armv7'])),
+ 'arm_neon_srcs': pretty(scrub(defs['neon'])),
+ 'arm64_srcs': pretty(scrub(defs['arm64'] +
+ defs['crc32'])),
+ 'mips_srcs': pretty(scrub(defs['mips_dsp'])),
+ 'mips64_srcs': pretty(scrub(defs['none'])),
+ 'x86_srcs': pretty(scrub(defs['sse2'] +
+ defs['ssse3'] +
+ defs['sse41'] +
+ defs['sse42'] +
+ defs['avx' ] +
+ defs['hsw' ]))
+ })
+
+#... and all the #defines we want to put in SkUserConfig.h.
+with open('SkUserConfig.h', 'w') as f:
+ print >>f, '// This file is autogenerated by gn_to_bp.py.'
+ print >>f, '#ifndef SkUserConfig_DEFINED'
+ print >>f, '#define SkUserConfig_DEFINED'
+ for define in defines:
+ print >>f, ' #define', define
+ print >>f, '#endif//SkUserConfig_DEFINED'