skia2/gn/BUILD.gn
Brian Osman 50ea3c06b8 Add support for MSVC run-time checks (and control flow guard)
This enables four different options in the compiler, described
below. I also added enough masks to satisfy RTCc when running
all GMs in both 8888 and gl configs.

---

/RTCc - Detects when a value is assigned to a smaller data
type and results in data loss. This happens even when casting.
Masking is required to suppress this.

/RTCs - Various stack-related checks, including uninitialized
data (by initializing locals to a non-zero value), array bounds
checking, and stack pointer corruption that can occur with a
calling convention mismatch.

/RTCu - Reports when a variable is used without having been
initialized. Mostly redundant with compile-time checks.

/guard:cf - This is more of a security option, that computes
all possible targets for indirect calls at compile time, and
verifies that those are the only targets reached at compile
time. Also generates similar logic around switch statements
that turn into jump tables.

Bug: skia:
Change-Id: I7b527af8fd67dec0b6556f38bcd0efc3fd505856
Reviewed-on: https://skia-review.googlesource.com/c/188625
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
2019-02-04 20:55:24 +00:00

518 lines
13 KiB
Plaintext

# Copyright 2016 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
declare_args() {
extra_asmflags = []
extra_cflags = []
extra_cflags_c = []
extra_cflags_cc = []
extra_ldflags = []
malloc = ""
}
if (is_ios) {
if (is_tvos) {
sdk = "appletvos"
if (target_cpu == "x86" || target_cpu == "x64") {
sdk = "appletvsimulator"
}
} else {
sdk = "iphoneos"
if (target_cpu == "x86" || target_cpu == "x64") {
sdk = "iphonesimulator"
}
}
ios_sysroot = exec_script("find_ios_sysroot.py", [ sdk ], "trim string")
}
config("default") {
asmflags = []
cflags = []
cflags_c = []
cflags_cc = []
defines = []
ldflags = []
libs = []
if (is_win) {
cflags += [
"/bigobj", # Some of our files are bigger than the regular limits.
"/WX", # Treat warnings as errors.
"/utf-8", # Set Source and Executable character sets to UTF-8.
]
if (is_clang) {
cflags += [ "-fms-compatibility-version=19" ] # 2015
}
defines += [
"_CRT_SECURE_NO_WARNINGS", # Disables warnings about sscanf().
"_HAS_EXCEPTIONS=0", # Disables exceptions in MSVC STL.
"WIN32_LEAN_AND_MEAN",
"NOMINMAX",
]
if (msvc == 2015) {
_include_dirs = [ "$win_vc/include" ]
} else { # 2017
_include_dirs = [ "$win_vc/Tools/MSVC/$win_toolchain_version/include" ]
}
_include_dirs += [
"$win_sdk/Include/$win_sdk_version/shared",
"$win_sdk/Include/$win_sdk_version/ucrt",
"$win_sdk/Include/$win_sdk_version/um",
"$win_sdk/Include/$win_sdk_version/winrt",
]
if (is_clang) {
foreach(dir, _include_dirs) {
cflags += [
"-imsvc",
dir,
]
}
} else {
include_dirs = _include_dirs
}
lib_dirs = [
"$win_sdk/Lib/$win_sdk_version/ucrt/$target_cpu",
"$win_sdk/Lib/$win_sdk_version/um/$target_cpu",
]
if (msvc == 2015) {
if (target_cpu == "x86") {
lib_dirs += [ "$win_vc/lib" ]
} else {
lib_dirs += [ "$win_vc/lib/amd64" ]
}
} else { # 2017
lib_dirs +=
[ "$win_vc/Tools/MSVC/$win_toolchain_version/lib/$target_cpu" ]
}
} else {
cflags += [
"-fstrict-aliasing",
"-fPIC",
]
cflags_cc += [ "-std=c++14" ]
# The main idea is to slim the exported API, but these flags also improve link time on Mac.
# These would make stack traces worse on Linux, so we don't just set them willy-nilly.
if (is_component_build || is_ios || is_mac) {
cflags += [ "-fvisibility=hidden" ]
cflags_cc += [ "-fvisibility-inlines-hidden" ]
}
}
if (current_cpu == "arm") {
cflags += [
"-march=armv7-a",
"-mfpu=neon",
"-mthumb",
]
} else if (current_cpu == "loongson3a") {
asmflags += [ "-march=loongson3a" ]
cflags += [
"-march=loongson3a",
# Causes an internal compiler error.
"-DSKCMS_PORTABLE",
]
} else if (current_cpu == "mips64el") {
asmflags += [ "-march=mips64" ]
cflags += [ "-march=mips64" ]
} else if (current_cpu == "x86" && !is_win) {
asmflags += [ "-m32" ]
cflags += [
"-m32",
"-msse2",
"-mfpmath=sse",
]
ldflags += [ "-m32" ]
}
if (malloc != "" && !is_win) {
cflags += [
"-fno-builtin-malloc",
"-fno-builtin-calloc",
"-fno-builtin-realloc",
"-fno-builtin-free",
]
libs += [ malloc ]
}
if (is_android) {
asmflags += [ "--target=$ndk_target" ]
cflags += [
"--sysroot=$ndk/sysroot",
"-isystem$ndk/sysroot/usr/include/$ndk_target",
"-D__ANDROID_API__=$ndk_api",
"--target=$ndk_target",
]
cflags_cc += [
"-isystem$ndk/sources/cxx-stl/llvm-libc++/include",
"-isystem$ndk/sources/cxx-stl/llvm-libc++abi/include",
"-isystem$ndk/sources/android/support/include",
]
ldflags += [
"--sysroot=$ndk/platforms/$ndk_platform",
"--target=$ndk_target",
"-B$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/$ndk_target/bin",
]
lib_dirs = [
"$ndk/sources/cxx-stl/llvm-libc++/libs/$ndk_stdlib",
"$ndk/toolchains/$ndk_gccdir-4.9/prebuilt/$ndk_host/lib/gcc/$ndk_target/4.9.x",
]
libs += [
"c++_static",
"c++abi",
]
if (ndk_api < 21) {
libs += [ "android_support" ]
}
}
if (is_ios) {
_target = target_cpu
if (target_cpu == "arm") {
_target = "armv7"
} else if (target_cpu == "x86") {
_target = "i386"
} else if (target_cpu == "x64") {
_target = "x86_64"
}
asmflags += [
"-isysroot",
ios_sysroot,
"-arch",
_target,
]
cflags += [
"-isysroot",
ios_sysroot,
"-arch",
_target,
]
cflags_cc += [ "-stdlib=libc++" ]
ldflags += [
"-isysroot",
ios_sysroot,
"-arch",
_target,
"-stdlib=libc++",
]
libs += [ "objc" ]
}
if (is_linux) {
libs += [ "pthread" ]
if (is_debug && sanitize == "") {
defines += [ "_GLIBCXX_DEBUG" ]
}
}
if (is_mac) {
# Disable linker warnings. They're usually just annoyances like,
# ld: warning: text-based stub file
# /System/Library/Frameworks/foo.framework/foo.tbd and library file
# /System/Library/Frameworks/foo.framework/foo are out of sync.
# Falling back to library file for linking.
ldflags += [ "-Wl,-w" ]
}
if (sanitize != "" && sanitize != "MSVC") {
# You can either pass the sanitizers directly, e.g. "address,undefined",
# or pass one of the couple common aliases used by the bots.
sanitizers = sanitize
if (sanitize == "ASAN" || sanitize == "UBSAN") {
# ASAN implicitly runs all UBSAN checks also.
sanitizers = "undefined"
if (sanitize == "ASAN") {
sanitizers += ",address"
}
if (is_android) {
# TODO(mtklein): work out UBSAN link errors
sanitizers = "address"
}
} else if (sanitize == "TSAN") {
sanitizers = "thread"
} else if (sanitize == "MSAN") {
sanitizers = "memory"
}
_blacklist = rebase_path("../tools/xsan.blacklist")
cflags += [
"-fsanitize=$sanitizers",
"-fno-sanitize-recover=$sanitizers",
"-fsanitize-blacklist=$_blacklist",
]
ldflags += [ "-fsanitize=$sanitizers" ]
if (is_win) {
cflags += [ "/FI$_blacklist" ]
} else {
cflags += [
"-include$_blacklist",
"-fno-omit-frame-pointer",
]
}
if (is_linux) {
cflags_cc += [ "-stdlib=libc++" ]
ldflags += [ "-stdlib=libc++" ]
}
if (sanitizers == "memory") {
cflags += [ "-fsanitize-memory-track-origins" ]
}
}
}
config("no_exceptions") {
# Exceptions are disabled by default on Windows. (Use /EHsc to enable them.)
if (!is_win) {
cflags_cc = [ "-fno-exceptions" ]
}
}
config("warnings") {
cflags = []
cflags_cc = []
cflags_objc = []
cflags_objcc = []
if (is_win) {
cflags += [
"/W3", # Turn on lots of warnings.
# Disable a bunch of warnings:
"/wd4244", # conversion from 'float' to 'int', possible loss of data
"/wd4267", # conversion from 'size_t' to 'int', possible loss of data
"/wd4800", # forcing value to bool 'true' or 'false' (performance warning)
# Probably only triggers when /EHsc is enabled.
"/wd4291", # no matching operator delete found;
# memory will not be freed if initialization throws an exception
]
} else {
cflags += [
"-Werror",
"-Wall",
"-Wextra",
"-Winit-self",
"-Wpointer-arith",
"-Wsign-compare",
"-Wvla",
"-Wno-deprecated-declarations",
"-Wno-maybe-uninitialized",
]
cflags_cc += [
"-Wnon-virtual-dtor",
"-Wno-noexcept-type",
]
}
if (is_clang) {
cflags += [
"-Weverything",
"-Wno-unknown-warning-option", # Let older Clangs ignore newer Clangs' warnings.
]
if (target_cpu == "arm" && is_ios) {
# Clang seems to think new/malloc will only be 4-byte aligned on 32-bit iOS.
# We're pretty sure it's actually 8-byte alignment.
cflags += [ "-Wno-over-aligned" ]
}
if (target_cpu == "x86" && is_android) {
# Clang seems to think new/malloc will only be 4-byte aligned on 32-bit x86 Android builds.
# We're pretty sure it's actually 8-byte alignment. See OverAlignedTest.cpp for more info.
cflags += [ "-Wno-over-aligned" ]
}
# Shouldn't be necessary for local builds. With distributed Windows builds, files may lose
# their case during copy, causing case-sensitivity mismatch on remote machines.
cflags += [
"-Wno-nonportable-include-path",
"-Wno-nonportable-system-include-path",
]
# TODO: These would all be really great warnings to turn on.
cflags += [
"-Wno-cast-align",
"-Wno-cast-qual",
"-Wno-conversion",
"-Wno-disabled-macro-expansion",
"-Wno-documentation",
"-Wno-documentation-unknown-command",
"-Wno-double-promotion",
"-Wno-exit-time-destructors", # TODO: OK outside libskia
"-Wno-float-equal",
"-Wno-format-nonliteral",
"-Wno-global-constructors", # TODO: OK outside libskia
"-Wno-missing-prototypes",
"-Wno-missing-variable-declarations",
"-Wno-pedantic",
"-Wno-reserved-id-macro",
"-Wno-shadow",
"-Wno-shift-sign-overflow",
"-Wno-signed-enum-bitfield",
"-Wno-switch-enum",
"-Wno-undef",
"-Wno-unreachable-code",
"-Wno-unreachable-code-break",
"-Wno-unreachable-code-return",
"-Wno-unused-macros",
"-Wno-unused-member-function",
"-Wno-unused-template",
"-Wno-zero-as-null-pointer-constant",
]
cflags_cc += [
"-Wno-abstract-vbase-init",
"-Wno-weak-vtables",
]
# We are unlikely to want to fix these.
cflags += [
"-Wno-bad-function-cast",
"-Wno-covered-switch-default",
"-Wno-deprecated",
"-Wno-missing-noreturn",
"-Wno-old-style-cast",
"-Wno-padded",
"-Wno-newline-eof",
]
cflags_cc += [
"-Wno-c++98-compat",
"-Wno-c++98-compat-pedantic",
"-Wno-undefined-func-template",
]
cflags_objc += [
"-Wno-direct-ivar-access",
"-Wno-objc-interface-ivars",
]
cflags_objcc += [
"-Wno-direct-ivar-access",
"-Wno-objcc-interface-ivars",
]
}
if (!is_win || is_clang) {
cflags += [ "-Wno-implicit-fallthrough" ]
}
}
config("warnings_except_public_headers") {
if (!is_win || is_clang) {
cflags = [ "-Wno-unused-parameter" ]
}
}
config("extra_flags") {
asmflags = extra_asmflags
cflags = extra_cflags
cflags_c = extra_cflags_c
cflags_cc = extra_cflags_cc
ldflags = extra_ldflags
}
config("debug_symbols") {
# It's annoying to wait for full debug symbols to push over
# to Android devices. -gline-tables-only is a lot slimmer.
if (is_android) {
cflags = [
"-gline-tables-only",
"-funwind-tables", # Helps make in-process backtraces fuller.
]
} else if (is_win) {
cflags = [ "/Z7" ]
if (is_clang) {
cflags += [
"-mllvm",
"-emit-codeview-ghash-section",
]
ldflags = [ "/DEBUG:GHASH" ]
} else {
ldflags = [ "/DEBUG:FASTLINK" ]
}
} else {
cflags = [ "-g" ]
}
}
config("no_rtti") {
if (sanitize != "ASAN") { # -fsanitize=vptr requires RTTI
if (is_win) {
cflags_cc = [ "/GR-" ]
} else {
cflags_cc = [ "-fno-rtti" ]
}
}
}
config("optimize") {
if (is_win) {
cflags = [
"/O2",
"/Zc:inline",
]
ldflags = [
"/OPT:ICF",
"/OPT:REF",
]
} else {
cflags = [
"-O3",
"-fdata-sections",
"-ffunction-sections",
]
if (is_mac || is_ios) {
ldflags = [ "-dead_strip" ]
} else {
ldflags = [ "-Wl,--gc-sections" ]
}
if (target_cpu == "wasm") {
# The compiler asks us to add an optimization flag to both cflags
# and ldflags to cut down on the local variables,
# for performance reasons.
# The "linking" step is the conversion to javascript.
ldflags += [ "-O3" ]
}
}
}
config("NDEBUG") {
defines = [ "NDEBUG" ]
}
config("msvc_rtc") {
defines = [ "_ALLOW_RTCc_IN_STL" ]
cflags = [
"/RTCcsu",
"/guard:cf",
]
ldflags = [ "/guard:cf" ]
}
config("executable") {
if (is_android) {
ldflags = [
"-pie",
"-rdynamic",
]
} else if (is_mac) {
ldflags = [ "-Wl,-rpath,@loader_path/." ]
} else if (is_linux) {
ldflags = [
"-rdynamic",
"-Wl,-rpath,\$ORIGIN",
]
} else if (is_win) {
ldflags = [
"/SUBSYSTEM:CONSOLE", # Quiet "no subsystem specified; CONSOLE assumed".
"/INCREMENTAL:NO", # Quiet warnings about failing to incrementally link by never trying to.
]
}
}