1 # Copyright 2019 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import("//build/config/clang/clang.gni")
7 # This template creates a set of shared libraries, by linking a single
8 # "partitioned" shared library, then splitting it into multiple pieces.
9 # The intention is to facilitate code-splitting between a base library and
10 # additional feature-specific libraries that may be obtained and loaded at a
13 # The combined library is an intermediate product made by leveraging the LLVM
14 # toolchain. Code modules may be labeled via compiler flag as belonging to a
15 # particular partition. At link time, any symbols reachable by only a single
16 # partition's entrypoints will be located in a partition-specific library
17 # segment. After linking, the segments are split apart using objcopy into
18 # separate libraries. The main library is then packaged with the application
19 # as usual, while feature libraries may be packaged, delivered and loaded
22 # When loading a feature library, the intended address of the library must be
23 # supplied to the loader, so that it can be mapped to the memory location. The
24 # address offsets of the feature libraries are stored in the base library and
25 # accessed through special symbols named according to the partitions.
27 # The template instantiates targets for the base library, as well as each
28 # specified partition, based on the root target name. Example:
30 # - monochrome_base (base library)
31 # - monochrome_base_foo (partition library for feature 'foo')
32 # - monochrome_base_bar (partition library for feature 'bar')
34 # The base library is placed in the root output directory, but additional
35 # feature libraries are placed in a subdirectory named according to the base
36 # library. This avoids name collisions, since feature library names are not
37 # sensitive to the base library to which they are paired. Example:
39 # - out/libmonochrome_base.so
40 # - out/monochrome_base_partitions/libfoo.so
41 # - out/monochrome_base_partitions/libbar.so
43 # This template uses shared_library's default configurations.
46 # partitions: A list of library partition names to extract, in addition to
49 template("partitioned_shared_library") {
51 forward_variables_from(invoker, [ "testonly" ])
53 _combined_library_target = "${target_name}__combined"
55 # Strip "lib" from target names; it will be re-added to output libraries.
56 _output_name = string_replace(target_name, "lib", "")
58 shared_library(_combined_library_target) {
59 forward_variables_from(invoker, "*", [ "partitions" ])
60 if (!defined(ldflags)) {
64 "-Wl,-soname,lib${_output_name}.so",
69 template("partition_action") {
72 ":$_combined_library_target",
74 script = "//build/extract_partition.py"
76 "$root_out_dir/lib.unstripped/lib${_output_name}__combined.so",
79 invoker.unstripped_output,
80 invoker.stripped_output,
83 invoker.stripped_output,
87 rebase_path("$clang_base_path/bin/llvm-objcopy", root_build_dir),
88 "--unstripped-output",
89 rebase_path(invoker.unstripped_output, root_build_dir),
91 rebase_path(invoker.stripped_output, root_build_dir),
93 if (defined(invoker.partition) && invoker.partition != "") {
96 "lib${invoker.partition}.so",
99 args += [ rebase_path(sources[0], root_build_dir) ]
103 partition_action(target_name) {
104 stripped_output = "$root_out_dir/lib${_output_name}.so"
105 unstripped_output = "$root_out_dir/lib.unstripped/lib${_output_name}.so"
108 # Note that as of now, non-base partition libraries are placed in a
109 # subdirectory of the root output directory. This is because partition
110 # sonames are not sensitive to the filename of the base library, and as such,
111 # their corresponding file names may be generated multiple times by different
112 # base libraries. To avoid collisions, each base library target has a
113 # corresponding subdir for its extra partitions.
115 # If this proves problematic to various pieces of infrastructure, a proposed
116 # alternative is allowing the linker to rename partitions. For example,
117 # feature "foo" may be a partition. If two different base libraries both
118 # define "foo" partitions, the linker may be made to accept an extra command
119 # to rename the partition's soname to "foo1" or "foo2". Other build config
120 # can name the libraries foo1.so and foo2.so, allowing them to reside in the
122 _partition_dir = "$root_out_dir/${invoker.target_name}_partitions"
123 foreach(_partition, invoker.partitions) {
124 partition_action("${target_name}_${_partition}") {
125 partition = _partition
126 unstripped_output = "$_partition_dir/lib.unstripped/lib${partition}.so"
127 stripped_output = "$_partition_dir/lib${partition}.so"
132 set_defaults("partitioned_shared_library") {
133 configs = default_shared_library_configs