OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
Yaron
2013/04/02 01:30:35
Move to build/android/gyp
cjhopman
2013/04/02 20:47:31
Done.
| |
2 # | 2 # |
3 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 """Writes dependency ordered list of native libraries. | 7 """Writes dependency ordered list of native libraries. |
8 | 8 |
9 This list of libraries is used for several steps of building an APK. | 9 This list of libraries is used for several steps of building an APK. |
10 In the component build, the --input-libraries only needs to be the top-level | |
11 library (i.e. libcontent_shell_content_view). This will then use readelf to | |
12 inspect the shared libraries and determine the full list of (non-system) | |
13 libraries that should be included in the APK. | |
10 """ | 14 """ |
11 | 15 |
16 # TODO(cjhopman): See if we can expose the list of library dependencies from | |
17 # gyp, rather than calculating it ourselves. | |
18 # http://crbug.com/2255588 | |
Yaron
2013/04/02 01:30:35
That link doesn't work for me. Wrong #?
And ya, s
cjhopman
2013/04/02 20:47:31
Done.
| |
19 | |
12 import json | 20 import json |
13 import optparse | 21 import optparse |
14 import os | 22 import os |
23 import re | |
15 import sys | 24 import sys |
16 | 25 |
17 from pylib import build_utils | 26 from pylib import build_utils |
18 | 27 |
28 options = None | |
Yaron
2013/04/02 01:30:35
globals should be prefixed with "_"
cjhopman
2013/04/02 20:47:31
Done.
| |
29 libraries_dir = None | |
30 | |
31 def FullLibraryPath(library_name): | |
32 return '%s/%s' % (libraries_dir, library_name) | |
33 | |
34 | |
35 def IsSystemLibrary(library_name): | |
36 return not os.path.exists(FullLibraryPath(library_name)) | |
37 | |
38 | |
39 def CallReadElf(library_name): | |
40 readelf_cmd = [options.readelf, | |
41 '-d', | |
42 FullLibraryPath(library_name)] | |
43 return build_utils.CheckCallDie(readelf_cmd) | |
44 | |
45 | |
46 def GetDependencies(library_name): | |
Yaron
2013/04/02 01:30:35
GetNonSystemLibraryDependencies
cjhopman
2013/04/02 20:47:31
Done.
| |
47 elf = CallReadElf(library_name) | |
48 library_re = re.compile( | |
Yaron
2013/04/02 01:30:35
compile this once at module level
cjhopman
2013/04/02 20:47:31
Done.
| |
49 '.*NEEDED.*Shared library: \[(?P<library_name>[\w/.]+)\]') | |
50 matches = library_re.findall(elf) | |
51 return set([lib for lib in matches if not IsSystemLibrary(lib)]) | |
Yaron
2013/04/02 01:30:35
If you're always excluding system libraries, how a
cjhopman
2013/04/02 20:47:31
Added this to the file-level comment. System libra
Yaron
2013/04/02 21:00:41
Heh, of course. So you don't need to System.loadLi
| |
52 | |
53 | |
54 def GetSortedTransitiveDependencies(libraries): | |
55 """Returns all transitive library dependencies in dependency order.""" | |
56 def GraphNode(library): | |
57 return (library, GetDependencies(library)) | |
58 | |
59 # First: find all library dependencies. | |
60 unchecked_deps = libraries | |
61 all_deps = set(libraries) | |
62 while unchecked_deps: | |
63 lib = unchecked_deps.pop() | |
64 new_deps = GetDependencies(lib).difference(all_deps) | |
65 unchecked_deps.extend(new_deps) | |
66 all_deps = all_deps.union(new_deps) | |
67 | |
68 # Then: simple, slow topological sort. | |
69 sorted_deps = [] | |
70 unsorted_deps = dict(map(GraphNode, all_deps)) | |
71 while unsorted_deps: | |
72 for (library, dependencies) in unsorted_deps.items(): | |
Yaron
2013/04/02 01:30:35
nit: no parens
cjhopman
2013/04/02 20:47:31
Done.
| |
73 if not dependencies.intersection(unsorted_deps.keys()): | |
74 sorted_deps.append(library) | |
75 del unsorted_deps[library] | |
76 | |
77 return sorted_deps | |
78 | |
19 | 79 |
20 def main(argv): | 80 def main(argv): |
21 parser = optparse.OptionParser() | 81 parser = optparse.OptionParser() |
22 | 82 |
23 parser.add_option('--input-libraries', | 83 parser.add_option('--input-libraries', |
24 help='A list of top-level input libraries') | 84 help='A list of top-level input libraries') |
85 parser.add_option('--readelf') | |
Yaron
2013/04/02 01:30:35
Add help
cjhopman
2013/04/02 20:47:31
Done.
| |
25 parser.add_option('--output', help='Path to the generated .json file') | 86 parser.add_option('--output', help='Path to the generated .json file') |
26 parser.add_option('--stamp', help='Path to touch on success') | 87 parser.add_option('--stamp', help='Path to touch on success') |
27 | 88 |
89 global options | |
28 options, _ = parser.parse_args() | 90 options, _ = parser.parse_args() |
29 | 91 |
30 libraries = build_utils.ParseGypList(options.input_libraries) | 92 libraries = build_utils.ParseGypList(options.input_libraries) |
93 global libraries_dir | |
94 libraries_dir = os.path.dirname(libraries[0]) | |
31 libraries = [os.path.basename(lib) for lib in libraries] | 95 libraries = [os.path.basename(lib) for lib in libraries] |
32 | 96 |
97 libraries = GetSortedTransitiveDependencies(libraries) | |
98 | |
33 with open(options.output, 'w') as outfile: | 99 with open(options.output, 'w') as outfile: |
34 json.dump(libraries, outfile) | 100 json.dump(libraries, outfile) |
35 | 101 |
36 if options.stamp: | 102 if options.stamp: |
37 build_utils.Touch(options.stamp) | 103 build_utils.Touch(options.stamp) |
38 | 104 |
39 | 105 |
40 if __name__ == '__main__': | 106 if __name__ == '__main__': |
41 sys.exit(main(sys.argv)) | 107 sys.exit(main(sys.argv)) |
42 | 108 |
43 | 109 |
OLD | NEW |