Copy modules back in from skia-recipes repo
BUG=skia:6070
Change-Id: I86b3f039c27bd8287516c1db8bd1cae62888171b
Reviewed-on: https://skia-review.googlesource.com/7890
Reviewed-by: Ravi Mistry <rmistry@google.com>
Commit-Queue: Eric Boren <borenet@google.com>
diff --git a/infra/bots/recipe_modules/flavor/gn_android_flavor.py b/infra/bots/recipe_modules/flavor/gn_android_flavor.py
new file mode 100644
index 0000000..bf1510b
--- /dev/null
+++ b/infra/bots/recipe_modules/flavor/gn_android_flavor.py
@@ -0,0 +1,179 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import default_flavor
+import subprocess
+
+
+"""GN Android flavor utils, used for building Skia for Android with GN."""
+class GNAndroidFlavorUtils(default_flavor.DefaultFlavorUtils):
+ def __init__(self, m):
+ super(GNAndroidFlavorUtils, self).__init__(m)
+ self._ever_ran_adb = False
+
+ self.device_dirs = default_flavor.DeviceDirs(
+ dm_dir = self.m.vars.android_data_dir + 'dm_out',
+ perf_data_dir = self.m.vars.android_data_dir + 'perf',
+ resource_dir = self.m.vars.android_data_dir + 'resources',
+ images_dir = self.m.vars.android_data_dir + 'images',
+ skp_dir = self.m.vars.android_data_dir + 'skps',
+ svg_dir = self.m.vars.android_data_dir + 'svgs',
+ tmp_dir = self.m.vars.android_data_dir)
+
+ def _strip_environment(self):
+ self.m.vars.default_env = {k: v for (k,v)
+ in self.m.vars.default_env.iteritems()
+ if k in ['PATH']}
+
+ def _run(self, title, *cmd, **kwargs):
+ self._strip_environment()
+ return self.m.run(self.m.step, title, cmd=list(cmd),
+ cwd=self.m.vars.skia_dir, **kwargs)
+
+ def _py(self, title, script, infra_step=True):
+ self._strip_environment()
+ return self.m.run(self.m.python, title, script=script,
+ cwd=self.m.vars.skia_dir, env=None, infra_step=infra_step)
+
+ def _adb(self, title, *cmd, **kwargs):
+ self._ever_ran_adb = True
+ # The only non-infra adb steps (dm / nanobench) happen to not use _adb().
+ if 'infra_step' not in kwargs:
+ kwargs['infra_step'] = True
+ return self._run(title, 'adb', *cmd, **kwargs)
+
+ def compile(self, unused_target, **kwargs):
+ compiler = self.m.vars.builder_cfg.get('compiler')
+ configuration = self.m.vars.builder_cfg.get('configuration')
+ extra_config = self.m.vars.builder_cfg.get('extra_config', '')
+ os = self.m.vars.builder_cfg.get('os')
+ target_arch = self.m.vars.builder_cfg.get('target_arch')
+
+ assert compiler == 'Clang' # At this rate we might not ever support GCC.
+
+ extra_cflags = []
+ if configuration == 'Debug':
+ extra_cflags.append('-O1')
+
+ ndk_asset = 'android_ndk_linux'
+ if 'Mac' in os:
+ ndk_asset = 'android_ndk_darwin'
+ elif 'Win' in os:
+ ndk_asset = 'n'
+
+ quote = lambda x: '"%s"' % x
+ args = {
+ 'ndk': quote(self.m.vars.slave_dir.join(ndk_asset)),
+ 'target_cpu': quote(target_arch),
+ }
+
+ if configuration != 'Debug':
+ args['is_debug'] = 'false'
+ if 'Vulkan' in extra_config:
+ args['ndk_api'] = 24
+ args['skia_enable_vulkan_debug_layers'] = 'false'
+ if 'FrameworkDefs' in extra_config:
+ args['skia_enable_android_framework_defines'] = 'true'
+ if extra_cflags:
+ args['extra_cflags'] = repr(extra_cflags).replace("'", '"')
+
+ gn_args = ' '.join('%s=%s' % (k,v) for (k,v) in sorted(args.iteritems()))
+
+ gn = 'gn.exe' if 'Win' in os else 'gn'
+ ninja = 'ninja.exe' if 'Win' in os else 'ninja'
+ gn = self.m.vars.skia_dir.join('bin', gn)
+
+ self._py('fetch-gn', self.m.vars.skia_dir.join('bin', 'fetch-gn'))
+ self._run('gn gen', gn, 'gen', self.out_dir, '--args=' + gn_args)
+ self._run('ninja', ninja, '-C', self.out_dir)
+
+ def install(self):
+ self._adb('mkdir ' + self.device_dirs.resource_dir,
+ 'shell', 'mkdir', '-p', self.device_dirs.resource_dir)
+
+ def cleanup_steps(self):
+ if self._ever_ran_adb:
+ self.m.python.inline('dump log', """
+ import os
+ import subprocess
+ import sys
+ out = sys.argv[1]
+ log = subprocess.check_output(['adb', 'logcat', '-d'])
+ for line in log.split('\\n'):
+ tokens = line.split()
+ if len(tokens) == 11 and tokens[-7] == 'F' and tokens[-3] == 'pc':
+ addr, path = tokens[-2:]
+ local = os.path.join(out, os.path.basename(path))
+ if os.path.exists(local):
+ sym = subprocess.check_output(['addr2line', '-Cfpe', local, addr])
+ line = line.replace(addr, addr + ' ' + sym.strip())
+ print line
+ """,
+ args=[self.m.vars.skia_out.join(self.m.vars.configuration)],
+ infra_step=True)
+ self._adb('kill adb server', 'kill-server')
+
+ def step(self, name, cmd, env=None, **kwargs):
+ app = self.m.vars.skia_out.join(self.m.vars.configuration, cmd[0])
+ self._adb('push %s' % cmd[0],
+ 'push', app, self.m.vars.android_bin_dir)
+
+ sh = '%s.sh' % cmd[0]
+ self.m.run.writefile(self.m.vars.tmp_dir.join(sh),
+ 'set -x; %s%s; echo $? >%src' %
+ (self.m.vars.android_bin_dir, subprocess.list2cmdline(map(str, cmd)),
+ self.m.vars.android_bin_dir))
+ self._adb('push %s' % sh,
+ 'push', self.m.vars.tmp_dir.join(sh), self.m.vars.android_bin_dir)
+
+ self._adb('clear log', 'logcat', '-c')
+ self.m.python.inline('%s' % cmd[0], """
+ import subprocess
+ import sys
+ bin_dir = sys.argv[1]
+ sh = sys.argv[2]
+ subprocess.check_call(['adb', 'shell', 'sh', bin_dir + sh])
+ try:
+ sys.exit(int(subprocess.check_output(['adb', 'shell', 'cat',
+ bin_dir + 'rc'])))
+ except ValueError:
+ print "Couldn't read the return code. Probably killed for OOM."
+ sys.exit(1)
+ """, args=[self.m.vars.android_bin_dir, sh])
+
+ def copy_file_to_device(self, host, device):
+ self._adb('push %s %s' % (host, device), 'push', host, device)
+
+ def copy_directory_contents_to_device(self, host, device):
+ # Copy the tree, avoiding hidden directories and resolving symlinks.
+ self.m.python.inline('push %s/* %s' % (host, device), """
+ import os
+ import subprocess
+ import sys
+ host = sys.argv[1]
+ device = sys.argv[2]
+ for d, _, fs in os.walk(host):
+ p = os.path.relpath(d, host)
+ if p != '.' and p.startswith('.'):
+ continue
+ for f in fs:
+ print os.path.join(p,f)
+ subprocess.check_call(['adb', 'push',
+ os.path.realpath(os.path.join(host, p, f)),
+ os.path.join(device, p, f)])
+ """, args=[host, device], cwd=self.m.vars.skia_dir, infra_step=True)
+
+ def copy_directory_contents_to_host(self, device, host):
+ self._adb('pull %s %s' % (device, host), 'pull', device, host)
+
+ def read_file_on_device(self, path):
+ return self._adb('read %s' % path,
+ 'shell', 'cat', path, stdout=self.m.raw_io.output()).stdout
+
+ def remove_file_on_device(self, path):
+ self._adb('rm %s' % path, 'shell', 'rm', '-f', path)
+
+ def create_clean_device_dir(self, path):
+ self._adb('rm %s' % path, 'shell', 'rm', '-rf', path)
+ self._adb('mkdir %s' % path, 'shell', 'mkdir', '-p', path)