| # 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", |
| ]) |
| } |
| } |
| } |