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 |