Add Apps.AppListSearchQueryLength UMA histogram.
[chromium-blink-merge.git] / build / android / gyp / write_ordered_libraries.py
blob67e7805cd2bdda847d0da350266bbc6e64a12ac1
1 #!/usr/bin/env python
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.
7 """Writes dependency ordered list of native libraries.
9 The list excludes any Android system libraries, as those are not bundled with
10 the APK.
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 """
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
23 import optparse
24 import os
25 import re
26 import sys
28 from util import build_utils
30 _readelf = None
31 _library_dirs = None
33 _library_re = re.compile(
34 '.*NEEDED.*Shared library: \[(?P<library_name>.+)\]')
37 def SetReadelfPath(path):
38 global _readelf
39 _readelf = path
42 def SetLibraryDirs(dirs):
43 global _library_dirs
44 _library_dirs = dirs
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
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))
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)
70 def GetDependencies(library_or_executable):
71 elf = CallReadElf(library_or_executable)
72 return set(_library_re.findall(elf))
75 def GetNonSystemDependencies(library_name):
76 all_deps = GetDependencies(FullLibraryPath(library_name))
77 return set((lib for lib in all_deps if not IsSystemLibrary(lib)))
80 def GetSortedTransitiveDependencies(libraries):
81 """Returns all transitive library dependencies in dependency order."""
82 return build_utils.GetSortedTransitiveDependencies(
83 libraries, GetNonSystemDependencies)
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)]
94 return GetSortedTransitiveDependencies(libraries)
97 def main():
98 parser = optparse.OptionParser()
99 build_utils.AddDepfileOption(parser)
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.')
109 options, _ = parser.parse_args()
111 SetReadelfPath(options.readelf)
112 SetLibraryDirs(options.libraries_dir.split(','))
114 libraries = build_utils.ParseGypList(options.input_libraries)
115 if len(libraries):
116 libraries = GetSortedTransitiveDependenciesForBinaries(libraries)
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]))
122 build_utils.WriteJson(
123 {'libraries': libraries, 'java_libraries_list': java_libraries_list},
124 options.output,
125 only_if_changed=True)
127 if options.stamp:
128 build_utils.Touch(options.stamp)
130 if options.depfile:
131 build_utils.WriteDepfile(
132 options.depfile,
133 libraries + build_utils.GetPythonDependencies())
136 if __name__ == '__main__':
137 sys.exit(main())