[Android] Build gtest APKs like other APKs
After much work, we can build gtest APKs without first transforming .java files, resource files, or the AndroidManifest.xml. We can directly use java_apk.gypi and build like all other APKs. Do that. Also, native_test_apk.xml was the last user of common.xml and sdk-targets.xml, and so those can now be removed. Review URL: https://chromiumcodereview.appspot.com/13828003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@193576 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
build
testing/android
@@ -1,3 +1,2 @@
|
||||
apk-based runner for Chromium unit test bundles. Many of these files
|
||||
are templates for generating an apk specific to a test bundle.
|
||||
See generate_native_test.py or discuss with OWNERS.
|
||||
apk-based runner for Chromium unit test bundles. This is a simple wrapper APK
|
||||
that should include a single gtest native library.
|
||||
|
@@ -1,202 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2012 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.
|
||||
|
||||
# On Android we build unit test bundles as shared libraries. To run
|
||||
# tests, we launch a special "test runner" apk which loads the library
|
||||
# then jumps into it. Since java is required for many tests
|
||||
# (e.g. PathUtils.java), a "pure native" test bundle is inadequate.
|
||||
#
|
||||
# This script, generate_native_test.py, is used to generate the source
|
||||
# for an apk that wraps a unit test shared library bundle. That
|
||||
# allows us to have a single boiler-plate application be used across
|
||||
# all unit test bundles.
|
||||
|
||||
import logging
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# cmd_helper.py is under ../../build/android/
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
|
||||
'..', 'build', 'android')))
|
||||
from pylib import cmd_helper # pylint: disable=F0401
|
||||
|
||||
|
||||
class NativeTestApkGenerator(object):
|
||||
"""Generate a native test apk source tree.
|
||||
|
||||
TODO(jrg): develop this more so the activity name is replaced as
|
||||
well. That will allow multiple test runners to be installed at the
|
||||
same time. (The complication is that it involves renaming a java
|
||||
class, which implies regeneration of a jni header, and on and on...)
|
||||
"""
|
||||
|
||||
# Files or directories we need to copy to create a complete apk test shell.
|
||||
_SOURCE_FILES = ['AndroidManifest.xml',
|
||||
'native_test_apk.xml',
|
||||
'res', # res/values/strings.xml
|
||||
'java', # .../ChromeNativeTestActivity.java
|
||||
]
|
||||
|
||||
# Files in the destion directory that have a "replaceme" string
|
||||
# which should be replaced by the basename of the shared library.
|
||||
# Note we also update the filename if 'replaceme' is itself found in
|
||||
# the filename.
|
||||
_REPLACEME_FILES = ['AndroidManifest.xml',
|
||||
'native_test_apk.xml',
|
||||
'res/values/strings.xml']
|
||||
|
||||
def __init__(self, native_library, strip_binary, output_directory,
|
||||
target_abi):
|
||||
self._native_library = native_library
|
||||
self._strip_binary = strip_binary
|
||||
self._output_directory = os.path.abspath(output_directory)
|
||||
self._target_abi = target_abi
|
||||
self._root_name = None
|
||||
if self._native_library:
|
||||
self._root_name = self._LibraryRoot()
|
||||
logging.info('root name: %s', self._root_name)
|
||||
|
||||
def _LibraryRoot(self):
|
||||
"""Return a root name for a shared library.
|
||||
|
||||
The root name should be suitable for substitution in apk files
|
||||
like the manifest. For example, blah/foo/libbase_unittests.so
|
||||
becomes base_unittests.
|
||||
"""
|
||||
rootfinder = re.match('.?lib(.+).so',
|
||||
os.path.basename(self._native_library))
|
||||
if rootfinder:
|
||||
return rootfinder.group(1)
|
||||
else:
|
||||
return None
|
||||
|
||||
def _CopyTemplateFilesAndClearDir(self):
|
||||
"""Copy files needed to build a new apk.
|
||||
|
||||
Uses rsync to avoid unnecessary io. This call also clears outstanding
|
||||
files in the directory.
|
||||
"""
|
||||
srcdir = os.path.abspath(os.path.dirname(__file__))
|
||||
destdir = self._output_directory
|
||||
if not os.path.exists(destdir):
|
||||
os.makedirs(destdir)
|
||||
elif not '/out/' in destdir:
|
||||
raise Exception('Unbelievable output directory; bailing for safety')
|
||||
logging.info('rsync %s --> %s', self._SOURCE_FILES, destdir)
|
||||
logging.info(cmd_helper.GetCmdOutput(
|
||||
['rsync', '-aRv', '--delete', '--exclude', '.svn'] +
|
||||
self._SOURCE_FILES + [destdir], cwd=srcdir))
|
||||
|
||||
def _ReplaceStrings(self):
|
||||
"""Replace 'replaceme' strings in generated files with a root libname.
|
||||
|
||||
If we have no root libname (e.g. no shlib was specified), do nothing.
|
||||
"""
|
||||
if not self._root_name:
|
||||
return
|
||||
logging.info('Replacing "replaceme" with ' + self._root_name)
|
||||
for f in self._REPLACEME_FILES:
|
||||
dest = os.path.join(self._output_directory, f)
|
||||
contents = open(dest).read()
|
||||
contents = contents.replace('replaceme', self._root_name)
|
||||
dest = dest.replace('replaceme', self._root_name) # update the filename!
|
||||
open(dest, 'w').write(contents)
|
||||
|
||||
def _CopyLibrary(self):
|
||||
"""Copy the shlib into the apk source tree (if relevant)."""
|
||||
if self._native_library:
|
||||
destdir = os.path.join(self._output_directory, 'libs/' + self._target_abi)
|
||||
if not os.path.exists(destdir):
|
||||
os.makedirs(destdir)
|
||||
dest = os.path.join(destdir, os.path.basename(self._native_library))
|
||||
logging.info('strip %s --> %s', self._native_library, dest)
|
||||
cmd_helper.RunCmd(
|
||||
[self._strip_binary, '--strip-unneeded', self._native_library, '-o',
|
||||
dest])
|
||||
|
||||
def CreateBundle(self):
|
||||
"""Create the apk bundle source and assemble components."""
|
||||
self._CopyTemplateFilesAndClearDir()
|
||||
self._ReplaceStrings()
|
||||
self._CopyLibrary()
|
||||
|
||||
def Compile(self, ant_args):
|
||||
"""Build the generated apk with ant.
|
||||
|
||||
Args:
|
||||
ant_args: extra args to pass to ant
|
||||
"""
|
||||
cmd = ['ant']
|
||||
if ant_args:
|
||||
cmd.extend(ant_args)
|
||||
cmd.append("-DAPP_ABI=" + self._target_abi)
|
||||
cmd.extend(['-buildfile',
|
||||
os.path.join(self._output_directory, 'native_test_apk.xml')])
|
||||
logging.info(cmd)
|
||||
p = subprocess.Popen(cmd, stderr=subprocess.STDOUT)
|
||||
(stdout, _) = p.communicate()
|
||||
logging.info(stdout)
|
||||
if p.returncode != 0:
|
||||
logging.error('Ant return code %d', p.returncode)
|
||||
sys.exit(p.returncode)
|
||||
|
||||
def main(argv):
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('--verbose',
|
||||
help='Be verbose')
|
||||
parser.add_option('--native_library',
|
||||
help='Full name of native shared library test bundle')
|
||||
parser.add_option('--jars',
|
||||
help='Space separated list of jars to be included')
|
||||
parser.add_option('--output',
|
||||
help='Output directory for generated files.')
|
||||
parser.add_option('--app_abi', default='armeabi',
|
||||
help='ABI for native shared library')
|
||||
parser.add_option('--strip-binary',
|
||||
help='Binary to use for stripping the native libraries.')
|
||||
parser.add_option('--ant-args', action='append',
|
||||
help='extra args for ant')
|
||||
parser.add_option('--stamp-file',
|
||||
help='Path to file to touch on success.')
|
||||
parser.add_option('--no-compile', action='store_true',
|
||||
help='Use this flag to disable ant compilation.')
|
||||
|
||||
options, _ = parser.parse_args(argv)
|
||||
|
||||
# It is not an error to specify no native library; the apk should
|
||||
# still be generated and build. It will, however, print
|
||||
# NATIVE_LOADER_FAILED when run.
|
||||
if not options.output:
|
||||
raise Exception('No output directory specified for generated files')
|
||||
|
||||
if options.verbose:
|
||||
logging.basicConfig(level=logging.DEBUG, format=' %(message)s')
|
||||
|
||||
if not options.strip_binary:
|
||||
options.strip_binary = os.getenv('STRIP')
|
||||
if not options.strip_binary:
|
||||
raise Exception('No tool for stripping the libraries has been supplied')
|
||||
|
||||
ntag = NativeTestApkGenerator(native_library=options.native_library,
|
||||
strip_binary=options.strip_binary,
|
||||
output_directory=options.output,
|
||||
target_abi=options.app_abi)
|
||||
|
||||
ntag.CreateBundle()
|
||||
if not options.no_compile:
|
||||
ntag.Compile(options.ant_args)
|
||||
|
||||
if options.stamp_file:
|
||||
with file(options.stamp_file, 'a'):
|
||||
os.utime(options.stamp_file, None)
|
||||
|
||||
logging.info('COMPLETE.')
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
@@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2012 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.
|
||||
-->
|
||||
|
||||
<project name="replaceme" default="debug" basedir=".">
|
||||
|
||||
<description>
|
||||
Building native test runner ChromeNativeTests_replaceme.apk
|
||||
</description>
|
||||
|
||||
<!--
|
||||
TODO(beverloo): Remove this property when all gyp files (also those in
|
||||
WebKit) define the CHROMIUM_SRC property. This works because properties
|
||||
in ant files are immutable.
|
||||
-->
|
||||
<property name="CHROMIUM_SRC" value="${PRODUCT_DIR}/../.." />
|
||||
|
||||
<import file="${CHROMIUM_SRC}/build/android/ant/common.xml"/>
|
||||
|
||||
<!--
|
||||
TODO(yfriedman): Remove the need to specify this. We should generate the packages in a way such
|
||||
that it's not required.
|
||||
-->
|
||||
<property name="source.absolute.dir" value="java/src"/>
|
||||
<path id="javac.custom.classpath">
|
||||
<pathelement location="${ANDROID_SDK}/android.jar" />
|
||||
</path>
|
||||
<property name="target.abi" value="${APP_ABI}"/>
|
||||
|
||||
<path id="native.libs.gdbserver">
|
||||
<fileset file="${android.gdbserver}"/>
|
||||
</path>
|
||||
|
||||
<!-- We expect PRODUCT_DIR to be set like the gyp var
|
||||
(e.g. $ROOT/out/Debug) -->
|
||||
<fail message="PRODUCT_DIR env var not set?">
|
||||
<condition>
|
||||
<not>
|
||||
<isset property="PRODUCT_DIR"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
|
||||
<property name="out.dir" location="${PRODUCT_DIR}/replaceme_apk"/>
|
||||
|
||||
<property name="resource.absolute.dir" value="res"/>
|
||||
<property name="gen.absolute.dir" value="${out.dir}/gen"/>
|
||||
|
||||
<path id="out.dex.jar.input.ref">
|
||||
<filelist files="${INPUT_JARS_PATHS}"/>
|
||||
</path>
|
||||
<condition property="java.compilerargs"
|
||||
value="-classpath ${toString:out.dex.jar.input.ref}">
|
||||
<not>
|
||||
<equals arg1="${toString:out.dex.jar.input.ref}" arg2=""/>
|
||||
</not>
|
||||
</condition>
|
||||
<property name="native.libs.absolute.dir" location="${out.dir}/libs" />
|
||||
|
||||
<!-- Copy the below manifest file to a new directory because the project
|
||||
base directory and output directory are the same and manifest merge
|
||||
task takes the same file as source and target when doing copying.
|
||||
Otherwise it'll generate an empty manifest file. -->
|
||||
<copy file="AndroidManifest.xml" todir="${out.dir}/manifest"/>
|
||||
<property name="manifest.abs.file" location="${out.dir}/manifest/AndroidManifest.xml"/>
|
||||
|
||||
<target name="-post-compile">
|
||||
<!-- copy gdbserver to main libs directory if building debug. -->
|
||||
<if>
|
||||
<condition>
|
||||
<equals arg1="${build.target}" arg2="debug" />
|
||||
</condition>
|
||||
<then>
|
||||
<copy todir="${out.dir}/libs/${target.abi}">
|
||||
<path refid="native.libs.gdbserver"/>
|
||||
</copy>
|
||||
</then>
|
||||
</if>
|
||||
</target>
|
||||
|
||||
<import file="${CHROMIUM_SRC}/build/android/ant/sdk-targets.xml"/>
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2012 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.
|
||||
-->
|
||||
<resources>
|
||||
<!-- argument to pass to System.loadLibrary(). E.g. base_unittests
|
||||
for loading libbase_unittests.so. -->
|
||||
<string name="native_library">replaceme</string>
|
||||
</resources>
|
Reference in New Issue
Block a user