Chromium Code Reviews| 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 |