chromium/chrome/android/chrome_common_shared_library.gni

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

import("//base/android/linker/config.gni")
import("//build/config/android/config.gni")
import("//build/config/android/create_unwind_table.gni")
import("//build/config/android/extract_unwind_tables.gni")
import("//build/config/android/linker_version_script.gni")
import("//build/config/chrome_build.gni")
import("//build/config/compiler/compiler.gni")
import("//build/partitioned_shared_library.gni")
import("//chrome/android/modules/buildflags.gni")
import("//device/vr/buildflags/buildflags.gni")
import("//third_party/jni_zero/jni_zero.gni")

declare_args() {
  # Compile libmonochrome.so with RELR relocations, which are smaller and more
  # efficient, but supported only on API 28+.
  # This is not permanently enabled for Trichrome because it shares its native
  # library with Monochrome.
  # Restricted to official builds to avoid turning off is_high_end_android
  # explicitly on all relevant non-official bots. TODO(crbug.com/41488915):
  # Always use RELR when Android O (and O_MR1) is no longer supported.
  use_relr_relocations = is_high_end_android && is_official_build
}

# This template contains all common configuration for native shared libraries,
# including libchrome, monochrome, standalone webview (also called monochrome),
# and libchromefortest (used by chrome_public_test_apk).
#
# Variables:
#    is_monochrome: Optional. If set, the library is for use in monochrome.
#    is_webview: If true, the library is for webview, and browser-specific
#      config is skipped.
#    module_descs: Optional. Descriptors of feature modules for which library
#      targets should be auto-generated. The targets are called
#      "${target_name}_<module name>" and can be depended on like shared_library
#      targets. If enabled, the library targets create partitions containing the
#      module's native code. Otherwise, they simply depend on the module's
#      native_deps. See //chrome/android/modules/chrome_feature_modules.gni for
#      the descriptor format.
template("chrome_common_shared_library") {
  forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
  _is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
  _is_webview = defined(invoker.is_webview) && invoker.is_webview
  _collect_inputs_only =
      defined(invoker.collect_inputs_only) && invoker.collect_inputs_only

  # Create a partitioned libraries if the build config supports it, and the
  # invoker has supplied module descriptors.
  _generate_partitions = defined(invoker.module_descs) &&
                         use_native_partitions && !_collect_inputs_only
  _module_descs = []
  if (defined(invoker.module_descs)) {
    _module_descs = invoker.module_descs
  }

  if (!_collect_inputs_only) {
    _linker_script_target = "${target_name}_linker_script"
    _linker_script = "$target_gen_dir/${target_name}_linker_script.txt"

    # Create a custom linker script based on JNI and feature module requirements.
    generate_linker_version_script(_linker_script_target) {
      linker_script = _linker_script
      export_feature_registrations = true
      if (_generate_partitions) {
        export_symbol_allowlist_files = []
        foreach(_module_desc, invoker.module_descs) {
          if (defined(_module_desc.native_entrypoints)) {
            export_symbol_allowlist_files += [ _module_desc.native_entrypoints ]
          }
        }
      }
    }
  }

  if (_generate_partitions) {
    _target_type = "partitioned_shared_library_with_jni"
  } else {
    _target_type = "shared_library_with_jni"
  }

  target(_target_type, target_name) {
    forward_variables_from(
        invoker,
        "*",
        TESTONLY_AND_VISIBILITY + [ "define_unwind_table_target" ])

    if (!defined(deps)) {
      deps = []
    }

    if (!_is_webview) {
      deps += [ "//chrome:chrome_android_core" ]
    }

    # Warn if linking code which could implicitly disable BTI on Arm systems
    configs += [ "//build/config/android:lld_branch_target_hardening" ]

    if (!(defined(testonly) && testonly)) {
      configs -= [ "//build/config/compiler:thinlto_optimize_default" ]
      configs += [ "//build/config/compiler:thinlto_optimize_max" ]
    }
    configs += [ "//build/config/compiler:chrome_orderfile_config" ]

    # Use a dynamically-generated linker script.
    configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
    if (!defined(ldflags)) {
      ldflags = []
    }
    if (_collect_inputs_only) {
      metadata = {
      }
      ldflags += [ "--collect-inputs-only" ]
    } else {
      deps += [ ":$_linker_script_target" ]
      inputs = [ "$_linker_script" ]
      ldflags += [ "-Wl,--version-script=" +
                   rebase_path(_linker_script, root_build_dir) ]
    }

    if (_generate_partitions) {
      partitions = []
      foreach(_module_desc, _module_descs) {
        if (defined(_module_desc.native_deps)) {
          partitions += [ _module_desc.name ]
          deps += _module_desc.native_deps
        }
      }
    } else if (_collect_inputs_only) {
      foreach(_module_desc, _module_descs) {
        if (defined(_module_desc.native_deps)) {
          deps += _module_desc.native_deps
        }
      }
    }

    # Compress relocations if needed.
    if (use_relr_relocations) {
      configs += [ "//build/config/android:lld_relr_relocations" ]
    } else if ((_is_monochrome || _is_webview || chromium_linker_supported) &&
               use_lld) {
      configs += [ "//build/config/android:lld_pack_relocations" ]
    }

    if ((_is_monochrome || _is_webview || chromium_linker_supported) &&
        target_cpu != "mipsel" && target_cpu != "mips64el") {
      # By default, the static linker will create ELF executables with both
      # SysV and GNU hash tables. Now that the chromium linker supports the GNU
      # format, which is considerably smaller, ensure that the SysV one is
      # never compiled in the final library (http://crbug.com/742525#c28). GNU
      # hash support was added in Android M. Also not supported on MIPS
      # architecture (http://crbug.com/811306).
      ldflags += [ "-Wl,--hash-style=gnu" ]
    }

    # See crbug.com/705088.
    if (target_cpu == "arm" && is_asan) {
      ldflags += [ "-Wl,--long-plt" ]
    }
  }

  if (!_generate_partitions && !_collect_inputs_only) {
    # Make helper targets so that we always have module native targets no matter
    # whether partitions are enabled.
    foreach(_module_desc, _module_descs) {
      if (defined(_module_desc.native_deps)) {
        group("${target_name}_${_module_desc.name}") {
          deps = _module_desc.native_deps
        }
      }
    }
  }

  if (defined(invoker.define_unwind_table_target) &&
      invoker.define_unwind_table_target) {
    _library_target = ":$target_name"

    # TODO(crbug.com/40833600): Remove generation of v1 unwind asset when
    # `CFIBacktraceAndroid` is replaced with `ChromeUnwinderAndroid`.
    unwind_table_v1("${target_name}_unwind_table_v1") {
      library_target = _library_target
    }

    if (use_android_unwinder_v2) {
      unwind_table_v2("${target_name}_unwind_table_v2") {
        library_target = _library_target
      }
    }
  }
}