| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # | |
| 3 # Copyright 2013 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 """Writes dependency ordered list of native libraries. | |
| 8 | |
| 9 The list excludes any Android system libraries, as those are not bundled with | |
| 10 the APK. | |
| 11 | |
| 12 This list of libraries is used for several steps of building an APK. | |
| 13 In the component build, the --input-libraries only needs to be the top-level | |
| 14 library (i.e. libcontent_shell_content_view). This will then use readelf to | |
| 15 inspect the shared libraries and determine the full list of (non-system) | |
| 16 libraries that should be included in the APK. | |
| 17 """ | |
| 18 | |
| 19 # TODO(cjhopman): See if we can expose the list of library dependencies from | |
| 20 # gyp, rather than calculating it ourselves. | |
| 21 # http://crbug.com/225558 | |
| 22 | |
| 23 import optparse | |
| 24 import os | |
| 25 import re | |
| 26 import sys | |
| 27 | |
| 28 from util import build_utils | |
| 29 | |
| 30 _readelf = None | |
| 31 _library_dirs = None | |
| 32 | |
| 33 _library_re = re.compile( | |
| 34 '.*NEEDED.*Shared library: \[(?P<library_name>.+)\]') | |
| 35 | |
| 36 | |
| 37 def SetReadelfPath(path): | |
| 38 global _readelf | |
| 39 _readelf = path | |
| 40 | |
| 41 | |
| 42 def SetLibraryDirs(dirs): | |
| 43 global _library_dirs | |
| 44 _library_dirs = dirs | |
| 45 | |
| 46 | |
| 47 def FullLibraryPath(library_name): | |
| 48 assert _library_dirs is not None | |
| 49 for directory in _library_dirs: | |
| 50 path = '%s/%s' % (directory, library_name) | |
| 51 if os.path.exists(path): | |
| 52 return path | |
| 53 return library_name | |
| 54 | |
| 55 | |
| 56 def IsSystemLibrary(library_name): | |
| 57 # If the library doesn't exist in the libraries directory, assume that it is | |
| 58 # an Android system library. | |
| 59 return not os.path.exists(FullLibraryPath(library_name)) | |
| 60 | |
| 61 | |
| 62 def CallReadElf(library_or_executable): | |
| 63 assert _readelf is not None | |
| 64 readelf_cmd = [_readelf, | |
| 65 '-d', | |
| 66 FullLibraryPath(library_or_executable)] | |
| 67 return build_utils.CheckOutput(readelf_cmd) | |
| 68 | |
| 69 | |
| 70 def GetDependencies(library_or_executable): | |
| 71 elf = CallReadElf(library_or_executable) | |
| 72 return set(_library_re.findall(elf)) | |
| 73 | |
| 74 | |
| 75 def GetNonSystemDependencies(library_name): | |
| 76 all_deps = GetDependencies(library_name) | |
| 77 return set((lib for lib in all_deps if not IsSystemLibrary(lib))) | |
| 78 | |
| 79 | |
| 80 def GetSortedTransitiveDependencies(libraries): | |
| 81 """Returns all transitive library dependencies in dependency order.""" | |
| 82 return build_utils.GetSortedTransitiveDependencies( | |
| 83 libraries, GetNonSystemDependencies) | |
| 84 | |
| 85 | |
| 86 def GetSortedTransitiveDependenciesForBinaries(binaries): | |
| 87 if binaries[0].endswith('.so'): | |
| 88 libraries = [os.path.basename(lib) for lib in binaries] | |
| 89 else: | |
| 90 assert len(binaries) == 1 | |
| 91 all_deps = GetDependencies(binaries[0]) | |
| 92 libraries = [lib for lib in all_deps if not IsSystemLibrary(lib)] | |
| 93 | |
| 94 return GetSortedTransitiveDependencies(libraries) | |
| 95 | |
| 96 | |
| 97 def main(): | |
| 98 parser = optparse.OptionParser() | |
| 99 build_utils.AddDepfileOption(parser) | |
| 100 | |
| 101 parser.add_option('--input-libraries', | |
| 102 help='A list of top-level input libraries.') | |
| 103 parser.add_option('--libraries-dir', | |
| 104 help='The directory which contains shared libraries.') | |
| 105 parser.add_option('--readelf', help='Path to the readelf binary.') | |
| 106 parser.add_option('--output', help='Path to the generated .json file.') | |
| 107 parser.add_option('--stamp', help='Path to touch on success.') | |
| 108 | |
| 109 options, _ = parser.parse_args() | |
| 110 | |
| 111 SetReadelfPath(options.readelf) | |
| 112 SetLibraryDirs(options.libraries_dir.split(',')) | |
| 113 | |
| 114 libraries = build_utils.ParseGypList(options.input_libraries) | |
| 115 if len(libraries): | |
| 116 libraries = GetSortedTransitiveDependenciesForBinaries(libraries) | |
| 117 | |
| 118 # Convert to "base" library names: e.g. libfoo.so -> foo | |
| 119 java_libraries_list = ( | |
| 120 '{%s}' % ','.join(['"%s"' % s[3:-3] for s in libraries])) | |
| 121 | |
| 122 out_json = { | |
| 123 'libraries': libraries, | |
| 124 'lib_paths': [FullLibraryPath(l) for l in libraries], | |
| 125 'java_libraries_list': java_libraries_list | |
| 126 } | |
| 127 build_utils.WriteJson( | |
| 128 out_json, | |
| 129 options.output, | |
| 130 only_if_changed=True) | |
| 131 | |
| 132 if options.stamp: | |
| 133 build_utils.Touch(options.stamp) | |
| 134 | |
| 135 if options.depfile: | |
| 136 build_utils.WriteDepfile( | |
| 137 options.depfile, | |
| 138 libraries + build_utils.GetPythonDependencies()) | |
| 139 | |
| 140 | |
| 141 if __name__ == '__main__': | |
| 142 sys.exit(main()) | |
| 143 | |
| 144 | |
| OLD | NEW |