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
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.
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
28 from util
import build_utils
33 _library_re
= re
.compile(
34 '.*NEEDED.*Shared library: \[(?P<library_name>.+)\]')
37 def SetReadelfPath(path
):
42 def SetLibraryDirs(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
):
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
,
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
]
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
)
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
)
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
},
125 only_if_changed
=True)
128 build_utils
.Touch(options
.stamp
)
131 build_utils
.WriteDepfile(
133 libraries
+ build_utils
.GetPythonDependencies())
136 if __name__
== '__main__':