blob: fb6309d76bccaa32037c458d41b0858b9ee89af0 [file] [log] [blame]
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/current_target_tuple.gni")
import("//build/config/zircon/standard.gni")
import("//build/toolchain/zircon/clang.gni")
_llvm_ifs = "$clang_tool_dir/llvm-ifs"
# Define a linkable shared library built from a text ABI (.ifs) specification.
#
# This uses a `.ifs` file kept in the source tree to create a linkable ELF
# shared library stub file. This can be used at link time to build executable
# and (non-stub) shared library binaries without reference to the actual
# runtime shared library. The real (non-stub) shared library to be used at
# runtime must be compiled separately and included at runtime as necessary.
# This target only takes care of satisfying any link-time dependencies.
# Its label is used in `deps` like a shared_library() target.
#
# This defines two public targets and a config. The main target acts like
# shared_library() for linking purposes, but is not a GN target with outputs.
# An additional target "$target_name.stub" is defined whose outputs include the
# linking stub ELF file itself, e.g. for use as input to a copy() target or the
# like. The "$target_name.config" config is defined to make `-l$output_name`
# implicit link arguments work by supplying a `lib_dirs` that will find the
# stub and nothing else. This config is propagated from the main target via
# public_configs, but this alone may not be sufficient for it to reach the
# linking targets unless all the intervening deps are via public_deps.
#
# Parameters
#
# * abi
# - Required: Source path to a `.ifs` file defining the library's ELF ABI.
# **NOTE:** This file must be consistent across $current_cpu values!
# - Type: file
#
# * output_name
# - Optional: The plain name of the linkable library file to write,
# without the `lib` prefix or the `.so` extension.
# - Type: string
# - Default: $target_name
#
# * data_deps, public, public_configs, public_deps
# - Optional: As for shared_library().
#
# * deps
# - Optional: Any dependencies that went into the creation of the supplied
# `.ifs` file.
# - Type: list(label)
#
template("ifs_shared_library") {
main_target = target_name
stub_target = "$target_name.stub"
config_target = "$target_name.config"
gen_target_base = "_ifs_shared_library.$target_name."
gen_target = "$gen_target_base$clang_cpu"
gen_label = ":$gen_target($default_toolchain)"
gen_dir_base = get_label_info(gen_label, "target_gen_dir") + "/$target_name."
if (defined(invoker.output_name)) {
output_name = invoker.output_name
} else {
output_name = target_name
}
gen_dir = "$gen_dir_base$clang_cpu"
gen_stub_file = "$gen_dir/lib$output_name.so"
public_stub_file = "$target_out_dir/lib$output_name.so"
source_set(main_target) {
public_configs = []
forward_variables_from(invoker,
[
"data_deps",
"public",
"public_configs",
"public_deps",
"testonly",
"visibility",
])
public_configs += [ ":$config_target" ]
libs = [ gen_stub_file ]
deps = [ gen_label ]
}
config(config_target) {
forward_variables_from(invoker,
[
"visibility",
"testonly",
])
if (defined(visibility)) {
visibility += [ ":$main_target" ]
}
lib_dirs = [ gen_dir ]
}
copy(stub_target) {
forward_variables_from(invoker,
[
"visibility",
"testonly",
])
deps = [ gen_label ]
sources = [ gen_stub_file ]
outputs = [ public_stub_file ]
}
if (current_toolchain == default_toolchain) {
# Define a target to generate a stub for each CPU type, but all generated
# in the default toolchain since nothing but CPU varies among them. Note
# that because of GN's special treatment of the default toolchain, these
# will all get Ninja targets even if they're not in any GN deps graph.
# But since these targets depend only on the source files and don't cause
# anything else new to get built, that should not add any build overhead.
foreach(cpu, standard_fuchsia_cpus) {
foreach(translation, clang_cpu_translations) {
if (cpu == translation.gn) {
cpu = translation.clang
}
}
gen_target = "$gen_target_base$cpu"
gen_dir = "$gen_dir_base$cpu"
gen_stub_file = "$gen_dir/lib$output_name.so"
action(gen_target) {
forward_variables_from(invoker,
[
"visibility",
"testonly",
"deps",
])
if (defined(visibility)) {
visibility += [
":$main_target",
":$stub_target",
]
}
# Output timestamps are not freshened if contents do not change.
all_outputs_fresh = false
script = _llvm_ifs
sources = [ invoker.abi ]
outputs = [ gen_stub_file ]
args = [
"--input-format=IFS",
"--target=$cpu-fuchsia",
"--write-if-changed",
"--output-elf=" + rebase_path(gen_stub_file, root_build_dir),
rebase_path(invoker.abi, root_build_dir),
]
}
}
} else {
not_needed(invoker,
[
"abi",
"deps",
])
}
}