Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Side by Side Diff: testing/android/generate_native_test.py

Issue 13828003: [Android] Build gtest APKs like other APKs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « testing/android/README.chromium ('k') | testing/android/native_test_apk.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 # On Android we build unit test bundles as shared libraries. To run
8 # tests, we launch a special "test runner" apk which loads the library
9 # then jumps into it. Since java is required for many tests
10 # (e.g. PathUtils.java), a "pure native" test bundle is inadequate.
11 #
12 # This script, generate_native_test.py, is used to generate the source
13 # for an apk that wraps a unit test shared library bundle. That
14 # allows us to have a single boiler-plate application be used across
15 # all unit test bundles.
16
17 import logging
18 import optparse
19 import os
20 import re
21 import subprocess
22 import sys
23
24 # cmd_helper.py is under ../../build/android/
25 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
26 '..', 'build', 'android')))
27 from pylib import cmd_helper # pylint: disable=F0401
28
29
30 class NativeTestApkGenerator(object):
31 """Generate a native test apk source tree.
32
33 TODO(jrg): develop this more so the activity name is replaced as
34 well. That will allow multiple test runners to be installed at the
35 same time. (The complication is that it involves renaming a java
36 class, which implies regeneration of a jni header, and on and on...)
37 """
38
39 # Files or directories we need to copy to create a complete apk test shell.
40 _SOURCE_FILES = ['AndroidManifest.xml',
41 'native_test_apk.xml',
42 'res', # res/values/strings.xml
43 'java', # .../ChromeNativeTestActivity.java
44 ]
45
46 # Files in the destion directory that have a "replaceme" string
47 # which should be replaced by the basename of the shared library.
48 # Note we also update the filename if 'replaceme' is itself found in
49 # the filename.
50 _REPLACEME_FILES = ['AndroidManifest.xml',
51 'native_test_apk.xml',
52 'res/values/strings.xml']
53
54 def __init__(self, native_library, strip_binary, output_directory,
55 target_abi):
56 self._native_library = native_library
57 self._strip_binary = strip_binary
58 self._output_directory = os.path.abspath(output_directory)
59 self._target_abi = target_abi
60 self._root_name = None
61 if self._native_library:
62 self._root_name = self._LibraryRoot()
63 logging.info('root name: %s', self._root_name)
64
65 def _LibraryRoot(self):
66 """Return a root name for a shared library.
67
68 The root name should be suitable for substitution in apk files
69 like the manifest. For example, blah/foo/libbase_unittests.so
70 becomes base_unittests.
71 """
72 rootfinder = re.match('.?lib(.+).so',
73 os.path.basename(self._native_library))
74 if rootfinder:
75 return rootfinder.group(1)
76 else:
77 return None
78
79 def _CopyTemplateFilesAndClearDir(self):
80 """Copy files needed to build a new apk.
81
82 Uses rsync to avoid unnecessary io. This call also clears outstanding
83 files in the directory.
84 """
85 srcdir = os.path.abspath(os.path.dirname(__file__))
86 destdir = self._output_directory
87 if not os.path.exists(destdir):
88 os.makedirs(destdir)
89 elif not '/out/' in destdir:
90 raise Exception('Unbelievable output directory; bailing for safety')
91 logging.info('rsync %s --> %s', self._SOURCE_FILES, destdir)
92 logging.info(cmd_helper.GetCmdOutput(
93 ['rsync', '-aRv', '--delete', '--exclude', '.svn'] +
94 self._SOURCE_FILES + [destdir], cwd=srcdir))
95
96 def _ReplaceStrings(self):
97 """Replace 'replaceme' strings in generated files with a root libname.
98
99 If we have no root libname (e.g. no shlib was specified), do nothing.
100 """
101 if not self._root_name:
102 return
103 logging.info('Replacing "replaceme" with ' + self._root_name)
104 for f in self._REPLACEME_FILES:
105 dest = os.path.join(self._output_directory, f)
106 contents = open(dest).read()
107 contents = contents.replace('replaceme', self._root_name)
108 dest = dest.replace('replaceme', self._root_name) # update the filename!
109 open(dest, 'w').write(contents)
110
111 def _CopyLibrary(self):
112 """Copy the shlib into the apk source tree (if relevant)."""
113 if self._native_library:
114 destdir = os.path.join(self._output_directory, 'libs/' + self._target_abi)
115 if not os.path.exists(destdir):
116 os.makedirs(destdir)
117 dest = os.path.join(destdir, os.path.basename(self._native_library))
118 logging.info('strip %s --> %s', self._native_library, dest)
119 cmd_helper.RunCmd(
120 [self._strip_binary, '--strip-unneeded', self._native_library, '-o',
121 dest])
122
123 def CreateBundle(self):
124 """Create the apk bundle source and assemble components."""
125 self._CopyTemplateFilesAndClearDir()
126 self._ReplaceStrings()
127 self._CopyLibrary()
128
129 def Compile(self, ant_args):
130 """Build the generated apk with ant.
131
132 Args:
133 ant_args: extra args to pass to ant
134 """
135 cmd = ['ant']
136 if ant_args:
137 cmd.extend(ant_args)
138 cmd.append("-DAPP_ABI=" + self._target_abi)
139 cmd.extend(['-buildfile',
140 os.path.join(self._output_directory, 'native_test_apk.xml')])
141 logging.info(cmd)
142 p = subprocess.Popen(cmd, stderr=subprocess.STDOUT)
143 (stdout, _) = p.communicate()
144 logging.info(stdout)
145 if p.returncode != 0:
146 logging.error('Ant return code %d', p.returncode)
147 sys.exit(p.returncode)
148
149 def main(argv):
150 parser = optparse.OptionParser()
151 parser.add_option('--verbose',
152 help='Be verbose')
153 parser.add_option('--native_library',
154 help='Full name of native shared library test bundle')
155 parser.add_option('--jars',
156 help='Space separated list of jars to be included')
157 parser.add_option('--output',
158 help='Output directory for generated files.')
159 parser.add_option('--app_abi', default='armeabi',
160 help='ABI for native shared library')
161 parser.add_option('--strip-binary',
162 help='Binary to use for stripping the native libraries.')
163 parser.add_option('--ant-args', action='append',
164 help='extra args for ant')
165 parser.add_option('--stamp-file',
166 help='Path to file to touch on success.')
167 parser.add_option('--no-compile', action='store_true',
168 help='Use this flag to disable ant compilation.')
169
170 options, _ = parser.parse_args(argv)
171
172 # It is not an error to specify no native library; the apk should
173 # still be generated and build. It will, however, print
174 # NATIVE_LOADER_FAILED when run.
175 if not options.output:
176 raise Exception('No output directory specified for generated files')
177
178 if options.verbose:
179 logging.basicConfig(level=logging.DEBUG, format=' %(message)s')
180
181 if not options.strip_binary:
182 options.strip_binary = os.getenv('STRIP')
183 if not options.strip_binary:
184 raise Exception('No tool for stripping the libraries has been supplied')
185
186 ntag = NativeTestApkGenerator(native_library=options.native_library,
187 strip_binary=options.strip_binary,
188 output_directory=options.output,
189 target_abi=options.app_abi)
190
191 ntag.CreateBundle()
192 if not options.no_compile:
193 ntag.Compile(options.ant_args)
194
195 if options.stamp_file:
196 with file(options.stamp_file, 'a'):
197 os.utime(options.stamp_file, None)
198
199 logging.info('COMPLETE.')
200
201 if __name__ == '__main__':
202 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « testing/android/README.chromium ('k') | testing/android/native_test_apk.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698