OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 # On Android we build unit test bundles as shared libraries. To run | 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 | 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 | 9 # then jumps into it. Since java is required for many tests |
10 # (e.g. PathUtils.java), a "pure native" test bundle is inadequate. | 10 # (e.g. PathUtils.java), a "pure native" test bundle is inadequate. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 | 53 |
54 def __init__(self, native_library, strip_binary, output_directory, | 54 def __init__(self, native_library, strip_binary, output_directory, |
55 target_abi): | 55 target_abi): |
56 self._native_library = native_library | 56 self._native_library = native_library |
57 self._strip_binary = strip_binary | 57 self._strip_binary = strip_binary |
58 self._output_directory = os.path.abspath(output_directory) | 58 self._output_directory = os.path.abspath(output_directory) |
59 self._target_abi = target_abi | 59 self._target_abi = target_abi |
60 self._root_name = None | 60 self._root_name = None |
61 if self._native_library: | 61 if self._native_library: |
62 self._root_name = self._LibraryRoot() | 62 self._root_name = self._LibraryRoot() |
63 logging.warn('root name: %s', self._root_name) | 63 logging.info('root name: %s', self._root_name) |
64 | 64 |
65 def _LibraryRoot(self): | 65 def _LibraryRoot(self): |
66 """Return a root name for a shared library. | 66 """Return a root name for a shared library. |
67 | 67 |
68 The root name should be suitable for substitution in apk files | 68 The root name should be suitable for substitution in apk files |
69 like the manifest. For example, blah/foo/libbase_unittests.so | 69 like the manifest. For example, blah/foo/libbase_unittests.so |
70 becomes base_unittests. | 70 becomes base_unittests. |
71 """ | 71 """ |
72 rootfinder = re.match('.?lib(.+).so', | 72 rootfinder = re.match('.?lib(.+).so', |
73 os.path.basename(self._native_library)) | 73 os.path.basename(self._native_library)) |
74 if rootfinder: | 74 if rootfinder: |
75 return rootfinder.group(1) | 75 return rootfinder.group(1) |
76 else: | 76 else: |
77 return None | 77 return None |
78 | 78 |
79 def _CopyTemplateFilesAndClearDir(self): | 79 def _CopyTemplateFilesAndClearDir(self): |
80 """Copy files needed to build a new apk. | 80 """Copy files needed to build a new apk. |
81 | 81 |
82 Uses rsync to avoid unnecessary io. This call also clears outstanding | 82 Uses rsync to avoid unnecessary io. This call also clears outstanding |
83 files in the directory. | 83 files in the directory. |
84 """ | 84 """ |
85 srcdir = os.path.abspath(os.path.dirname(__file__)) | 85 srcdir = os.path.abspath(os.path.dirname(__file__)) |
86 destdir = self._output_directory | 86 destdir = self._output_directory |
87 if not os.path.exists(destdir): | 87 if not os.path.exists(destdir): |
88 os.makedirs(destdir) | 88 os.makedirs(destdir) |
89 elif not '/out/' in destdir: | 89 elif not '/out/' in destdir: |
90 raise Exception('Unbelievable output directory; bailing for safety') | 90 raise Exception('Unbelievable output directory; bailing for safety') |
91 logging.warning('rsync %s --> %s', self._SOURCE_FILES, destdir) | 91 logging.info('rsync %s --> %s', self._SOURCE_FILES, destdir) |
92 logging.info(cmd_helper.GetCmdOutput( | 92 logging.info(cmd_helper.GetCmdOutput( |
93 ['rsync', '-aRv', '--delete', '--exclude', '.svn'] + | 93 ['rsync', '-aRv', '--delete', '--exclude', '.svn'] + |
94 self._SOURCE_FILES + [destdir], cwd=srcdir)) | 94 self._SOURCE_FILES + [destdir], cwd=srcdir)) |
95 | 95 |
96 def _ReplaceStrings(self): | 96 def _ReplaceStrings(self): |
97 """Replace 'replaceme' strings in generated files with a root libname. | 97 """Replace 'replaceme' strings in generated files with a root libname. |
98 | 98 |
99 If we have no root libname (e.g. no shlib was specified), do nothing. | 99 If we have no root libname (e.g. no shlib was specified), do nothing. |
100 """ | 100 """ |
101 if not self._root_name: | 101 if not self._root_name: |
102 return | 102 return |
103 logging.warn('Replacing "replaceme" with ' + self._root_name) | 103 logging.info('Replacing "replaceme" with ' + self._root_name) |
104 for f in self._REPLACEME_FILES: | 104 for f in self._REPLACEME_FILES: |
105 dest = os.path.join(self._output_directory, f) | 105 dest = os.path.join(self._output_directory, f) |
106 contents = open(dest).read() | 106 contents = open(dest).read() |
107 contents = contents.replace('replaceme', self._root_name) | 107 contents = contents.replace('replaceme', self._root_name) |
108 dest = dest.replace('replaceme', self._root_name) # update the filename! | 108 dest = dest.replace('replaceme', self._root_name) # update the filename! |
109 open(dest, 'w').write(contents) | 109 open(dest, 'w').write(contents) |
110 | 110 |
111 def _CopyLibrary(self): | 111 def _CopyLibrary(self): |
112 """Copy the shlib into the apk source tree (if relevant).""" | 112 """Copy the shlib into the apk source tree (if relevant).""" |
113 if self._native_library: | 113 if self._native_library: |
114 destdir = os.path.join(self._output_directory, 'libs/' + self._target_abi) | 114 destdir = os.path.join(self._output_directory, 'libs/' + self._target_abi) |
115 if not os.path.exists(destdir): | 115 if not os.path.exists(destdir): |
116 os.makedirs(destdir) | 116 os.makedirs(destdir) |
117 dest = os.path.join(destdir, os.path.basename(self._native_library)) | 117 dest = os.path.join(destdir, os.path.basename(self._native_library)) |
118 logging.warn('strip %s --> %s', self._native_library, dest) | 118 logging.info('strip %s --> %s', self._native_library, dest) |
119 cmd_helper.RunCmd( | 119 cmd_helper.RunCmd( |
120 [self._strip_binary, '--strip-unneeded', self._native_library, '-o', | 120 [self._strip_binary, '--strip-unneeded', self._native_library, '-o', |
121 dest]) | 121 dest]) |
122 | 122 |
123 def CreateBundle(self): | 123 def CreateBundle(self): |
124 """Create the apk bundle source and assemble components.""" | 124 """Create the apk bundle source and assemble components.""" |
125 self._CopyTemplateFilesAndClearDir() | 125 self._CopyTemplateFilesAndClearDir() |
126 self._ReplaceStrings() | 126 self._ReplaceStrings() |
127 self._CopyLibrary() | 127 self._CopyLibrary() |
128 | 128 |
129 def Compile(self, ant_args): | 129 def Compile(self, ant_args): |
130 """Build the generated apk with ant. | 130 """Build the generated apk with ant. |
131 | 131 |
132 Args: | 132 Args: |
133 ant_args: extra args to pass to ant | 133 ant_args: extra args to pass to ant |
134 """ | 134 """ |
135 cmd = ['ant'] | 135 cmd = ['ant'] |
136 if ant_args: | 136 if ant_args: |
137 cmd.extend(ant_args) | 137 cmd.extend(ant_args) |
138 cmd.append("-DAPP_ABI=" + self._target_abi) | 138 cmd.append("-DAPP_ABI=" + self._target_abi) |
139 cmd.extend(['-buildfile', | 139 cmd.extend(['-buildfile', |
140 os.path.join(self._output_directory, 'native_test_apk.xml')]) | 140 os.path.join(self._output_directory, 'native_test_apk.xml')]) |
141 logging.warn(cmd) | 141 logging.info(cmd) |
142 p = subprocess.Popen(cmd, stderr=subprocess.STDOUT) | 142 p = subprocess.Popen(cmd, stderr=subprocess.STDOUT) |
143 (stdout, _) = p.communicate() | 143 (stdout, _) = p.communicate() |
144 logging.warn(stdout) | 144 logging.info(stdout) |
145 if p.returncode != 0: | 145 if p.returncode != 0: |
146 logging.error('Ant return code %d', p.returncode) | 146 logging.error('Ant return code %d', p.returncode) |
147 sys.exit(p.returncode) | 147 sys.exit(p.returncode) |
148 | 148 |
149 def main(argv): | 149 def main(argv): |
150 parser = optparse.OptionParser() | 150 parser = optparse.OptionParser() |
151 parser.add_option('--verbose', | 151 parser.add_option('--verbose', |
152 help='Be verbose') | 152 help='Be verbose') |
153 parser.add_option('--native_library', | 153 parser.add_option('--native_library', |
154 help='Full name of native shared library test bundle') | 154 help='Full name of native shared library test bundle') |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 jar_list = options.jars.replace('"', '').split() | 188 jar_list = options.jars.replace('"', '').split() |
189 options.ant_args.append('-DINPUT_JARS_PATHS=' + " ".join(jar_list)) | 189 options.ant_args.append('-DINPUT_JARS_PATHS=' + " ".join(jar_list)) |
190 | 190 |
191 | 191 |
192 ntag = NativeTestApkGenerator(native_library=options.native_library, | 192 ntag = NativeTestApkGenerator(native_library=options.native_library, |
193 strip_binary=options.strip_binary, | 193 strip_binary=options.strip_binary, |
194 output_directory=options.output, | 194 output_directory=options.output, |
195 target_abi=options.app_abi) | 195 target_abi=options.app_abi) |
196 ntag.CreateBundle() | 196 ntag.CreateBundle() |
197 ntag.Compile(options.ant_args) | 197 ntag.Compile(options.ant_args) |
198 logging.warn('COMPLETE.') | 198 logging.info('COMPLETE.') |
199 | 199 |
200 if __name__ == '__main__': | 200 if __name__ == '__main__': |
201 sys.exit(main(sys.argv)) | 201 sys.exit(main(sys.argv)) |
OLD | NEW |