blob: f4f1221980447a4345b995f43162535cbbf4b8c6 [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/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.
# - 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
#
# * public, public_configs, public_deps
# - Optional: As for shared_library().
#
template("ifs_shared_library") {
main_target = target_name
stub_target = "$target_name.stub"
config_target = "$target_name.config"
gen_target = "_ifs_shared_library.$target_name.$clang_cpu"
gen_label = ":$gen_target($default_toolchain)"
gen_dir =
get_label_info(gen_label, "target_gen_dir") + "/$target_name.$clang_cpu"
if (defined(invoker.output_name)) {
output_name = invoker.output_name
} else {
output_name = target_name
}
gen_stub_file = "$gen_dir/lib$output_name.so"
public_stub_file = "$root_out_dir/lib$output_name.so"
source_set(main_target) {
public_configs = []
forward_variables_from(invoker,
[
"visibility",
"public",
"public_configs",
"public_deps",
"testonly",
])
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) {
action(gen_target) {
forward_variables_from(invoker,
[
"visibility",
"testonly",
])
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",
"--arch=${clang_cpu}",
"--endianness=little",
"--bitwidth=64",
"--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" ])
}
}