| # Copyright 2020 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. |
| |
| # This file exists to find the GN toolchain() instance used to build |
| # the version of the C library used for regular Fuchsia packages (which is |
| # potentially instrumented), as well as the version used by the Fuchsia |
| # system package (which may be different, as it must not be instrumented, |
| # but could still be built with a variant like "gcc" or "thinlto"). |
| # |
| # For more details, see the extensive TECHNICAL NOTE in the comments at |
| # the end of this file. |
| |
| # The C library's own GN target label, without a toolchain |
| sysroot_libc_label = "//zircon/system/ulib/c" |
| |
| # The base toolchain used to build the C library. This is the toolchain that is used |
| # when no variant is selected by the user through `select_variant` in args.gn. |
| sysroot_libc_base_toolchain = "//zircon/system/ulib/c:user.libc_$target_cpu" |
| |
| # The variant selector fields corresponding to the C library. |
| # Keep it in sync with the definitions of user.libc_${target_cpu} |
| # in //zircon/system/ulib/c/BUILD.gn! |
| # |
| _select_host = false |
| _select_testonly = false |
| _select_target_type = [ "shared_library" ] |
| _select_output_name = [ "libc.so" ] |
| _select_label = [ "//zircon/system/ulib/c" ] |
| _select_name = [ "c" ] |
| _select_dir = [ "//zircon/system/ulib/c" ] |
| _select_exclude_toolchain_tags = [ "fuzzer" ] |
| |
| # ====================================================================== |
| # START OF CODE TO KEEP IN SYNC WITH BUILDCONFIG.gn |
| # |
| # IMPORTANT: Always keep the code below in sync with the computations |
| # performed by variant_target() within //build/config/BUILDCONFIG.gn. |
| # |
| _instrumented_target_variant = "" |
| _uninstrumented_target_variant = "" |
| |
| if (select_variant_canonical != []) { |
| _selected = false |
| |
| foreach(selector, select_variant_canonical) { |
| if (_instrumented_target_variant == "" || |
| _uninstrumented_target_variant == "") { |
| _selector = { |
| } |
| _selector = { |
| target_type = [] |
| output_name = [] |
| label = [] |
| name = [] |
| dir = [] |
| forward_variables_from(selector, "*") |
| } |
| |
| _selected = true |
| if (_selected && defined(_selector.host)) { |
| _selected = _selector.host == _select_host |
| } |
| |
| if (_selected && defined(_selector.testonly)) { |
| _selected = _selector.testonly == _select_testonly |
| } |
| |
| if (_selected && _selector.target_type != []) { |
| _selected = _selector.target_type + _select_target_type - |
| _select_target_type != _selector.target_type |
| } |
| |
| if (_selected && _selector.output_name != []) { |
| _selected = _selector.output_name + _select_output_name - |
| _select_output_name != _selector.output_name |
| } |
| |
| if (_selected && _selector.label != []) { |
| _selected = |
| _selector.label + _select_label - _select_label != _selector.label |
| } |
| |
| if (_selected && _selector.name != []) { |
| _selected = |
| _selector.name + _select_name - _select_name != _selector.name |
| } |
| |
| if (_selected && _selector.dir != []) { |
| _selected = _selector.dir + _select_dir - _select_dir != _selector.dir |
| } |
| |
| if (_selected && _select_exclude_toolchain_tags != []) { |
| _selected = _select_exclude_toolchain_tags + _selector.variant_tags - |
| _selector.variant_tags == _select_exclude_toolchain_tags |
| } |
| |
| if (_selected && _selector.variant != false) { |
| if (_selector.variant_tags + [ "instrumented" ] - [ "instrumented" ] != |
| _selector.variant_tags) { |
| if (_instrumented_target_variant == "") { |
| _instrumented_target_variant = "-${_selector.variant}" |
| } |
| } else if (_uninstrumented_target_variant == "") { |
| _uninstrumented_target_variant = "-${_selector.variant}" |
| } |
| } |
| } |
| } |
| } |
| |
| # END OF CODE TO KEEP IN SYNC WITH BUILDCONFIG.gn! |
| # ================================================================== |
| |
| # See technical note below to understand why these computations are necessary. |
| if (_instrumented_target_variant != "") { |
| _user_target_variant = _instrumented_target_variant |
| } else { |
| _user_target_variant = _uninstrumented_target_variant |
| } |
| |
| _system_target_variant = _uninstrumented_target_variant |
| |
| # This is the toolchain used to build the C library that appears in the system package, |
| # i.e. that is installed under /lib/ld.so.1. It must be a non-instrumented version of |
| # the library, though a variant like "gcc" might be applied to it. |
| system_libc_toolchain = sysroot_libc_base_toolchain + _system_target_variant |
| |
| if (is_fuchsia) { |
| # When in a toolchain variant of the Fuchsia base toolchain, find the |
| # corresponding toolchain variant of user.libc_$target_cpu to build |
| # the C library with it. |
| sysroot_libc_toolchain = sysroot_libc_base_toolchain |
| if (toolchain_variant.suffix != "") { |
| sysroot_libc_toolchain = |
| sysroot_libc_base_toolchain + |
| string_replace(toolchain_variant.suffix, "-fuzzer", "") |
| } else { |
| sysroot_libc_toolchain = system_libc_toolchain |
| } |
| } else { |
| # This is the toolchain used to build the C library for regular Fuchsia packages. |
| # If an instrumented toolchain is used, it will be installed as lib/<variant>/ld.so.1 |
| # as expected by other user-level binaries. |
| sysroot_libc_toolchain = sysroot_libc_base_toolchain + _user_target_variant |
| } |
| |
| # The GN target that builds the C library for the current variant selection. |
| sysroot_libc_target = "$sysroot_libc_label($sysroot_libc_toolchain)" |
| |
| # The paths to the binaries generated by the C library target. Note that these |
| # are called libc.so, but are installed in packages or the system as ld.so.1. |
| sysroot_libc_stripped = |
| get_label_info(sysroot_libc_target, "root_out_dir") + "/libc.so" |
| sysroot_libc_unstripped = sysroot_libc_stripped + ".debug" |
| |
| # The GN target that builds the system C library. This is required for certain |
| # binaries that are placed in the system package, and expect to find the library |
| # under lib/ld.so.1, instead of lib/<variant>/ld.so.1 |
| system_libc_target = "$sysroot_libc_label($system_libc_toolchain)" |
| system_libc_stripped = |
| get_label_info(system_libc_target, "root_out_dir") + "/libc.so" |
| system_libc_unstripped = system_libc_stripped + ".debug" |
| |
| # The C runtime startup object, which must be linked to all Fuchsia executable |
| # binaries. |
| sysroot_crt1_toolchain = sysroot_libc_toolchain |
| sysroot_crt1_target = "//zircon/system/ulib/c:crt1($sysroot_crt1_toolchain)" |
| |
| sysroot_crt1_obj = |
| get_label_info(sysroot_crt1_target, "target_out_dir") + "/crt1.Scrt1.cc.o" |
| |
| # TECHNICAL NOTE |
| # |
| # This file exists because the C library, while technically not part of the |
| # system in Fuchsia, still requires very special care during the build. |
| # |
| # Its main purpose is to find the GN toolchain() instance that is used to |
| # build the uninstrumented version of 'libc.so', based on the current set |
| # of variant selectors (i.e. 'select_variant' as defined in |
| # 'out/default/args.gn') |
| # |
| # Some critical considerations to be aware of to understand what's below: |
| # |
| # - The C library is built as 'libc.so' and 'libc.so.debug', for the stripped |
| # and unstripped versions, respectively. |
| # |
| # The stripped version is installed into Fuchsia packages and is used |
| # at runtime. The unstripped version is used at link time and for |
| # debugging + symbolization. |
| # |
| # - The C library can be built with GCC, instead of Clang. This is usually |
| # done by enabling the "gcc" variant, which is ignored by non-Zircon specific |
| # targets (in other words, Fuchsia user binaries are never built with GCC |
| # even if this variant is enabled). |
| # |
| # - The stripped C library (libc.so) will be installed as 'lib/ld.so.1' |
| # by default within Fuchsia packages. This is because it implements both |
| # the C runtime and the dynamic loader at the same time. Fuchsia user |
| # executables contain a direct reference to this location inside their |
| # dynamic section. |
| # |
| # However, a Fuchsia executable built with an _instrumented_ variant, |
| # will look at runtime for 'lib/<variant>/ld.so.1' instead, which |
| # should contain the version of 'libc.so' compiled for the same variant. |
| # |
| # E.g., if the "asan" variant is enabled, then an executable installed |
| # as 'bin/program' will use 'lib/asan/ld.so.1' to find the dynamic loader, |
| # and this file should be a copy of 'out/default/user.libc_x64-asan/libc.so'. |
| # |
| # Hence, which version of the C library is associated with a given |
| # executable binary depends on the variant used to build it. |
| # |
| # As a reminder, our build system provides the ability to enable different |
| # variants for different targets, e.g.: |
| # |
| # select_variant = [ |
| # "ubsan/cat", |
| # "profile/echo", |
| # "asan" |
| # ] |
| # |
| # Would build the 'cat' executable with the 'ubsan' variant, the |
| # 'echo' one with the 'profile' variant, and all other Fuchsia executables |
| # with the 'asan' one. |
| # |
| # - Even if no variant is enabled in a given build, the "asan" and "asan-ubsan" |
| # variants of the C library need to be built and exported to the Fuchsia SDK. |
| # (see //zircon/system/ulib/c/sysroot_entries.gni for details). |
| # |
| # - The "system package" is a special Fuchsia package that contains system |
| # libraries and binaries (i.e. those required to boot the system). It requires |
| # an un-instrumented C library in 'lib/ld.so.1', since several prebuilt |
| # driver binaries depend on it. |
| # |
| # And this, even if a variant is enabled to build all Fuchsia binaries. |
| # Note that non-instrumented variants still need to apply to this binary |
| # (e.g. "gcc" or "thinlto"). |
| # |
| # - Finally, when linking executables or ELF shared objects, the C++ compiler |
| # will by default inject implicit dependencies to various libraries and |
| # object files, i.e.: |
| # |
| # - Adding an implicit '-lc' and '-lm' link argument before invoking |
| # the final linker program. |
| # |
| # - Adding implicit dependencies to compiler-builtins support libraries |
| # (e.g. '-lgcc'), the C++ runtime library (e.g. '-lc++') and other |
| # instrumentation-related runtime libraries (e.g. '-lclang_rt.asan') |
| # when needed. |
| # |
| # - For ELF executables, it will also search for a file named 'Scrt1.o' |
| # which contains the low-level C runtime startup code (i.e. the |
| # one that implements the '_start' entry point, called by the |
| # system once the executable and its dependent libraries are |
| # loaded, its role is to initialize the C runtime, then jump |
| # off to the main() function). |
| # |
| # All of these can be controlled by an array of compiler/linker flags, |
| # the most important one being the --sysroot=DIR option used to specify |
| # the location of these system headers and libraries at build time. |
| # |
| # - Rust and Go binaries do not participate in variant selection. As such |
| # they should always be linked against a non-instrumented version of |
| # the C library, even if an instrumented variant is used for other |
| # C++ Fuchsia binaries. |
| # |
| # - Apparently, it is ok to link an instrumented executable or loadable |
| # module against a non-instrumented C library at build time, as long |
| # as the proper instrumented binary is installed into the corresponding |
| # Fuchsia package. |
| # |
| # That is the way the build worked before unification, and continues to |
| # do so for now. In the future, it might be possible to use the right |
| # instrumented C library at link time instead. |
| # |
| |