blob: 73f39b0ef54e75b7cebefe5fcce61cd6ffc13573 [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.
declare_args() {
# If $clang_tool_dir is "", then this controls how the Clang toolchain
# binaries are found. If true, then the standard prebuilt is used.
# Otherwise the tools are just expected to be found by the shell via `PATH`.
use_prebuilt_clang = true
# Directory where the Clang toolchain binaries ("clang", "llvm-nm", etc.) are
# found. If this is "", then the behavior depends on $use_prebuilt_clang.
# This toolchain is expected to support both Fuchsia targets and the host.
clang_tool_dir = ""
}
# This is a string identifying the particular toolchain version in use. Its
# only purpose is to be unique enough that it changes when switching to a new
# toolchain, so that recompilations with the new compiler can be triggered.
#
# When using the prebuilt, the CIPD instance ID of the prebuilt is perfect.
# When not using the prebuilt, there isn't a quick way to extract the compiler
# version. But at least changing the setting to a different compiler will
# change the string.
clang_version_string = clang_tool_dir
if (clang_tool_dir == "" && use_prebuilt_clang) {
_prebuilt_dir = "$zx/prebuilt/downloads/clang"
clang_tool_dir = "$_prebuilt_dir/bin"
_prebuilt_cipd_version =
read_file("$_prebuilt_dir/.versions/clang.cipd_version", "json")
clang_version_string = _prebuilt_cipd_version.instance_id
}
_clang_lib_dir = "$clang_tool_dir/../lib"
# Human-readable identifier for the toolchain version.
#
# clang_version_string is useful for Fuchsia standard prebuilts, since it's
# the CIPD instance ID that can be looked up to find the compiler build.
# clang_version_description is something that can lead a human to find the
# specific toolchain, such as a source repository URL and revision identifier.
#
# TODO(mcgrathr): Make this the same repo/revision info from `clang --version`.
# e.g., clang_version_description = read_file("$_clang_lib_dir/VERSION")
clang_version_description = ""
# This file is provided by the toolchain to describe the runtime
# dependencies implied by linking a binary based on --target and other
# compiler switches. The file contains a JSON array of objects that map to
# the following GN schema. Each entry matches a single compilation mode
# and yields all the runtime dependencies implied by that mode.
#
# Type: list(scope)
#
# target
# Required: --target tuple a la ${toolchain.target_tuple}.
# Type: string
#
# cflags
# Optional: List of compilation flags that select this mode,
# e.g. "-fsanitizer=..." and the like.
# Type: list(string)
# Default: []
#
# ldflags
# Optional: Link-time flags that select this mode.
# This is either [ "-static-libstdc++" ] or [].
# Type: list(string)
# Default: []
#
# runtime
# Required: List of runtime files needed by binaries in this mode.
# Type: list(scope)
#
# soname
# Required: `DT_SONAME` string in the ELF shared library.
# Type: string
#
# dist
# Required: File to load to satisfy $soname `DT_NEEDED` entries.
# Type: path relative to JSON file's directory
#
# debug
# Optional: Unstripped or separate debug file matching $dist.
# Type: path relative to JSON file's directory
#
_clang_runtime_file = "$_clang_lib_dir/runtime.json"
clang_runtime = read_file(_clang_runtime_file, "json")
# Provide deps required by toolchain-provided runtime libraries.
#
# Every linking target, such as executable(), shared_library(), or
# loadable_module(), needs this in deps to represent the link-time and
# runtime dependencies of support code the compiler links in implicitly.
# The parameters indicate the compilation mode in terms of the link-time
# and compile-time flags used. These must exactly match lists supplied by
# the toolchain in $clang_runtime to select for things like instrumentation
# and shared vs static linking of the standard C++ library.
#
# Parameters
#
# cflags, ldflags
# Required: Flags to match in the runtimes manifest.
# Type: list(string)
#
template("toolchain_runtime_deps") {
group(target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
# This information comes out the same in the main and the shlib
# toolchains. But we don't want two copies to appear in the metadata
# collection, so we always redirect to the shlib toolchain (when there
# is one). Note that multiple toolchains (variants that aren't that
# different, e.g. uninstrumented variants) may produce identical
# manifest entries because they match the same entries in the
# clang_runtime and use the same ${toolchain.libprefix} string. That
# is less than ideal but it does no harm since the tools like zbi that
# consume manifests accept redundant entries if they are identical.
if (!defined(toolchain.shlib) || current_toolchain == toolchain.shlib) {
if (defined(toolchain.shlib) && defined(visibility)) {
visibility += [ ":$target_name" ]
}
match = false
foreach(config, clang_runtime) {
if (!defined(config.cflags)) {
config.cflags = []
}
if (!defined(config.ldflags)) {
config.ldflags = []
}
if (config.target + [ toolchain.target_tuple ] -
[ toolchain.target_tuple ] != config.target &&
invoker.cflags == config.cflags &&
invoker.ldflags == config.ldflags) {
match = config
}
}
assert(match != false,
"$_clang_runtime_file has no match for" +
" --target=${toolchain.target_tuple} + $invoker")
metadata = {
binaries = []
manifest_lines = []
foreach(lib, match.runtime) {
# For build_api_module("binaries") in $zx/BUILD.gn.
binaries += [
{
cpu = current_cpu
os = current_os
environment = toolchain.environment
label = get_label_info(":$target_name", "label_with_toolchain")
type = "shared_library"
dist = rebase_path(lib.dist, root_build_dir, _clang_lib_dir)
if (defined(lib.debug)) {
debug = rebase_path(lib.debug, root_build_dir, _clang_lib_dir)
}
target_tuple = match.target
cflags = match.cflags
ldflags = match.ldflags
if (clang_version_string != "") {
toolchain_id = clang_version_string
}
if (clang_version_description != "") {
toolchain_version = clang_version_description
}
},
]
# This is the main purpose of the whole target.
manifest_lines +=
[ "lib/${toolchain.libprefix}${lib.soname}=" +
rebase_path(lib.dist, root_build_dir, _clang_lib_dir) ]
}
}
} else {
public_deps = [
":$target_name(${toolchain.shlib})",
]
not_needed(invoker,
[
"cflags",
"ldflags",
])
}
}
}