Upload upstream chromium 76.0.3809.146
[platform/framework/web/chromium-efl.git] / build / partitioned_shared_library.gni
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.
4
5 import("//build/config/clang/clang.gni")
6
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
11 # later time.
12 #
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
20 # separately.
21 #
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.
26 #
27 # The template instantiates targets for the base library, as well as each
28 # specified partition, based on the root target name.  Example:
29 #
30 #   - monochrome_base       (base library)
31 #   - monochrome_base_foo   (partition library for feature 'foo')
32 #   - monochrome_base_bar   (partition library for feature 'bar')
33 #
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:
38 #
39 #   - out/libmonochrome_base.so
40 #   - out/monochrome_base_partitions/libfoo.so
41 #   - out/monochrome_base_partitions/libbar.so
42 #
43 # This template uses shared_library's default configurations.
44 #
45 # Variables:
46 #   partitions: A list of library partition names to extract, in addition to
47 #     the base library.
48
49 template("partitioned_shared_library") {
50   assert(is_clang)
51   forward_variables_from(invoker, [ "testonly" ])
52
53   _combined_library_target = "${target_name}__combined"
54
55   # Strip "lib" from target names; it will be re-added to output libraries.
56   _output_name = string_replace(target_name, "lib", "")
57
58   shared_library(_combined_library_target) {
59     forward_variables_from(invoker, "*", [ "partitions" ])
60     if (!defined(ldflags)) {
61       ldflags = []
62     }
63     ldflags += [
64       "-Wl,-soname,lib${_output_name}.so",
65       "--link-only",
66     ]
67   }
68
69   template("partition_action") {
70     action(target_name) {
71       deps = [
72         ":$_combined_library_target",
73       ]
74       script = "//build/extract_partition.py"
75       sources = [
76         "$root_out_dir/lib.unstripped/lib${_output_name}__combined.so",
77       ]
78       outputs = [
79         invoker.unstripped_output,
80         invoker.stripped_output,
81       ]
82       data = [
83         invoker.stripped_output,
84       ]
85       args = [
86         "--objcopy",
87         rebase_path("$clang_base_path/bin/llvm-objcopy", root_build_dir),
88         "--unstripped-output",
89         rebase_path(invoker.unstripped_output, root_build_dir),
90         "--stripped-output",
91         rebase_path(invoker.stripped_output, root_build_dir),
92       ]
93       if (defined(invoker.partition) && invoker.partition != "") {
94         args += [
95           "--partition",
96           "lib${invoker.partition}.so",
97         ]
98       }
99       args += [ rebase_path(sources[0], root_build_dir) ]
100     }
101   }
102
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"
106   }
107
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.
114   #
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
121   # same directory.
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"
128     }
129   }
130 }
131
132 set_defaults("partitioned_shared_library") {
133   configs = default_shared_library_configs
134 }