blob: a7ef9c60ee7c505981ecdf72bdac24fad24718a0 [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.
import("levels.gni")
# TODO: download all host sysroot prebuilts
if (host_os == "mac") {
_prebuilt_sysroot = []
} else {
_prebuilt_sysroot = "$zx/prebuilt/downloads/sysroot"
}
declare_args() {
# The `--sysroot` directory for host compilations.
# This can be a string, which only applies to $host_os-$host_cpu.
# Or it can be a list of scopes containing `cpu`, `os`, and `sysroot`.
# The empty list (or empty string) means don't use `--sysroot` at all.
sysroot = _prebuilt_sysroot
}
# Convert a string to a list.
if (sysroot == "") {
sysroot = []
} else if (sysroot == "$sysroot") {
sysroot = [
{
cpu = host_cpu
os = host_os
sysroot = sysroot
},
]
}
config("sysroot") {
foreach(host, sysroot) {
if (host.cpu == current_cpu && host.os == current_os) {
compiler_flags =
[ "--sysroot=" + rebase_path(host.sysroot, root_build_dir) ]
}
}
}
if (is_gcc) {
# Assume ld.gold is available for any native Linux host, and for any ELF
# cross-compile target. Use Gold for userland, and BFD ld for kernel.
if (current_os == "linux" ||
((current_cpu != host_cpu || current_os != host_os) && !is_kernel &&
current_os != "mac" && current_os != "win")) {
linker = "gold"
} else {
# For GCC on non-ELF hosts, use the system default linker.
linker = ""
}
} else {
# Always use lld with Clang.
linker = "lld"
}
config("compiler") {
compiler_flags = []
defines = []
ldflags = []
# For GCC, the compiler command implies the target.
# For Clang, there's a single compiler command that takes `--target`.
if (!is_gcc && (current_cpu != host_cpu || current_os != host_os)) {
compiler_flags += [ "--target=${toolchain.target_tuple}" ]
}
if (linker != "") {
ldflags += [ "-fuse-ld=$linker" ]
}
if (defined(toolchain.version_string) && 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=${toolchain.version_string}" ]
}
# This is the default already on Fuchsia and maybe others, but never hurts.
cflags = [ "-fno-common" ]
public_deps = [
":color_diagnostics",
# TODO: "$current_os:compiler",
]
if (is_host) {
public_deps += [ ":sysroot" ]
if (current_os != "win" && current_os != "mac") {
ldflags += [ "-Wl,--build-id" ]
}
} else if (is_gcc) {
# This is predefined by Clang --target=*-fuchsia.
# But the GCC toolchain is the generic --target=*-elf one.
defines += [ "__Fuchsia__" ]
# This is done by default in the Clang toolchain.
ldflags += [ "-Wl,--build-id" ]
}
if (current_os == "linux") {
public_deps += [ ":static-libc++" ]
}
if (current_cpu == "arm64") {
# Generate code for the fairly generic cortex-a53.
compiler_flags += [ "-mcpu=cortex-a53" ]
# x18 is reserved in the Fuchsia userland ABI so it can be used
# for things like -fsanitize=shadow-call-stack. In the kernel,
# it's reserved so we can use it to point at the per-CPU structure.
compiler_flags += [ "-ffixed-x18" ]
}
if (current_os == "linux") {
public_deps += [ ":static-libc++" ]
}
include_dirs = toolchain.include_dirs
lib_dirs = toolchain.lib_dirs
}
config("language") {
cflags_c = [ "-std=c11" ]
cflags_cc = [ "-std=c++17" ]
}
config("color_diagnostics") {
# GCC correctly defaults this from the terminal, so leave it alone.
if (!is_gcc) {
compiler_flags = [ "-fcolor-diagnostics" ]
# The macOS linker does not support `--color-diagnostics`.
if (current_os != "mac") {
ldflags = [ "-Wl,--color-diagnostics" ]
}
}
}
config("relative_paths") {
# Make builds independent of absolute file path. The file names embedded
# in debugging information will be expressed as relative to the build
# directory, e.g. "../.." for an "out/subdir" under //. This is
# consistent with the file names in __FILE__ expansions (e.g. in
# assertion messages), which the compiler doesn't provide a way to remap.
# That way source file names in logging and symbolization can all be
# treated the same way. This won't go well if $root_build_dir is not a
# subdirectory of //, but there isn't a better option to keep all source
# file name references uniformly relative to a single root.
absolute_path = rebase_path("//.")
relative_path = rebase_path("//.", root_build_dir)
# This makes sure that the DW_AT_comp_dir string (the current
# directory while running the compiler, which is the basis for all
# relative source file names in the DWARF info) is represented as
# relative to //.
compiler_flags = [ "-fdebug-prefix-map=$absolute_path=$relative_path" ]
if (!is_gcc) {
# This makes sure that include directories in the toolchain are
# represented as relative to the build directory (because that's how we
# invoke the compiler), rather than absolute. This can affect __FILE__
# expansions (e.g. assertions in system headers). We normally run a
# compiler that's someplace within the source tree, so its absolute
# installation path will have a prefix matching `absolute_path` and
# hence be mapped to `relative_path` in the debugging information, so
# this should actually be superfluous for purposes of the debugging
# information.
compiler_flags += [ "-no-canonical-prefixes" ]
}
}
config("nostdlib") {
# Don't actually use -nostdlib, because the builtins and -lc++ 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.
ldflags = [ "-nostartfiles" ]
lib_dirs = [ "libc-dummy" ]
if (is_gcc) {
# Include this in every link.
libs = [ "$zx/scripts/dso_handle.ld" ]
}
}
config("data_sections") {
cflags = [ "-fdata-sections" ]
}
config("linker_gc") {
public_deps = [
":data_sections",
]
cflags = [ "-ffunction-sections" ]
ldflags = cflags
if (current_os == "mac") {
ldflags += [ "-Wl,-dead_strip" ]
} else if (current_os == "win") {
ldflags += [ "-Wl,/opt:ref" ]
} else {
ldflags += [ "-Wl,--gc-sections" ]
}
}
config("assert_level") {
assert(assert_level >= 0)
defines = [ "ZX_DEBUGLEVEL=$assert_level" ]
if (is_kernel) {
defines += [ "LK_DEBUGLEVEL=$assert_level" ]
}
if (assert_level == 0) {
defines += [ "NDEBUG" ]
}
}
config("opt_level") {
if (opt_level == -1) {
compiler_flags = [ "-O0" ]
} else {
assert(opt_level >= 0)
if (opt_level == 0) {
if (is_gcc) {
compiler_flags = [ "-O0" ]
} else {
compiler_flags = [ "-Og" ]
}
} else if (opt_level == 4) {
if (is_gcc) {
compiler_flags = [ "-Os" ]
} else {
compiler_flags = [ "-Oz" ]
}
} else {
compiler_flags = [ "-O$opt_level" ]
}
}
public_deps = []
if (opt_level > 1) {
public_deps += [ ":icf" ]
}
if (opt_level > 2) {
# Enable optimal string merging.
ldflags = [ "-Wl,-O2" ]
}
}
# This is separate from opt_level so it can be removed.
config("default_linker_gc") {
# TODO(mcgrathr): Kernel can't be built without --gc-sections.
if (opt_level > 0 || toolchain.environment == "kernel") {
public_deps = [
":linker_gc",
]
}
}
config("symbol_level") {
assert(symbol_level >= 0 && symbol_level <= 2)
if (symbol_level == 0) {
compiler_flags = [ "-g0" ]
} else if (symbol_level == 1) {
compiler_flags = [ "-gline-tables-only" ]
} else if (symbol_level == 2) {
compiler_flags = [ "-g3" ]
}
if (symbol_level > 0 && current_os == "win") {
# TODOD: ??? This produces the .pdb file, but it doesn't seem
# to get the DWARF data out of the main output file.
ldflags = [ "-Wl,/debug:full" ]
}
}
config("werror") {
cflags = [
"-Werror",
# Declarations marked as deprecated should not cause build failures.
# Rather they should emit warnings to notify developers about the use
# of deprecated interfaces.
"-Wno-error=deprecated-declarations",
# Do not add additional `-Wno-error=...` switches to this config!
]
if (current_os == "win") {
ldflags = [ "-Wl,/WX" ]
}
}
config("default_warnings") {
cflags = [
"-Wall",
"-Wextra",
"-Wno-multichar",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-Werror=unused-label",
"-Werror=return-type",
]
cflags_c = [
"-Werror=implicit-function-declaration",
"-Wstrict-prototypes",
"-Wwrite-strings",
]
cflags_cc = [
"-Wconversion",
"-Wno-sign-conversion",
]
if (is_gcc) {
cflags += [
"-Wno-nonnull-compare",
"-Wno-format-truncation",
]
} else {
cflags += [
"-Wno-address-of-packed-member",
"-Wimplicit-fallthrough",
]
}
}
config("icf") {
# This changes C/C++ semantics and might be incompatible with third-party
# code that relies on function pointers comparison.
if (current_os == "win" && (linker == "lld" || !is_gcc)) {
ldflags = [ "-Wl,/opt:icf=all" ]
} else if (linker == "gold" || linker == "lld") {
ldflags = [ "-Wl,--icf=all" ]
}
}
config("exceptions") {
cflags_cc = [ "-fexceptions" ]
cflags_objcc = cflags_cc
}
config("no_exceptions") {
cflags_cc = [ "-fno-exceptions" ]
cflags_objcc = cflags_cc
}
config("rtti") {
cflags_cc = [ "-frtti" ]
cflags_objcc = cflags_cc
}
config("no_rtti") {
cflags_cc = [ "-fno-rtti" ]
cflags_objcc = cflags_cc
}
config("no_threadsafe_statics") {
cflags_cc = [ "-fno-threadsafe-statics" ]
cflags_objcc = cflags_cc
}
config("default_include_dirs") {
include_dirs = [
"$zx/system/public",
"$zx/system/private",
]
}
config("default_frame_pointers") {
if (true || opt_level < 2) {
public_deps = [
":frame_pointers",
]
} else {
public_deps = [
":no_frame_pointers",
]
}
}
config("frame_pointers") {
defines = [ "WITH_FRAME_POINTERS=1" ]
cflags = [ "-fno-omit-frame-pointer" ]
}
config("no_frame_pointers") {
defines = [ "WITH_FRAME_POINTERS=0" ]
cflags = [ "-fomit-frame-pointer" ]
}
config("thread_safety_annotations") {
if (!is_gcc) {
cflags = [ "-Wthread-safety" ]
defines = [ "_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS=1" ]
}
}
config("no_stack_protector") {
cflags = [ "-fno-stack-protector" ]
}
config("no_safestack") {
cflags = [ "-fno-sanitize=safe-stack" ]
public_deps = [
":no_stack_protector",
]
}
config("no_sanitizers") {
cflags = [ "-fno-sanitize=all" ]
public_deps = [
":no_stack_protector",
]
}
# Compile code appropriately to be linked into a shared library.
config("shared_library_config") {
if (current_os != "mac") {
# Assembly code can use `#ifdef __PIC__`.
compiler_flags = [ "-fPIC" ]
}
}
# Don't allow dangling undefined references in shared libraries.
# All references should be satisfied by link-time library dependencies.
config("no_undefined_symbols") {
if (current_os == "mac") {
ldflags = [ "-Wl,-undefined,error" ]
} else {
ldflags = [ "-Wl,-z,defs" ]
}
}
config("visibility_hidden") {
cflags = [ "-fvisibility=hidden" ]
}
config("machine") {
ldflags = []
if (current_cpu == "arm64") {
# The linker rewrites instructions to work around a CPU bug.
ldflags += [ "-Wl,--fix-cortex-a53-843419" ]
}
if (is_fuchsia) {
ldflags += [ "-Wl,-z,max-page-size=4096" ]
}
}
config("user") {
defines = [
"_ALL_SOURCE",
"ZIRCON_TOOLCHAIN",
]
public_deps = [
"$zx/system/ulib/c",
]
if (toolchain.environment == "user" && current_toolchain != toolchain.shlib) {
public_deps += [ "$zx/system/ulib/c:crt1" ]
}
}
config("integer-paranoia") {
cflags = [
"-fsanitize=integer-divide-by-zero,signed-integer-overflow",
"-fsanitize-undefined-trap-on-error",
]
}
config("static-libc++") {
ldflags = [ "-static-libstdc++" ]
if (current_os == "linux") {
# TODO(TC-74): The implicitly linked static libc++.a depends on these.
libs = [
"dl",
"pthread",
]
}
}