tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

partitioned_shared_library.gni (6324B)


      1 # Copyright 2019 The Chromium Authors
      2 
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import("//chromium/build/config/android/config.gni")
      7 import("//chromium/build/config/clang/clang.gni")
      8 import("//chromium/build/config/compiler/compiler.gni")
      9 if (build_with_chromium) {
     10   import("//third_party/jni_zero/jni_zero.gni")
     11 }
     12 
     13 # This template creates a set of shared libraries, by linking a single
     14 # "partitioned" shared library, then splitting it into multiple pieces.
     15 # The intention is to facilitate code-splitting between a base library and
     16 # additional feature-specific libraries that may be obtained and loaded at a
     17 # later time.
     18 #
     19 # The combined library is an intermediate product made by leveraging the LLVM
     20 # toolchain.  Code modules may be labeled via compiler flag as belonging to a
     21 # particular partition.  At link time, any symbols reachable by only a single
     22 # partition's entrypoints will be located in a partition-specific library
     23 # segment.  After linking, the segments are split apart using objcopy into
     24 # separate libraries.  The main library is then packaged with the application
     25 # as usual, while feature libraries may be packaged, delivered and loaded
     26 # separately (via an Android Dynamic Feature Module).
     27 #
     28 # When loading a feature library, the intended address of the library must be
     29 # supplied to the loader, so that it can be mapped to the memory location.  The
     30 # address offsets of the feature libraries are stored in the base library and
     31 # accessed through special symbols named according to the partitions.
     32 #
     33 # The template instantiates targets for the base library, as well as each
     34 # specified partition, based on the root target name.  Example:
     35 #
     36 #   - libmonochrome            (base library)
     37 #   - libmonochrome_foo        (partition library for feature 'foo')
     38 #   - libmonochrome_bar        (partition library for feature 'bar')
     39 #
     40 # Note that the feature library filenames are chosen based on the main
     41 # library's name (eg. libmonochrome_foo.so), but the soname of the feature
     42 # library is based on the feature name (eg. "foo").  This should generally be
     43 # okay, with the caveat that loading the library multiple times *might* cause
     44 # problems in Android.
     45 #
     46 # This template uses shared_library's default configurations.
     47 #
     48 # Variables:
     49 #   partitions: A list of library partition names to extract, in addition to
     50 #     the base library.
     51 
     52 template("partitioned_shared_library") {
     53   assert(is_clang)
     54   forward_variables_from(invoker, [ "testonly" ])
     55 
     56   _combined_library_target = "${target_name}__combined"
     57 
     58   # Strip "lib" from target names; it will be re-added to output libraries.
     59   _output_name = string_replace(target_name, "lib", "")
     60 
     61   shared_library(_combined_library_target) {
     62     forward_variables_from(invoker, "*", [ "partitions" ])
     63     if (!defined(ldflags)) {
     64       ldflags = []
     65     }
     66     ldflags += [
     67       "-Wl,-soname,lib${_output_name}.so",
     68       "--partitioned-library",
     69     ]
     70 
     71     # This shared library is an intermediate artifact that should not packaged
     72     # into the final build. Therefore, reset metadata.
     73     metadata = {
     74     }
     75   }
     76 
     77   template("partition_action") {
     78     action(target_name) {
     79       deps = [ ":$_combined_library_target" ]
     80       script = "//chromium/build/extract_partition.py"
     81       sources =
     82           [ "$root_out_dir/lib.unstripped/lib${_output_name}__combined.so" ]
     83       outputs = [
     84         invoker.unstripped_output,
     85         invoker.stripped_output,
     86       ]
     87       data = [ invoker.unstripped_output ]
     88       metadata = {
     89         shared_libraries = [ invoker.stripped_output ]
     90       }
     91       args = [
     92         "--objcopy",
     93         rebase_path("$clang_base_path/bin/llvm-objcopy", root_build_dir),
     94         "--unstripped-output",
     95         rebase_path(invoker.unstripped_output, root_build_dir),
     96         "--stripped-output",
     97         rebase_path(invoker.stripped_output, root_build_dir),
     98       ]
     99       if (defined(invoker.partition) && invoker.partition != "") {
    100         args += [
    101           "--partition",
    102           "${invoker.partition}",
    103         ]
    104       }
    105 
    106       if (use_debug_fission) {
    107         args += [ "--split-dwarf" ]
    108         outputs += [ invoker.unstripped_output + ".dwp" ]
    109       }
    110       args += [ rebase_path(sources[0], root_build_dir) ]
    111     }
    112   }
    113 
    114   partition_action(target_name) {
    115     stripped_output = "$root_out_dir/lib${_output_name}.so"
    116     unstripped_output = "$root_out_dir/lib.unstripped/lib${_output_name}.so"
    117   }
    118 
    119   # Note that as of now, non-base partition libraries are placed in a
    120   # subdirectory of the root output directory.  This is because partition
    121   # sonames are not sensitive to the filename of the base library, and as such,
    122   # their corresponding file names may be generated multiple times by different
    123   # base libraries.  To avoid collisions, each base library target has a
    124   # corresponding subdir for its extra partitions.
    125   #
    126   # If this proves problematic to various pieces of infrastructure, a proposed
    127   # alternative is allowing the linker to rename partitions.  For example,
    128   # feature "foo" may be a partition.  If two different base libraries both
    129   # define "foo" partitions, the linker may be made to accept an extra command
    130   # to rename the partition's soname to "foo1" or "foo2".  Other build config
    131   # can name the libraries foo1.so and foo2.so, allowing them to reside in the
    132   # same directory.
    133   foreach(_partition, invoker.partitions) {
    134     partition_action("${target_name}_${_partition}") {
    135       partition = "${_partition}_partition"
    136       stripped_output = "$root_out_dir/lib${_output_name}_${partition}.so"
    137       unstripped_output =
    138           "$root_out_dir/lib.unstripped/lib${_output_name}_${partition}.so"
    139     }
    140   }
    141 }
    142 
    143 set_defaults("partitioned_shared_library") {
    144   configs = default_shared_library_configs
    145 }
    146 
    147 # native_with_jni for partitioned shared libraries - see native_with_jni for
    148 # details.
    149 template("partitioned_shared_library_with_jni") {
    150   native_with_jni(target_name) {
    151     forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
    152     forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    153     target_type = "partitioned_shared_library"
    154     target_type_import = "//chromium/build/partitioned_shared_library.gni"
    155   }
    156 }
    157 set_defaults("partitioned_shared_library_with_jni") {
    158   configs = default_shared_library_configs
    159 }