From 56d5bd07067aa64cd5559c939bd54b36b1f5bb47 Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Wed, 19 Jun 2019 21:43:38 +0000 Subject: [PATCH 1/7] build: simplify cc_configure Signed-off-by: Lizan Zhou --- bazel/cc_configure.bzl | 52 +---------------------------------- bazel/cc_wrapper.py | 26 ++++++++++-------- bazel/envoy_internal.bzl | 4 +-- test/exe/envoy_static_test.sh | 4 +-- 4 files changed, 18 insertions(+), 68 deletions(-) diff --git a/bazel/cc_configure.bzl b/bazel/cc_configure.bzl index 9122735d9a2d..30275140b917 100644 --- a/bazel/cc_configure.bzl +++ b/bazel/cc_configure.bzl @@ -2,57 +2,8 @@ load("@bazel_tools//tools/cpp:cc_configure.bzl", _upstream_cc_autoconf_impl = "c load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value") load("@bazel_tools//tools/cpp:unix_cc_configure.bzl", "find_cc") -# Stub for `repository_ctx.which()` that always succeeds. See comments in -# `_find_cxx` for details. -def _quiet_fake_which(program): - return struct(_envoy_fake_which = program) - -# Stub for `repository_ctx.which()` that always fails. See comments in -# `_find_cxx` for details. -def _noisy_fake_which(program): - return None - -# Find a good path for the C++ compiler, by hooking into Bazel's C compiler -# detection. Uses `$CXX` if found, otherwise defaults to `g++` because Bazel -# defaults to `gcc`. -def _find_cxx(repository_ctx): - # Bazel's `find_cc` helper uses the repository context to inspect `$CC`. - # Replace this value with `$CXX` if set. - environ_cxx = repository_ctx.os.environ.get("CXX", "g++") - fake_os = struct( - environ = {"CC": environ_cxx}, - ) - - # We can't directly assign `repository_ctx.which` to a struct attribute - # because Skylark doesn't support bound method references. Instead, stub - # out `which()` using a two-pass approach: - # - # * The first pass uses a stub that always succeeds, passing back a special - # value containing the original parameter. - # * If we detect the special value, we know that `find_cc` found a compiler - # name but don't know if that name could be resolved to an executable path. - # So do the `which()` call ourselves. - # * If our `which()` failed, call `find_cc` again with a dummy which that - # always fails. The error raised by `find_cc` will be identical to what Bazel - # would generate for a missing C compiler. - # - # See https://github.com/bazelbuild/bazel/issues/4644 for more context. - real_cxx = find_cc(struct( - which = _quiet_fake_which, - os = fake_os, - ), {}) - if hasattr(real_cxx, "_envoy_fake_which"): - real_cxx = repository_ctx.which(real_cxx._envoy_fake_which) - if real_cxx == None: - find_cc(struct( - which = _noisy_fake_which, - os = fake_os, - ), {}) - return real_cxx - def _build_envoy_cc_wrapper(repository_ctx): real_cc = find_cc(repository_ctx, {}) - real_cxx = _find_cxx(repository_ctx) # Copy our CC wrapper script into @local_config_cc, with the true paths # to the C and C++ compiler injected in. The wrapper will use these paths @@ -64,7 +15,6 @@ def _build_envoy_cc_wrapper(repository_ctx): repository_ctx.template("extra_tools/envoy_cc_wrapper", repository_ctx.attr._envoy_cc_wrapper, { "{ENVOY_REAL_CC}": repr(str(real_cc)), "{ENVOY_CFLAGS}": repr(str(repository_ctx.os.environ.get("CFLAGS", ""))), - "{ENVOY_REAL_CXX}": repr(str(real_cxx)), "{ENVOY_CXXFLAGS}": repr(str(repository_ctx.os.environ.get("CXXFLAGS", ""))), }) return repository_ctx.path("extra_tools/envoy_cc_wrapper") @@ -93,6 +43,7 @@ cc_autoconf = repository_rule( "ABI_VERSION", "BAZEL_COMPILER", "BAZEL_HOST_SYSTEM", + "BAZEL_CXXOPTS", "BAZEL_LINKOPTS", "BAZEL_PYTHON", "BAZEL_SH", @@ -108,7 +59,6 @@ cc_autoconf = repository_rule( "USE_CLANG_CL", "CC", "CFLAGS", - "CXX", "CXXFLAGS", "CC_CONFIGURE_DEBUG", "CC_TOOLCHAIN_NAME", diff --git a/bazel/cc_wrapper.py b/bazel/cc_wrapper.py index c4883edd065d..0dda9b1f5af8 100755 --- a/bazel/cc_wrapper.py +++ b/bazel/cc_wrapper.py @@ -5,8 +5,7 @@ import sys import tempfile -envoy_real_cc = {ENVOY_REAL_CC} -envoy_real_cxx = {ENVOY_REAL_CXX} +compiler = {ENVOY_REAL_CC} envoy_cflags = {ENVOY_CFLAGS} envoy_cxxflags = {ENVOY_CXXFLAGS} @@ -37,11 +36,9 @@ def is_cpp_flag(arg): def modify_driver_args(input_driver_flags): # Detect if we're building for C++ or vanilla C. if any(map(is_cpp_flag, input_driver_flags)): - compiler = envoy_real_cxx # Append CXXFLAGS to all C++ targets (this is mostly for dependencies). argv = shlex.split(envoy_cxxflags) else: - compiler = envoy_real_cc # Append CFLAGS to all C targets (this is mostly for dependencies). argv = shlex.split(envoy_cflags) @@ -50,9 +47,8 @@ def modify_driver_args(input_driver_flags): # b) replace all occurrences of -lstdc++ with -lc++ (when linking against libc++). if "-static-libstdc++" in input_driver_flags or "-stdlib=libc++" in envoy_cxxflags: for arg in input_driver_flags: - if arg == "-lstdc++": - if "-stdlib=libc++" in envoy_cxxflags: - argv.append("-lc++") + if arg in ("-lstdc++", "-static-libstdc++"): + pass elif arg.startswith("-Wl,@"): # tempfile.mkstemp will write to the out-of-sandbox tempdir # unless the user has explicitly set environment variables @@ -67,6 +63,14 @@ def modify_driver_args(input_driver_flags): else: argv += input_driver_flags + # This flags should after all libraries + if "-lstdc++" in input_driver_flags: + if "-stdlib=libc++" in envoy_cxxflags: + argv.append("-l:libc++.a") + argv.append("-l:libc++abi.a") + else: + argv.append("-l:libstdc++.a") + # Bazel will add -fuse-ld=gold in some cases, gcc/clang will take the last -fuse-ld argument, # so whenever we see lld once, add it to the end. if "-fuse-ld=lld" in argv: @@ -87,13 +91,13 @@ def modify_driver_args(input_driver_flags): # See https://github.com/envoyproxy/envoy/issues/2987 argv.append("-Wno-maybe-uninitialized") - return compiler, argv + return argv def main(): # Append CXXFLAGS to correctly detect include paths for either libstdc++ or libc++. if sys.argv[1:5] == ["-E", "-xc++", "-", "-v"]: - os.execv(envoy_real_cxx, [envoy_real_cxx] + sys.argv[1:] + shlex.split(envoy_cxxflags)) + os.execv(compiler, [compiler] + sys.argv[1:] + shlex.split(envoy_cxxflags)) if sys.argv[1].startswith("@"): # Read flags from file @@ -102,7 +106,7 @@ def main(): input_driver_flags = fd.read().splitlines() # Compute new args - compiler, new_driver_args = modify_driver_args(input_driver_flags) + new_driver_args = modify_driver_args(input_driver_flags) # Write args to temp file (new_flagfile_fd, new_flagfile_path) = tempfile.mkstemp(dir="./", suffix=".linker-params") @@ -116,7 +120,7 @@ def main(): else: # TODO(https://github.com/bazelbuild/bazel/issues/7687): Remove this branch # when Bazel 0.27 is released. - compiler, new_args = modify_driver_args(sys.argv[1:]) + new_args = modify_driver_args(sys.argv[1:]) os.execv(compiler, [compiler] + new_args) diff --git a/bazel/envoy_internal.bzl b/bazel/envoy_internal.bzl index b716c0f7b348..02a48ca7ba8e 100644 --- a/bazel/envoy_internal.bzl +++ b/bazel/envoy_internal.bzl @@ -77,9 +77,7 @@ def envoy_select_force_libcpp(if_libcpp, default = None): def envoy_static_link_libstdcpp_linkopts(): return envoy_select_force_libcpp( - # TODO(PiotrSikora): statically link libc++ once that's possible. - # See: https://reviews.llvm.org/D53238 - ["-stdlib=libc++"], + ["-stdlib=libc++", "-l:libc++.a", "-l:libc++abi.a", "-static-libgcc"], ["-static-libstdc++", "-static-libgcc"], ) diff --git a/test/exe/envoy_static_test.sh b/test/exe/envoy_static_test.sh index 8324aeca736e..17832c183efd 100755 --- a/test/exe/envoy_static_test.sh +++ b/test/exe/envoy_static_test.sh @@ -17,9 +17,7 @@ fi if [[ ${DYNLIBS} =~ "libc++" ]]; then echo "libc++ is dynamically linked:" echo "${DYNLIBS}" - # TODO(PiotrSikora): enforce this once there is a way to statically link libc++. - # See: https://reviews.llvm.org/D53238 - exit 0 + exit 1 fi if [[ ${DYNLIBS} =~ "libstdc++" || ${DYNLIBS} =~ "libgcc" ]]; then From 76bbfa9ce373dfc76bff8581bca2e8da82fdefe9 Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Wed, 19 Jun 2019 22:52:47 +0000 Subject: [PATCH 2/7] fix Signed-off-by: Lizan Zhou --- bazel/envoy_internal.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazel/envoy_internal.bzl b/bazel/envoy_internal.bzl index 02a48ca7ba8e..8ae4b3cb4efd 100644 --- a/bazel/envoy_internal.bzl +++ b/bazel/envoy_internal.bzl @@ -78,7 +78,7 @@ def envoy_select_force_libcpp(if_libcpp, default = None): def envoy_static_link_libstdcpp_linkopts(): return envoy_select_force_libcpp( ["-stdlib=libc++", "-l:libc++.a", "-l:libc++abi.a", "-static-libgcc"], - ["-static-libstdc++", "-static-libgcc"], + ["-l:libstdc++.a", "-static-libgcc"], ) # Dependencies on tcmalloc_and_profiler should be wrapped with this function. From f4c1fc25e4f48e99a5e58b813ff58f29db527feb Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Thu, 20 Jun 2019 04:51:19 +0000 Subject: [PATCH 3/7] fix asan and more Signed-off-by: Lizan Zhou --- bazel/cc_wrapper.py | 4 ++-- bazel/foreign_cc/BUILD | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bazel/cc_wrapper.py b/bazel/cc_wrapper.py index 0dda9b1f5af8..7a0ed1d8a43a 100755 --- a/bazel/cc_wrapper.py +++ b/bazel/cc_wrapper.py @@ -24,7 +24,7 @@ def sanitize_flagfile(in_path, out_fd): if line != "-lstdc++\n": os.write(out_fd, line) elif "-stdlib=libc++" in envoy_cxxflags: - os.write(out_fd, "-lc++\n") + os.write(out_fd, "-l:libc++.a\n-l:libc++abi.a\n") # Is the arg a flag indicating that we're building for C++ (rather than C)? @@ -45,7 +45,7 @@ def modify_driver_args(input_driver_flags): # Either: # a) remove all occurrences of -lstdc++ (when statically linking against libstdc++), # b) replace all occurrences of -lstdc++ with -lc++ (when linking against libc++). - if "-static-libstdc++" in input_driver_flags or "-stdlib=libc++" in envoy_cxxflags: + if "-l:libstdc++.a" in input_driver_flags or "-stdlib=libc++" in envoy_cxxflags: for arg in input_driver_flags: if arg in ("-lstdc++", "-static-libstdc++"): pass diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 8b0b98ef0a43..2de9e4390bac 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -118,6 +118,7 @@ envoy_cmake_external( "ENABLE_LIB_ONLY": "on", "CMAKE_BUILD_TYPE": "RelWithDebInfo", "CMAKE_INSTALL_LIBDIR": "lib", + "CMAKE_CXX_COMPILER_FORCED": "on", # Disable ranlib because it is not handled by bazel, and therefore # doesn't respect custom toolchains such as the Android NDK, # see https://github.com/bazelbuild/rules_foreign_cc/issues/252 @@ -140,6 +141,7 @@ envoy_cmake_external( "YAML_CPP_BUILD_TESTS": "off", "YAML_CPP_BUILD_TOOLS": "off", "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_CXX_COMPILER_FORCED": "on", # Disable ranlib because it is not handled by bazel, and therefore # doesn't respect custom toolchains such as the Android NDK, # see https://github.com/bazelbuild/rules_foreign_cc/issues/252 From 9f0eec5a996f8fc61f370d2a51b8535c9c8708dc Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Thu, 20 Jun 2019 05:20:46 +0000 Subject: [PATCH 4/7] fix Signed-off-by: Lizan Zhou --- .bazelrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.bazelrc b/.bazelrc index d0cd3e3f007a..b38f536435b0 100644 --- a/.bazelrc +++ b/.bazelrc @@ -59,6 +59,7 @@ build:libc++ --action_env=CC build:libc++ --action_env=CXX build:libc++ --action_env=CXXFLAGS=-stdlib=libc++ build:libc++ --action_env=PATH +build:libc++ --host_linkopt=-fuse-ld=lld build:libc++ --define force_libcpp=enabled # Optimize build for binary size reduction. From 900b80874b0c331c6d9b092b46e6588e9802e049 Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Thu, 20 Jun 2019 06:47:21 +0000 Subject: [PATCH 5/7] tsan fix Signed-off-by: Lizan Zhou --- .bazelrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.bazelrc b/.bazelrc index b38f536435b0..d58c3ff8b3f9 100644 --- a/.bazelrc +++ b/.bazelrc @@ -40,6 +40,7 @@ build:clang-tsan --define ENVOY_CONFIG_TSAN=1 build:clang-tsan --copt -fsanitize=thread build:clang-tsan --linkopt -fsanitize=thread build:clang-tsan --linkopt -fuse-ld=lld +build:clang-tsan --linkopt -static-libsan build:clang-tsan --define tcmalloc=disabled # Needed due to https://github.com/libevent/libevent/issues/777 build:clang-tsan --copt -DEVENT__DISABLE_DEBUG_MODE From dae720b5899cbec215c52f389294547dabc49793 Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Thu, 20 Jun 2019 08:18:13 +0000 Subject: [PATCH 6/7] retrofit bazel 0.26 Signed-off-by: Lizan Zhou --- bazel/cc_wrapper.py | 13 ++++++------- bazel/envoy_internal.bzl | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bazel/cc_wrapper.py b/bazel/cc_wrapper.py index 7a0ed1d8a43a..53037e67bd2e 100755 --- a/bazel/cc_wrapper.py +++ b/bazel/cc_wrapper.py @@ -45,7 +45,7 @@ def modify_driver_args(input_driver_flags): # Either: # a) remove all occurrences of -lstdc++ (when statically linking against libstdc++), # b) replace all occurrences of -lstdc++ with -lc++ (when linking against libc++). - if "-l:libstdc++.a" in input_driver_flags or "-stdlib=libc++" in envoy_cxxflags: + if "-static-libstdc++" in input_driver_flags or "-stdlib=libc++" in envoy_cxxflags: for arg in input_driver_flags: if arg in ("-lstdc++", "-static-libstdc++"): pass @@ -64,12 +64,11 @@ def modify_driver_args(input_driver_flags): argv += input_driver_flags # This flags should after all libraries - if "-lstdc++" in input_driver_flags: - if "-stdlib=libc++" in envoy_cxxflags: - argv.append("-l:libc++.a") - argv.append("-l:libc++abi.a") - else: - argv.append("-l:libstdc++.a") + if "-static-libstdc++" in input_driver_flags: + argv.append("-l:libstdc++.a") + if "-lstdc++" in input_driver_flags and "-stdlib=libc++" in envoy_cxxflags: + argv.append("-l:libc++.a") + argv.append("-l:libc++abi.a") # Bazel will add -fuse-ld=gold in some cases, gcc/clang will take the last -fuse-ld argument, # so whenever we see lld once, add it to the end. diff --git a/bazel/envoy_internal.bzl b/bazel/envoy_internal.bzl index 8ae4b3cb4efd..02a48ca7ba8e 100644 --- a/bazel/envoy_internal.bzl +++ b/bazel/envoy_internal.bzl @@ -78,7 +78,7 @@ def envoy_select_force_libcpp(if_libcpp, default = None): def envoy_static_link_libstdcpp_linkopts(): return envoy_select_force_libcpp( ["-stdlib=libc++", "-l:libc++.a", "-l:libc++abi.a", "-static-libgcc"], - ["-l:libstdc++.a", "-static-libgcc"], + ["-static-libstdc++", "-static-libgcc"], ) # Dependencies on tcmalloc_and_profiler should be wrapped with this function. From 30a0b42b17dfc7cd8e4fff9fc8f954a55baa2346 Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Wed, 10 Jul 2019 19:37:17 +0000 Subject: [PATCH 7/7] c++fs doesn't have to be explicitly in linkopts Signed-off-by: Lizan Zhou --- bazel/envoy_test.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazel/envoy_test.bzl b/bazel/envoy_test.bzl index 5e93e1585871..ea564d619fa8 100644 --- a/bazel/envoy_test.bzl +++ b/bazel/envoy_test.bzl @@ -60,7 +60,7 @@ def _envoy_test_linkopts(): # TODO(mattklein123): It's not great that we universally link against the following libs. # In particular, -latomic and -lrt are not needed on all platforms. Make this more granular. "//conditions:default": ["-pthread", "-lrt", "-ldl"], - }) + envoy_select_force_libcpp(["-lc++fs"], ["-lstdc++fs", "-latomic"]) + }) + envoy_select_force_libcpp([], ["-lstdc++fs", "-latomic"]) # Envoy C++ fuzz test targets. These are not included in coverage runs. def envoy_cc_fuzz_test(name, corpus, deps = [], tags = [], **kwargs):