SkQP: split make_apk script into create_apk and make_apk

gn_to_bp:  wrap defines in ifndef

create_apk.py assumes you are either run from the aosp tree, or you are
being run from make_universal_apk.py, which now defers to create_apk.py
for all functionality, even argument parsing.

tools/skqp/generate_gn_args moved some functionity into skqp_gn_args.py,
which is now used by create_apk.py

create_apk now accepts android sdk license for you.

create_apk and make_universal_apk.py now are better about cleaning up
after exceptions happen.

Old script make_apk.sh now just points at make_universal_apk.py

CQ_INCLUDE_TRYBOTS=skia.primary:Build-Debian9-Clang-x86-devrel-Android_SKQP,Test-Debian9-Clang-NUC7i5BNK-CPU-Emulator-x86-devrel-All-Android_SKQP

Change-Id: I2dba20ef7017987cabb2bd49f070e2b1594785d5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235678
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
This commit is contained in:
Hal Canary 2019-08-19 15:04:24 -04:00 committed by Skia Commit-Bot
parent e53f7ff95f
commit 82e3afa99d
8 changed files with 359 additions and 329 deletions

View File

@ -116,4 +116,7 @@ def WriteUserConfig(userConfigPath, defines):
print >>f, '#pragma once'
print >>f, '#include "SkUserConfigManual.h"'
for define in sorted(defines):
print >>f, '#define', define.replace('=', ' ')
print >>f, ''
print >>f, '#ifndef', define.split('=')[0]
print >>f, '#define', define.replace('=', ' ', 1)
print >>f, '#endif'

235
tools/skqp/create_apk.py Executable file
View File

@ -0,0 +1,235 @@
#! /usr/bin/env python
# Copyright 2019 Google LLC.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
'''
This script can be run with no arguments, in which case it will produce an
APK with native libraries for all four architectures: arm, arm64, x86, and
x64. You can instead list the architectures you want as arguments to this
script. For example:
python create_apk.py arm x86
The environment variables ANDROID_NDK and ANDROID_HOME must be set to the
locations of the Android NDK and SDK.
Additionally, `ninja` should be in your path.
It assumes that the source tree is in the desired state, e.g. by having
run 'python tools/git-sync-deps' in the root of the skia checkout.
We also assume that the 'resources' directory has been copied to
'platform_tools/android/apps/skqp/src/main/assets', and the
'tools/skqp/download_model' script has been run.
Also:
* If the environment variable SKQP_BUILD_DIR is set, many of the
intermediate build objects will be placed here.
* If the environment variable SKQP_OUTPUT_DIR is set, the final APK
will be placed in this directory.
* If the environment variable SKQP_DEBUG is set, Skia will be compiled
in debug mode.
'''
import os
import re
import subprocess
import sys
import shutil
import time
import skqp_gn_args
def print_cmd(cmd, o):
m = re.compile('[^A-Za-z0-9_./-]')
o.write('+ ')
for c in cmd:
if m.search(c) is not None:
o.write(repr(c) + ' ')
else:
o.write(c + ' ')
o.write('\n')
o.flush()
def check_call(cmd, **kwargs):
print_cmd(cmd, sys.stdout)
return subprocess.check_call(cmd, **kwargs)
def find_name(searchpath, filename):
for dirpath, _, filenames in os.walk(searchpath):
if filename in filenames:
yield os.path.join(dirpath, filename)
def check_ninja():
with open(os.devnull, 'w') as devnull:
return subprocess.call(['ninja', '--version'],
stdout=devnull, stderr=devnull) == 0
def remove(p):
if not os.path.islink(p) and os.path.isdir(p):
shutil.rmtree(p)
elif os.path.lexists(p):
os.remove(p)
assert not os.path.exists(p)
def makedirs(dst):
if not os.path.exists(dst):
os.makedirs(dst)
class RemoveFiles(object):
def __init__(self, *args):
self.args = args
def __enter__(self):
pass
def __exit__(self, a, b, c):
for arg in self.args:
remove(arg)
class ChDir(object):
def __init__(self, d):
self.orig = os.getcwd()
os.chdir(d)
def __enter__(self):
pass
def __exit__(self, a, b, c):
os.chdir(self.orig)
def make_symlinked_subdir(target, working_dir):
newdir = os.path.join(working_dir, os.path.basename(target))
makedirs(newdir)
os.symlink(os.path.relpath(newdir, os.path.dirname(target)), target)
def accept_android_license(android_home):
proc = subprocess.Popen(
[android_home + '/tools/bin/sdkmanager', '--licenses'],
stdin=subprocess.PIPE)
while proc.poll() is None:
proc.stdin.write('y\n')
time.sleep(1)
# pylint: disable=bad-whitespace
skia_to_android_arch_name_map = {'arm' : 'armeabi-v7a',
'arm64': 'arm64-v8a' ,
'x86' : 'x86' ,
'x64' : 'x86_64' }
def create_apk_impl(opts):
build_dir, final_output_dir = opts.build_dir, opts.final_output_dir
assert os.path.exists('bin/gn') # Did you `tools/git-syc-deps`?
for d in [build_dir, final_output_dir]:
makedirs(d)
apps_dir = 'platform_tools/android/apps'
app = 'skqp'
lib = 'lib%s_app.so' % app
# These are the locations in the tree where the gradle needs or will create
# not-checked-in files. Treat them specially to keep the tree clean.
remove(build_dir + '/libs')
build_paths = [apps_dir + '/.gradle',
apps_dir + '/' + app + '/build',
apps_dir + '/' + app + '/src/main/libs']
for path in build_paths:
remove(path)
try:
make_symlinked_subdir(path, build_dir)
except OSError:
sys.stderr.write('failed to create symlink "%s"\n' % path)
lib_dir = '%s/%s/src/main/libs' % (apps_dir, app)
apk_build_dir = '%s/%s/build/outputs/apk' % (apps_dir, app)
for d in [lib_dir, apk_build_dir]:
shutil.rmtree(d, True) # force rebuild
with RemoveFiles(*build_paths):
for arch in opts.architectures:
build = os.path.join(build_dir, arch)
gn_args = opts.gn_args(arch)
args = ' '.join('%s=%s' % (k, v) for k, v in gn_args.items())
check_call(['bin/gn', 'gen', build, '--args=' + args])
check_call(['ninja', '-C', build, lib])
dst = '%s/%s' % (lib_dir, skia_to_android_arch_name_map[arch])
makedirs(dst)
shutil.copy(os.path.join(build, lib), dst)
accept_android_license(opts.android_home)
env_copy = os.environ.copy()
env_copy['ANDROID_HOME'] = opts.android_home
env_copy['ANDROID_NDK_HOME'] = opts.android_ndk
# Why does gradlew need to be called from this directory?
check_call(['apps/gradlew', '-p' 'apps/' + app,
'-P', 'suppressNativeBuild',
':%s:assembleUniversalDebug' % app],
env=env_copy, cwd='platform_tools/android')
apk_name = app + "-universal-debug.apk"
apk_list = list(find_name(apk_build_dir, apk_name))
assert len(apk_list) == 1
out = os.path.join(final_output_dir, apk_name)
shutil.move(apk_list[0], out)
sys.stdout.write(out + '\n')
arches = '_'.join(sorted(opts.architectures))
copy = os.path.join(final_output_dir, "%s-%s-debug.apk" % (app, arches))
shutil.copyfile(out, copy)
sys.stdout.write(copy + '\n')
sys.stdout.write('* * * COMPLETE * * *\n\n')
def create_apk(opts):
skia_dir = os.path.abspath(os.path.dirname(__file__) + '/../..')
assert os.path.exists(skia_dir)
with ChDir(skia_dir):
create_apk_impl(opts)
class SkQP_Build_Options(object):
def __init__(self):
assert '/' in [os.sep, os.altsep] # 'a/b' over os.path.join('a', 'b')
self.error = ''
if not check_ninja():
self.error += '`ninja` is not in the path.\n'
for var in ['ANDROID_NDK', 'ANDROID_HOME']:
if not os.path.exists(os.environ.get(var, '')):
self.error += 'Environment variable `%s` is not set.\n' % var
self.android_ndk = os.path.abspath(os.environ['ANDROID_NDK'])
self.android_home = os.path.abspath(os.environ['ANDROID_HOME'])
args = sys.argv[1:]
for arg in args:
if arg not in skia_to_android_arch_name_map:
self.error += ('Argument %r is not in %r\n' %
(arg, skia_to_android_arch_name_map.keys()))
self.architectures = args if args else skia_to_android_arch_name_map.keys()
default_build = os.path.dirname(__file__) + '/../../out/skqp'
self.build_dir = os.path.abspath(os.environ.get('SKQP_BUILD_DIR', default_build))
self.final_output_dir = os.path.abspath(os.environ.get('SKQP_OUTPUT_DIR', default_build))
self.debug = bool(os.environ.get('SKQP_DEBUG', ''))
def gn_args(self, arch):
return skqp_gn_args.GetGNArgs(arch, self.android_ndk, self.debug, 26)
def write(self, o):
for k, v in [('ANDROID_NDK', self.android_ndk),
('ANDROID_HOME', self.android_home),
('SKQP_OUTPUT_DIR', self.final_output_dir),
('SKQP_BUILD_DIR', self.build_dir),
('SKQP_DEBUG', self.debug),
('Architectures', self.architectures)]:
o.write('%s = %r\n' % (k, v))
o.flush()
def main():
options = SkQP_Build_Options()
if options.error:
sys.stderr.write(options.error + __doc__)
sys.exit(1)
options.write(sys.stdout)
create_apk(options)
if __name__ == '__main__':
main()

View File

@ -1,71 +1,6 @@
#! /usr/bin/env python
# Copyright 2018 Google Inc.
# Copyright 2019 Google LLC.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import hashlib
import multiprocessing
import os
import shutil
import sys
import tempfile
import urllib2
def checksum(path):
if not os.path.exists(path):
return None
m = hashlib.md5()
with open(path, 'rb') as f:
while True:
buf = f.read(4096)
if 0 == len(buf):
return m.hexdigest()
m.update(buf)
def download(md5, path):
if not md5 == checksum(path):
dirname = os.path.dirname(path)
if dirname and not os.path.exists(dirname):
try:
os.makedirs(dirname)
except:
# ignore race condition
if not os.path.exists(dirname):
raise
url = 'https://storage.googleapis.com/skia-skqp-assets/' + md5
with open(path, 'wb') as o:
shutil.copyfileobj(urllib2.urlopen(url), o)
def tmp(prefix):
fd, path = tempfile.mkstemp(prefix=prefix)
os.close(fd)
return path
def main():
target_dir = os.path.join('platform_tools', 'android', 'apps', 'skqp', 'src', 'main', 'assets')
os.chdir(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, target_dir))
checksum_path = 'files.checksum'
if not os.path.isfile(checksum_path):
sys.stderr.write('Error: "%s" is missing.\n' % os.path.join(target_dir, checksum_path))
sys.exit(1)
file_list_file = tmp('files_')
with open(checksum_path, 'r') as f:
md5 = f.read().strip()
assert(len(md5) == 32)
download(md5, file_list_file)
with open(file_list_file, 'r') as f:
records = []
for line in f:
md5, path = line.strip().split(';', 1)
records.append((md5, path))
sys.stderr.write('Downloading %d files.\n' % len(records))
pool = multiprocessing.Pool(processes=multiprocessing.cpu_count() * 2)
for record in records:
pool.apply_async(download, record, callback=lambda x: sys.stderr.write('.'))
pool.close()
pool.join()
sys.stderr.write('\n')
if __name__ == '__main__':
main()
import download_model
download_model.main()

69
tools/skqp/download_model.py Executable file
View File

@ -0,0 +1,69 @@
#! /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.
import hashlib
import multiprocessing
import os
import shutil
import sys
import tempfile
import urllib2
def checksum(path):
if not os.path.exists(path):
return None
m = hashlib.md5()
with open(path, 'rb') as f:
while True:
buf = f.read(4096)
if not buf:
return m.hexdigest()
m.update(buf)
def download(md5, path):
if not md5 == checksum(path):
dirname = os.path.dirname(path)
if dirname and not os.path.exists(dirname):
try:
os.makedirs(dirname)
except OSError:
pass # ignore race condition
url = 'https://storage.googleapis.com/skia-skqp-assets/' + md5
with open(path, 'wb') as o:
shutil.copyfileobj(urllib2.urlopen(url), o)
def tmp(prefix):
fd, path = tempfile.mkstemp(prefix=prefix)
os.close(fd)
return path
def main():
target_dir = os.path.join('platform_tools', 'android', 'apps', 'skqp', 'src', 'main', 'assets')
os.chdir(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, target_dir))
checksum_path = 'files.checksum'
if not os.path.isfile(checksum_path):
sys.stderr.write('Error: "%s" is missing.\n' % os.path.join(target_dir, checksum_path))
sys.exit(1)
file_list_file = tmp('files_')
with open(checksum_path, 'r') as f:
md5 = f.read().strip()
assert(len(md5) == 32)
download(md5, file_list_file)
with open(file_list_file, 'r') as f:
records = []
for line in f:
md5, path = line.strip().split(';', 1)
records.append((md5, path))
sys.stderr.write('Downloading %d files.\n' % len(records))
pool = multiprocessing.Pool(processes=multiprocessing.cpu_count() * 2)
for record in records:
pool.apply_async(download, record, callback=lambda x: sys.stderr.write('.'))
pool.close()
pool.join()
sys.stderr.write('\n')
if __name__ == '__main__':
main()

View File

@ -8,14 +8,7 @@ import argparse
import os
import sys
from skqp_gn_args import SkqpGnArgs
fmt = '''
target_cpu = "{arch}"
ndk = "{android_ndk_dir}"
is_debug = {debug}
ndk_api = {api_level}
'''
import skqp_gn_args
def parse_args():
parser = argparse.ArgumentParser(description='Generate args.gn file.')
@ -25,23 +18,19 @@ def parse_args():
help='defaults to "arm", valid values: "arm" "arm64" "x86" "x64"')
parser.add_argument('--api_level', type=int, metavar='api_level',
default=26, help='android API level, defaults to 26')
parser.add_argument('--enable_workarounds', default=False,
action='store_true', help="enable GPU work-arounds, defaults to false")
parser.add_argument('--debug', default=False, action='store_true',
help='compile native code in debug mode, defaults to false')
# parse the args and convert bools to strings.
args = parser.parse_args()
gn_bool = lambda b : 'true' if b else 'false'
args.enable_workarounds = gn_bool(args.enable_workarounds)
args.debug = gn_bool(args.debug)
args.android_ndk_dir = os.path.abspath(args.android_ndk_dir)
return args
result = skqp_gn_args.GetGNArgs(args.arch,
os.path.abspath(args.android_ndk_dir),
args.debug,
args.api_level)
return args.target_build_dir, result)
def write_gn(o, args):
o.write(fmt.format(**args))
for k, v in SkqpGnArgs.iteritems():
o.write('%s = %s\n' % (k,v) )
l = max(len(k) for k in args)
for k, v in sorted(args.items()):
o.write('%-*s = %s\n' % (l, k, v))
def make_args_gn(out_dir, args):
if out_dir == '-':
@ -53,5 +42,5 @@ def make_args_gn(out_dir, args):
write_gn(o, args)
if __name__ == '__main__':
args = parse_args()
make_args_gn(args.target_build_dir, vars(args))
build_dir, args = parse_args()
make_args_gn(build_dir, args)

View File

@ -1,49 +1,5 @@
#! /bin/sh
# Copyright 2018 Google Inc.
# Copyright 2019 Google Inc.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
ANDROID_NDK="$1"
if ! [ -d "$ANDROID_NDK" ] || ! [ -x "${ANDROID_NDK}/ndk-build" ]; then
printf "\nUsage:\n %s ANDROID_NDK_PATH\n" "$0" >&2
exit 1
fi
case ":${PATH}:" in
*/depot_tools:*) ;;
*)
printf '\ndepot_tools should be in your $PATH.\n' >&2
exit 1;;
esac
if ! [ -d "$ANDROID_HOME" ] || ! [ -x "${ANDROID_HOME}/platform-tools/adb" ]; then
printf '\n$ANDROID_HOME not set or is broken.\n' >&2
exit 1
fi
set -x
ARCH=${SKQP_ARCH:-arm}
cd "$(dirname "$0")/../.."
BUILD=out/skqp-${ARCH}
python tools/skqp/generate_gn_args $BUILD "$ANDROID_NDK" $ARCH
GIT_SYNC_DEPS_QUIET=Y tools/git-sync-deps
bin/gn gen $BUILD
rm -rf $BUILD/gen
platform_tools/android/bin/android_build_app -C $BUILD skqp
set +x
printf '\n\nAPK built: "%s/skqp.apk"\n\n' "$(pwd)/$BUILD"
exec python "$(dirname "$0")"/make_universal_apk.py "$@"

View File

@ -21,7 +21,7 @@ run 'python tools/git-sync-deps' in the root of the skia checkout.
Also:
* If the environment variable SKQP_BUILD_DIR is set, many of the
intermediate build objects will be places here.
intermediate build objects will be placed here.
* If the environment variable SKQP_OUTPUT_DIR is set, the final APK
will be placed in this directory.
* If the environment variable SKQP_DEBUG is set, Skia will be compiled
@ -29,211 +29,41 @@ Also:
'''
import os
import glob
import re
import subprocess
import sys
import shutil
def print_cmd(cmd, o):
m = re.compile('[^A-Za-z0-9_./-]')
o.write('+ ')
for c in cmd:
if m.search(c) is not None:
o.write(repr(c) + ' ')
else:
o.write(c + ' ')
o.write('\n')
o.flush()
import create_apk
import download_model
def check_call(cmd, **kwargs):
print_cmd(cmd, sys.stdout)
return subprocess.check_call(cmd, **kwargs)
def find_name(searchpath, filename):
for dirpath, _, filenames in os.walk(searchpath):
if filename in filenames:
yield os.path.join(dirpath, filename)
def check_ninja():
with open(os.devnull, 'w') as devnull:
return 0 == subprocess.call(['ninja', '--version'],
stdout=devnull, stderr=devnull)
def remove(p):
if not os.path.islink(p) and os.path.isdir(p):
shutil.rmtree(p)
elif os.path.lexists(p):
os.remove(p)
assert not os.path.exists(p)
skia_to_android_arch_name_map = {'arm' : 'armeabi-v7a',
'arm64': 'arm64-v8a' ,
'x86' : 'x86' ,
'x64' : 'x86_64' }
def make_apk(architectures,
android_ndk,
android_home,
build_dir,
final_output_dir,
debug,
skia_dir):
def make_apk(opts):
assert '/' in [os.sep, os.altsep] # 'a/b' over os.path.join('a', 'b')
assert check_ninja()
assert os.path.exists(android_ndk)
assert os.path.exists(android_home)
assert os.path.exists(skia_dir)
assert os.path.exists(skia_dir + '/bin/gn') # Did you `tools/git-syc-deps`?
assert architectures
assert all(arch in skia_to_android_arch_name_map
for arch in architectures)
for d in [build_dir, final_output_dir]:
if not os.path.exists(d):
os.makedirs(d)
skia_dir = os.path.dirname(__file__) + '/../..'
create_apk.makedirs(opts.build_dir)
assets_dir = skia_dir + '/platform_tools/android/apps/skqp/src/main/assets'
gmkb = assets_dir + '/gmkb'
resources_path = assets_dir + '/resources'
os.chdir(skia_dir)
apps_dir = 'platform_tools/android/apps'
with create_apk.RemoveFiles(resources_path, gmkb): # always clean up
create_apk.remove(gmkb)
create_apk.make_symlinked_subdir(gmkb, opts.build_dir)
# These are the locations in the tree where the gradle needs or will create
# not-checked-in files. Treat them specially to keep the tree clean.
aosp_mode = os.path.exists('MODULE_LICENSE_BSD')
build_paths = [apps_dir + '/.gradle',
apps_dir + '/skqp/build',
apps_dir + '/skqp/src/main/libs']
if not aosp_mode:
build_paths.append(apps_dir + '/skqp/src/main/assets/gmkb')
remove(build_dir + '/libs')
for path in build_paths:
remove(path)
newdir = os.path.join(build_dir, os.path.basename(path))
if not os.path.exists(newdir):
os.makedirs(newdir)
try:
os.symlink(os.path.relpath(newdir, os.path.dirname(path)), path)
except OSError:
pass
if not aosp_mode:
resources_path = apps_dir + '/skqp/src/main/assets/resources'
remove(resources_path)
create_apk.remove(resources_path)
os.symlink('../../../../../../../resources', resources_path)
build_paths.append(resources_path)
app = 'skqp'
lib = 'libskqp_app.so'
shutil.rmtree(apps_dir + '/%s/src/main/libs' % app, True)
if not aosp_mode:
if os.path.exists(apps_dir + '/skqp/src/main/assets/files.checksum'):
check_call([sys.executable, 'tools/skqp/download_model'])
if os.path.exists(assets_dir + '/files.checksum'):
download_model.main()
else:
sys.stderr.write(
'\n* * *\n\nNote: SkQP models are missing!!!!\n\n* * *\n\n')
if aosp_mode:
with open('include/config/SkUserConfig.h') as f:
user_config = f.readlines()
with open('include/config/SkUserConfig.h', 'w') as o:
for line in user_config:
m = re.match(r'^#define\s+([A-Za-z0-9_]+)(|\s.*)$', line)
if m:
o.write('#ifndef %s\n%s\n#endif\n' % (m.group(1), m.group(0).strip()))
else:
o.write(line)
for arch in architectures:
build = os.path.join(build_dir, arch)
gn_args = [android_ndk, '--arch', arch]
if debug:
build += '-debug'
gn_args += ['--debug']
check_call([sys.executable, 'tools/skqp/generate_gn_args', build]
+ gn_args)
check_call(['bin/gn', 'gen', build])
check_call(['ninja', '-C', build, lib])
dst = apps_dir + '/%s/src/main/libs/%s' % (
app, skia_to_android_arch_name_map[arch])
if not os.path.isdir(dst):
os.makedirs(dst)
shutil.copy(os.path.join(build, lib), dst)
if aosp_mode:
subprocess.call('git', 'checkout', 'HEAD', 'include/config/SkUserConfig.h')
apk_build_dir = apps_dir + '/%s/build/outputs/apk' % app
shutil.rmtree(apk_build_dir, True) # force rebuild
# Why does gradlew need to be called from this directory?
os.chdir('platform_tools/android')
env_copy = os.environ.copy()
env_copy['ANDROID_HOME'] = android_home
check_call(['apps/gradlew', '-p' 'apps/' + app, '-P', 'suppressNativeBuild',
':%s:assembleUniversalDebug' % app], env=env_copy)
os.chdir(skia_dir)
apk_name = app + "-universal-debug.apk"
apk_list = list(find_name(apk_build_dir, apk_name))
assert len(apk_list) == 1
out = os.path.join(final_output_dir, apk_name)
shutil.move(apk_list[0], out)
sys.stdout.write(out + '\n')
for path in build_paths:
remove(path)
arches = '_'.join(sorted(architectures))
copy = os.path.join(final_output_dir, "%s-%s-debug.apk" % (app, arches))
shutil.copyfile(out, copy)
sys.stdout.write(copy + '\n')
sys.stdout.write('* * * COMPLETE * * *\n\n')
'\n* * * Note: SkQP models are missing! * * *\n\n')
create_apk.create_apk(opts)
def main():
def error(s):
sys.stderr.write(s + __doc__)
options = create_apk.SkQP_Build_Options()
if options.error:
sys.stderr.write(options.error + __doc__)
sys.exit(1)
if not check_ninja():
error('`ninja` is not in the path.\n')
for var in ['ANDROID_NDK', 'ANDROID_HOME']:
if not os.path.exists(os.environ.get(var, '')):
error('Environment variable `%s` is not set.\n' % var)
architectures = sys.argv[1:]
for arg in sys.argv[1:]:
if arg not in skia_to_android_arch_name_map:
error('Argument %r is not in %r\n' %
(arg, skia_to_android_arch_name_map.keys()))
if not architectures:
architectures = skia_to_android_arch_name_map.keys()
skia_dir = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
default_build = os.path.join(skia_dir, 'out', 'skqp')
build_dir = os.path.abspath(os.environ.get('SKQP_BUILD_DIR', default_build))
final_output_dir = os.path.abspath(
os.environ.get('SKQP_OUTPUT_DIR', default_build))
debug = bool(os.environ.get('SKQP_DEBUG', ''))
android_ndk = os.path.abspath(os.environ['ANDROID_NDK'])
android_home = os.path.abspath(os.environ['ANDROID_HOME'])
for k, v in [('ANDROID_NDK', android_ndk),
('ANDROID_HOME', android_home),
('skia root directory', skia_dir),
('SKQP_OUTPUT_DIR', final_output_dir),
('SKQP_BUILD_DIR', build_dir),
('Architectures', architectures)]:
sys.stdout.write('%s = %r\n' % (k, v))
sys.stdout.flush()
make_apk(architectures,
android_ndk,
android_home,
build_dir,
final_output_dir,
debug,
skia_dir)
options.write(sys.stdout)
make_apk(options)
if __name__ == '__main__':
main()

View File

@ -1,6 +1,7 @@
# Copyright 2019 Google LLC.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
SkqpGnArgs = {
'extra_cflags': '[ "-DSK_ENABLE_DUMP_GPU", "-DSK_BUILD_FOR_SKQP" ]',
'skia_enable_fontmgr_android': 'false',
@ -17,3 +18,15 @@ SkqpGnArgs = {
'skia_use_piex': 'false',
'skia_use_vulkan': 'true',
}
def GetGNArgs(arch, android_ndk, debug, api_level):
def gn_quote(s):
return '"%s"' % s
gn_args = {
'target_cpu': gn_quote(arch),
'ndk': gn_quote(android_ndk),
'is_debug': 'true' if debug else 'false',
'ndk_api': api_level,
}
gn_args.update(SkqpGnArgs)
return gn_args