| # 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 |
| # |
| # * public, public_configs, public_deps |
| # - Optional: As for shared_library(). |
| # |
| # * deps |
| # - Optional: Any dependencies that went into the creation of the supplied |
| # `.ifs` file. |
| # |
| 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 = "$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) { |
| # 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", |
| ]) |
| } |
| } |