| # 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. |
| |
| import("//build/board.gni") |
| import("//build/config/build_id.gni") |
| import("//build/config/clang/clang.gni") |
| import("//build/config/clang/crash_diagnostics.gni") |
| import("//build/config/compiler.gni") |
| import("//build/config/linker.gni") |
| import("//build/config/zircon/levels.gni") |
| import("//build/toolchain/variant.gni") |
| |
| # NOTE: This file provides the GN configs used by Zircon toolchains |
| # exclusively. See //build/toolchain/zircon/zircon_toolchain.gni. |
| # |
| # Major differences in the rewrite: |
| # |
| # - Uses |zircon_toolchain| global variable, instead of |toolchain|. |
| # |
| # - All code paths related to |is_host| has been removed (the Zircon toolchain |
| # are never used to build host binaries). |
| |
| # These flags are enabled by default in Fuchsia's Clang toolchain, but we set |
| # them explicitly to support other Clang toolchains and Clang-based tools. |
| config("clang_defaults") { |
| if (clang_embed_bitcode) { |
| cflags += [ |
| "-Xclang", |
| "-fembed-bitcode=all", |
| ] |
| } |
| if (current_cpu == "x64") { |
| asmflags = [ "-Wa,--mrelax-relocations=yes" ] |
| } |
| if (current_os == "linux") { |
| cflags_cc = [ "-stdlib=libc++" ] |
| ldflags = [ |
| "-stdlib=libc++", |
| "-unwindlib=libunwind", |
| "-rtlib=compiler-rt", |
| ] |
| } |
| } |
| |
| config("compiler") { |
| # Per CPU targeting policy we always target the baseline when building the |
| # kernel, rather than using board_configs. This is done to reduce binary |
| # diversity. See: TODO RFC LINK HERE |
| configs = [ "//build/config:cpu_baseline" ] |
| |
| compiler_flags = [] |
| cflags_cc = [] |
| defines = [] |
| ldflags = [] |
| |
| # NOTE: This config should only be used with Zircon-specific toolchains |
| # but this BUILD.gn file is also included from non-Zircon ones. To |
| # avoid un-necessary GN errors, define a fake local zircon_toolchain |
| # scope to ensure this config() definitions executes properly even if |
| # it is never used. |
| if (zircon_toolchain == false) { |
| zircon_toolchain = { |
| target_tuple = "" |
| version_string = "" |
| include_dirs_cc = [] |
| lib_dirs = [] |
| } |
| } |
| |
| # For GCC, the compiler command implies the target. |
| # For Clang, there's a single compiler command that takes `--target`. |
| if (!is_gcc) { |
| compiler_flags += [ "--target=${zircon_toolchain.target_tuple}" ] |
| } |
| |
| if (linker != "") { |
| ldflags += [ "-fuse-ld=$linker" ] |
| } |
| |
| if (defined(zircon_toolchain.version_string) && |
| zircon_toolchain.version_string != "") { |
| # Nothing uses this define, but its presence on compilation command |
| # lines ensures that Ninja will rebuild things when a new compiler |
| # version arrives. |
| defines += [ "TOOLCHAIN_VERSION=${zircon_toolchain.version_string}" ] |
| } |
| |
| # This is the default already on Fuchsia and maybe others, but never hurts. |
| cflags = [ "-fno-common" ] |
| |
| configs += [ |
| "//build/config:color_diagnostics", |
| "//build/config:crash_diagnostics", |
| |
| # TODO: "$current_os:compiler", |
| ] |
| if (!is_gcc) { |
| configs += [ ":clang_defaults" ] |
| } |
| |
| if (is_fuchsia) { |
| # ld.bfd doesn't support -z relro for the targets we use it for. |
| if (!is_gcc || linker == "gold") { |
| ldflags += [ "-Wl,-z,relro" ] |
| } |
| |
| if (is_gcc) { |
| # This is predefined by Clang --target=*-fuchsia. |
| # But the GCC toolchain is the generic --target=*-elf one. |
| defines += [ "__Fuchsia__" ] |
| |
| # These are done by default in the Clang toolchain. |
| cflags += [ "-fasynchronous-unwind-tables" ] |
| ldflags += [ |
| "-Wl,--build-id", |
| "-Wl,--hash-style=gnu", |
| "-Wl,-z,now", |
| "-Wl,-z,combreloc", |
| "-Wl,-z,text", |
| ] |
| |
| if (!is_kernel) { |
| ldflags += [ "-Wl,--eh-frame-hdr" ] |
| } |
| |
| if (linker == "" || linker == "bfd") { |
| # This is the default in both LLD and Gold, but not in BFD. |
| # However, Gold doesn't even have the switch. |
| ldflags += [ "-Wl,-z,separate-code" ] |
| } |
| |
| # In the Clang toolchain assembly files with no explicit marker don't |
| # cause the presumption of executable stack as they do in GCC. |
| ldflags += [ "-Wl,-z,noexecstack" ] |
| |
| if (current_cpu == "arm64") { |
| # x18 is reserved in the Fuchsia ABI so it can be used |
| # for things like -fsanitize=shadow-call-stack. |
| cflags += [ "-ffixed-x18" ] |
| } |
| } else { |
| # gcc defaults to enabling sized deallocation >= c++14; clang does not. |
| # Enable sized-deallocation for the kernel, so the heap implementation can |
| # optimize for or check generated sizes. |
| cflags += [ "-fsized-deallocation" ] |
| } |
| } else if (current_os == "win") { |
| # This enables build ID-like PDB UUIDs without timestamp. |
| ldflags += [ "-Wl,/Brepro" ] |
| } |
| |
| # The toolchain-supplied headers come after include_dirs from targets and |
| # configs but before libc. |
| foreach(dir, zircon_toolchain.include_dirs_cc) { |
| cflags_cc += [ |
| "-isystem", |
| rebase_path(dir, root_build_dir), |
| ] |
| } |
| |
| lib_dirs = zircon_toolchain.lib_dirs |
| |
| asmflags = compiler_flags |
| cflags += compiler_flags |
| ldflags += compiler_flags |
| |
| if (is_fuchsia && build_id_format != "") { |
| ldflags += [ "-Wl,--build-id=$build_id_format" ] |
| } |
| } |
| |
| config("nolibc") { |
| ldflags = [ "-nostartfiles" ] |
| |
| # Don't use -nostdlib, because the builtins (or libgcc) are what we want |
| # and are otherwise annoying to find and specify. It's just the -lc that |
| # we really want to defeat, and that's handled by giving a -L that will |
| # find exactly nothing but a dummy libc.so. Clang has -nolibc to kill |
| # the -lc, but for C++ it still uses -lm under -nolibc. So this is still |
| # needed to make -lm into a dummy, though for -lc only GCC needs it. |
| lib_dirs = [ "libc-dummy" ] |
| |
| if (is_gcc) { |
| # Include this in every link. |
| # Note GN requires "./" so it doesn't think this should mean a -l switch. |
| libs = [ "./dso_handle.ld" ] |
| } else { |
| # TODO(mcgrathr): GCC 9 has -nolibc, so use it when we get that toolchain. |
| ldflags += [ "-nolibc" ] |
| } |
| } |
| |
| config("freestanding") { |
| cflags = [ "-ffreestanding" ] |
| |
| # In Clang -fasynchronous-unwind-tables is the default for *-fuchsia |
| # targets. But -ffreestanding defeats that (in target-independent logic |
| # in the Clang driver). So add it back explicitly. For GCC, it's |
| # already added explicitly in :compiler regardless so don't double it. |
| if (!is_gcc) { |
| cflags += [ "-fasynchronous-unwind-tables" ] |
| } |
| |
| ldflags = cflags |
| } |
| |
| config("data_sections") { |
| cflags = [ "-fdata-sections" ] |
| ldflags = cflags |
| } |
| |
| # The 'default_assert_level' will point to one of the assert_level_<n> values |
| # below. This allows targets or toolchains to opt out from the default and |
| # select a specific value. |
| |
| foreach(level, |
| [ |
| 0, |
| 1, |
| 2, |
| ]) { |
| variant("assert_level_$level") { |
| defines = [ "ZX_ASSERT_LEVEL=$level" ] |
| if (level == 0) { |
| defines += [ "NDEBUG" ] |
| } |
| } |
| } |
| |
| variant("default_assert_level") { |
| assert( |
| zx_assert_level >= 0 && zx_assert_level <= 2, |
| "Invalid zx_assert_level value '$zx_assert_level', valid values are 0, 1 or 2") |
| configs = [ ":assert_level_$zx_assert_level" ] |
| } |
| |
| # This is separate from default_optimize so it can be removed. |
| config("default_icf") { |
| if (optimize != "none" && optimize != "debug") { |
| # Our code should never rely on C's unique function pointer semantics, |
| # which is broken by --icf=all for sometimes substantial space savings. |
| configs = [ "//build/config:icf" ] |
| } |
| } |
| |
| config("default_template_backtrace_limit") { |
| cflags_cc = [ "-ftemplate-backtrace-limit=0" ] |
| } |
| |
| config("no_threadsafe_statics") { |
| cflags_cc = [ "-fno-threadsafe-statics" ] |
| cflags_objcc = cflags_cc |
| } |
| |
| config("default_include_dirs") { |
| include_dirs = [ "//zircon/system/public" ] |
| } |
| |
| config("no_fuzzer") { |
| if (!is_gcc) { |
| cflags = [ "-fno-sanitize=fuzzer" ] |
| } |
| } |
| |
| # TODO(fxbug.dev/27266) Remove this once the warning with fit::variant is addressed. |
| config("no_maybe_uninitialized") { |
| if (is_gcc) { |
| cflags = [ "-Wno-maybe-uninitialized" ] |
| } |
| } |
| |
| config("machine") { |
| if (is_fuchsia && is_gcc) { |
| # TODO(fxbug.dev/32157): Really need to get this nailed down once and for all |
| # and set by default in the compiler driver (Clang at least). |
| ldflags = [ "-Wl,-z,max-page-size=4096" ] |
| } |
| } |
| |
| # TODO(fxbug.dev/54322): Use the config under //third_party/ulib/musl once the C |
| # library has been migrated to the GN build. |
| config("musl_headers") { |
| _musl_dir = "//zircon/third_party/ulib/musl" |
| visibility = [ |
| "${_musl_dir}/*", |
| "//zircon/system/ulib/c:*", |
| ] |
| cflags = [ |
| "-idirafter", |
| rebase_path("${_musl_dir}/include", root_build_dir), |
| ] |
| asmflags = cflags |
| } |
| |
| variant("user") { |
| defines = [ "_ALL_SOURCE" ] |
| configs = [ |
| ":nolibc", |
| ":musl_headers", |
| ] |
| |
| if (is_gcc) { |
| # This is the default in Clang for Fuchsia targets. In shlib toolchains |
| # this config will come before the one that overrides it with -fPIC. |
| common_flags = [ "-fPIE" ] |
| } |
| } |
| |
| variant("user-executable") { |
| # This prevents the default dynamic linker from being embedded. Other deps |
| # can still set PT_INTERP either via link inputs with a `.interp` section, or |
| # ldflags that come later with an explicit `-Wl,-dynamic-linker=...`. |
| ldflags = [ "-Wl,--no-dynamic-linker" ] |
| if (is_gcc) { |
| # This is already the default in Clang for Fuchsia targets. |
| ldflags += [ "-pie" ] |
| |
| # Gold doesn't handle --no-dynamic-linker and won't produce a PIE without a |
| # PT_INTERP. |
| ldflags += [ "-fuse-ld=bfd" ] |
| } |
| |
| # crt1 and libc will come via explicit link dependencies if at all. |
| ldflags += [ |
| "-nostartfiles", |
| "-nolibc", |
| ] |
| } |
| |
| config("integer-paranoia") { |
| cflags = [ |
| "-fsanitize=integer-divide-by-zero,signed-integer-overflow", |
| "-fsanitize-undefined-trap-on-error", |
| ] |
| } |
| |
| config("static-libc++") { |
| if (current_os == "mac") { |
| # The macOS driver doesn't support -static-libstdc++ properly, so pass |
| # the libraries directly. This has to locate the files explicitly in |
| # the toolchain, because -lc++ would look for the shared library. |
| ldflags = [ |
| "-nostdlib++", |
| |
| # NOTE: the path below was relative to toolchain.tool_dir in the Zircon build |
| # but the Fuchsia one doesn't support GCC-based host builds at all, so this |
| # is assuming Clang is always used instead. |
| "${rebased_clang_prefix}/../lib/libc++.a", |
| ] |
| } else { |
| ldflags = [ "-static-libstdc++" ] |
| |
| # TODO(fxbug.dev/26846): The implicitly linked static libc++.a depends on these. |
| if (current_os == "linux") { |
| libs = [ |
| "dl", |
| "pthread", |
| ] |
| } |
| } |
| } |
| |
| # This config is used for code that needs to be purely position-independent |
| # without using dynamic relocation. Since the compiler doesn't generally make |
| # guarantees about this, it's sometimes necessary to disable specific optimizations |
| # to ensure the code with this requirement doesn't get compiled in ways that won't |
| # work. This config can be changed to add switches when those needs arise. |
| config("pure") { |
| # TODO(fxbug.dev/125225): This disables the SwitchToLookupTable optimization, |
| # which is not PIC-friendly under LTO. |
| if ((current_toolchain == shlib_toolchain || |
| toolchain_variant.is_pic_default) && |
| toolchain_variant.tags + [ "lto" ] - [ "lto" ] != |
| toolchain_variant.tags) { |
| cflags = [ "-fno-jump-tables" ] |
| } |
| } |
| |
| variant("rodso") { |
| configs = [ ":pure" ] |
| if (is_gcc) { |
| inputs = [ "rodso.ld" ] |
| ldflags = [ "-Wl,-T," + rebase_path(inputs[0], root_build_dir) ] |
| } |
| } |
| |
| # This has to be variant() rather than config() to be used in the toolchain |
| # configs list. |
| variant("tiny") { |
| cflags = [ "-mcmodel=tiny" ] |
| asmflags = cflags |
| ldflags = cflags |
| } |
| |
| # Statically linked posititon independent executable. |
| # |
| # These have to be variant() rather than config() to be used in the toolchain |
| # configs list. |
| variant("static-pie-compile") { |
| cflags = [ "-fPIE" ] |
| } |
| |
| variant("static-pie-link") { |
| ldflags = [ |
| "-Wl,-pie", |
| "-Wl,--no-dynamic-linker", |
| ] |
| } |
| |
| # Disallow C++ static initializers in functions that require runtime init. |
| config("forbid-guard-variables") { |
| if (!is_gcc) { |
| cflags_cc = [ |
| "-Xclang", |
| "-fforbid-guard-variables", |
| ] |
| } |
| } |
| |
| # This is used by hermetic_code_blob() in hermetic_code_blob.gni. |
| config("hermetic-code-blob") { |
| inputs = [ "hermetic-code-blob.ld" ] |
| |
| # Use a custom linker script rather than the default PIE layout. |
| ldflags = [ "-Wl,-T," + rebase_path(inputs[0], root_build_dir) ] |
| |
| # lld defaults to PIE, while the GNU linkers do not. |
| if (!is_gcc) { |
| ldflags += [ "-Wl,--no-pie" ] |
| } |
| |
| # Don't add any additional sections or dependencies. |
| ldflags += [ |
| "-Wl,--build-id=none", |
| "-Wl,--no-dynamic-linker", |
| "-Wl,--no-eh-frame-hdr", |
| ] |
| if (!is_kernel) { |
| ldflags += [ |
| "-static", |
| "-nostartfiles", |
| ] |
| if (is_gcc) { |
| ldflags += [ "-nostdlib" ] |
| } else { |
| # Note this can still link in builtins, which is generally OK for user |
| # code (even the basic machine ABI), but not for kernel code that has its |
| # own ABI requirements. |
| ldflags += [ |
| "-nolibc", |
| "-nostdlib++", |
| "-unwindlib=none", |
| ] |
| } |
| } |
| } |