# Copyright 2019 The Chromium Authors

# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/config/android/config.gni")
import("//build/config/clang/clang.gni")
import("//build/config/compiler/compiler.gni")
if (build_with_chromium) {
  import("//third_party/jni_zero/jni_zero.gni")
}

# This template creates a set of shared libraries, by linking a single
# "partitioned" shared library, then splitting it into multiple pieces.
# The intention is to facilitate code-splitting between a base library and
# additional feature-specific libraries that may be obtained and loaded at a
# later time.
#
# The combined library is an intermediate product made by leveraging the LLVM
# toolchain.  Code modules may be labeled via compiler flag as belonging to a
# particular partition.  At link time, any symbols reachable by only a single
# partition's entrypoints will be located in a partition-specific library
# segment.  After linking, the segments are split apart using objcopy into
# separate libraries.  The main library is then packaged with the application
# as usual, while feature libraries may be packaged, delivered and loaded
# separately (via an Android Dynamic Feature Module).
#
# When loading a feature library, the intended address of the library must be
# supplied to the loader, so that it can be mapped to the memory location.  The
# address offsets of the feature libraries are stored in the base library and
# accessed through special symbols named according to the partitions.
#
# The template instantiates targets for the base library, as well as each
# specified partition, based on the root target name.  Example:
#
#   - libmonochrome            (base library)
#   - libmonochrome_foo        (partition library for feature 'foo')
#   - libmonochrome_bar        (partition library for feature 'bar')
#
# Note that the feature library filenames are chosen based on the main
# library's name (eg. libmonochrome_foo.so), but the soname of the feature
# library is based on the feature name (eg. "foo").  This should generally be
# okay, with the caveat that loading the library multiple times *might* cause
# problems in Android.
#
# This template uses shared_library's default configurations.
#
# Variables:
#   partitions: A list of library partition names to extract, in addition to
#     the base library.

template("partitioned_shared_library") {
  assert(is_clang)
  forward_variables_from(invoker, [ "testonly" ])

  _combined_library_target = "${target_name}__combined"

  # Strip "lib" from target names; it will be re-added to output libraries.
  _output_name = string_replace(target_name, "lib", "")

  shared_library(_combined_library_target) {
    forward_variables_from(invoker, "*", [ "partitions" ])
    if (!defined(ldflags)) {
      ldflags = []
    }
    ldflags += [
      "-Wl,-soname,lib${_output_name}.so",
      "--partitioned-library",
    ]

    # This shared library is an intermediate artifact that should not packaged
    # into the final build. Therefore, reset metadata.
    metadata = {
    }
  }

  template("partition_action") {
    action(target_name) {
      deps = [ ":$_combined_library_target" ]
      script = "//build/extract_partition.py"
      sources =
          [ "$root_out_dir/lib.unstripped/lib${_output_name}__combined.so" ]
      outputs = [
        invoker.unstripped_output,
        invoker.stripped_output,
      ]
      data = [ invoker.unstripped_output ]
      metadata = {
        shared_libraries = [ invoker.stripped_output ]
      }
      args = [
        "--objcopy",
        rebase_path("$clang_base_path/bin/llvm-objcopy", root_build_dir),
        "--unstripped-output",
        rebase_path(invoker.unstripped_output, root_build_dir),
        "--stripped-output",
        rebase_path(invoker.stripped_output, root_build_dir),
      ]
      if (defined(invoker.partition) && invoker.partition != "") {
        args += [
          "--partition",
          "${invoker.partition}",
        ]
      }

      if (use_debug_fission) {
        args += [ "--split-dwarf" ]
        outputs += [ invoker.unstripped_output + ".dwp" ]
      }
      args += [ rebase_path(sources[0], root_build_dir) ]
    }
  }

  partition_action(target_name) {
    stripped_output = "$root_out_dir/lib${_output_name}.so"
    unstripped_output = "$root_out_dir/lib.unstripped/lib${_output_name}.so"
  }

  # Note that as of now, non-base partition libraries are placed in a
  # subdirectory of the root output directory.  This is because partition
  # sonames are not sensitive to the filename of the base library, and as such,
  # their corresponding file names may be generated multiple times by different
  # base libraries.  To avoid collisions, each base library target has a
  # corresponding subdir for its extra partitions.
  #
  # If this proves problematic to various pieces of infrastructure, a proposed
  # alternative is allowing the linker to rename partitions.  For example,
  # feature "foo" may be a partition.  If two different base libraries both
  # define "foo" partitions, the linker may be made to accept an extra command
  # to rename the partition's soname to "foo1" or "foo2".  Other build config
  # can name the libraries foo1.so and foo2.so, allowing them to reside in the
  # same directory.
  foreach(_partition, invoker.partitions) {
    partition_action("${target_name}_${_partition}") {
      partition = "${_partition}_partition"
      stripped_output = "$root_out_dir/lib${_output_name}_${partition}.so"
      unstripped_output =
          "$root_out_dir/lib.unstripped/lib${_output_name}_${partition}.so"
    }
  }
}

set_defaults("partitioned_shared_library") {
  configs = default_shared_library_configs
}

# native_with_jni for partitioned shared libraries - see native_with_jni for
# details.
template("partitioned_shared_library_with_jni") {
  native_with_jni(target_name) {
    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    target_type = "partitioned_shared_library"
    target_type_import = "//build/partitioned_shared_library.gni"
  }
}
set_defaults("partitioned_shared_library_with_jni") {
  configs = default_shared_library_configs
}
