blob: 1a73ff5488020bb6c976de57b12c7946ca83f0cb [file] [log] [blame]
# Copyright 2019 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.
# Like action() but using utility binaries from the C/C++ toolchain.
# This is the way to use `nm`, `objcopy`, etc.
#
# Parameters
#
# utils
# Required: Utilities to use, e.g. "nm", "objcopy", "objdump".
# Type: list(string)
#
# script
# Optional: Same as for action(). The script receives an implicit
# argument for each element in $utils giving the command to run.
# If omitted, then $utils must have only one element and that command
# itself will be run with $args just as given.
# Type: file
#
# args
# Required: Same as for action(). If there is a $script,
# the implicit $utils arguments precede $args.
# Type: list(string)
#
# deps, inputs, outputs, sources, testonly, visibility
# See action().
#
template("toolchain_utils_action") {
assert(defined(invoker.utils),
"toolchain_utils_action(\"$target_name\") requires `utils`")
forward_variables_from(invoker, [ "script" ])
utils_inputs = []
utils_paths = []
if (toolchain.tool_dir != "") {
# The toolchain binaries are in a specified location (e.g. a prebuilt).
foreach(util, invoker.utils) {
if (util == "cc") {
util = toolchain.cc
} else {
util = "${toolchain.tool_prefix}${util}"
}
util = "${toolchain.tool_dir}/${util}"
utils_inputs += [ util ]
utils_paths += [ rebase_path(util, root_build_dir) ]
}
} else {
# The toolchain binaries are just found in the system PATH.
# They won't be used as dependencies.
if (!defined(script)) {
# If there's no script, utils_paths[0] will become the script.
# But the script has to be a known location that's a dependency.
# So use a dummy wrapper as the script.
script = "/usr/bin/env"
}
foreach(util, invoker.utils) {
if (util == "cc") {
util = toolchain.cc
} else {
util = "${toolchain.tool_prefix}${util}"
}
utils_paths += [ util ]
}
}
action(target_name) {
forward_variables_from(invoker,
"*",
[
"args",
"script",
"utils",
])
if (!defined(inputs)) {
inputs = []
}
inputs += utils_inputs
if (defined(script)) {
args = utils_paths + invoker.args
} else {
script = rebase_path(utils_paths[0], "", root_build_dir)
assert(
utils_paths == [ utils_paths[0] ],
"toolchain_utils_action(\"$target_name\") without `script` must have exactly one element in `utils`")
args = invoker.args
}
}
}
# generated_file() containing output file name of a linking target.
#
# Parameters
#
# deps, outputs, testonly, visibility
# See generated_file(). $deps determines the contents as described below.
#
# This produces a generated_file() target with $outputs as given. The
# contents of the file list the link outputs reached by $deps. That is,
# for each target that links a binary (executable(), loadable_module(),
# shared_library() via library(), etc.) the path relative to
# $root_build_dir of the actual binary created by the linker (before
# stripping) will be listed, one per line. The dependency traversal is
# pruned at each linking target, so e.g. if an executable() is listed then
# neither its shared_library() dependencies nor any $data_deps leading to
# loadable_module() or executable() targets will be listed.
#
template("link_output_rspfile") {
generated_file(target_name) {
forward_variables_from(invoker,
[
"deps",
"outputs",
"testonly",
"visibility",
])
data_keys = [ "link_output" ]
walk_keys = [ "link_barrier" ]
output_conversion = "list lines"
}
}