aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar John Millikin <jmillikin@stripe.com>2017-12-12 08:13:08 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-12-12 08:14:38 -0800
commit2aeaeba66857c561dd6d63c79a213f1cabc3650d (patch)
treeff65f89aa0d924e6c28ab22b9b07dcfc590c770a
parentd7f87aa4c3bbe1503d43b991551c2d1d156e52bb (diff)
When linking mostly-static Linux binaries, link libstdc++.a explicitly.
This allows libstdc++ to be statically linked, which is normally only possible when invoking GCC as `g++` with the `-static-libstdc++` flag. Fixes https://github.com/bazelbuild/bazel/issues/2840 See https://github.com/envoyproxy/envoy/issues/415 for additional background and context. cc @htuch (for Envoy) and @calpeyser @hlopko (who I talked to earlier about this) I'm only doing this in the Linux toolchain because MacOS doesn't do static linking of system libs anyway, and I don't know enough about Windows or FreeBSD to test on those platforms. Closes #4031. PiperOrigin-RevId: 178762357
-rw-r--r--src/test/shell/bazel/BUILD7
-rwxr-xr-xsrc/test/shell/bazel/cc_static_binary_test.sh89
-rwxr-xr-xsrc/test/shell/testenv.sh4
-rw-r--r--tools/cpp/CROSSTOOL.tpl1
-rw-r--r--tools/cpp/unix_cc_configure.bzl25
-rw-r--r--tools/cpp/windows_cc_configure.bzl1
6 files changed, 126 insertions, 1 deletions
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD
index 0f2ddd1fa9..d5a34b2b40 100644
--- a/src/test/shell/bazel/BUILD
+++ b/src/test/shell/bazel/BUILD
@@ -375,6 +375,13 @@ sh_test(
)
sh_test(
+ name = "cc_static_binary_test",
+ size = "medium",
+ srcs = ["cc_static_binary_test.sh"],
+ data = [":test-deps"],
+)
+
+sh_test(
name = "bazel_sandboxing_test",
size = "large",
srcs = ["bazel_sandboxing_test.sh"],
diff --git a/src/test/shell/bazel/cc_static_binary_test.sh b/src/test/shell/bazel/cc_static_binary_test.sh
new file mode 100755
index 0000000000..c120ecb3d0
--- /dev/null
+++ b/src/test/shell/bazel/cc_static_binary_test.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# Copyright 2017 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Tests for Bazel's static linking of C++ binaries.
+
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+source "${CURRENT_DIR}/../integration_test_setup.sh" \
+ || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
+
+if ! is_linux; then
+ echo "Tests for cc_binary static linking currently only run in Linux (this platform is ${PLATFORM})" >&2
+ exit 0
+fi
+
+function set_up() {
+ mkdir -p cpp/static
+ cat > cpp/static/main.cc <<EOF
+#include <iostream>
+int main() {
+ std::cout << "hello world!\n";
+ return 0;
+}
+EOF
+}
+
+function test_linux_somewhat_static_cc_binary() {
+ cat > cpp/static/BUILD <<EOF
+cc_binary(
+ name = "somewhat-static",
+ srcs = ["main.cc"],
+ linkstatic = 1,
+)
+EOF
+ assert_build //cpp/static:somewhat-static
+}
+
+function test_linux_mostly_static_cc_binary() {
+ cat > cpp/static/BUILD <<EOF
+cc_binary(
+ name = "mostly-static",
+ srcs = ["main.cc"],
+ linkstatic = 1,
+ linkopts = [
+ "-static-libstdc++",
+ "-static-libgcc",
+ ],
+)
+EOF
+ assert_build //cpp/static:mostly-static
+ LDD_STDOUT=$(ldd bazel-bin/cpp/static/mostly-static)
+ if [[ "${LDD_STDOUT}" =~ "libstdc++" ]]; then
+ log_fatal "A mostly-static binary shouldn't dynamically link libstdc++"
+ fi
+}
+
+function test_linux_fully_static_cc_binary() {
+ cat > cpp/static/BUILD <<EOF
+cc_binary(
+ name = "fully-static",
+ srcs = ["main.cc"],
+ linkstatic = 1,
+ linkopts = [
+ "-static",
+ "-static-libstdc++",
+ "-static-libgcc",
+ ],
+)
+EOF
+ assert_build //cpp/static:fully-static
+ LDD_STDOUT=$(ldd bazel-bin/cpp/static/fully-static || true)
+ if [[ ! "${LDD_STDOUT}" =~ "not a dynamic executable" ]]; then
+ log_fatal "Expected a fully-static binary"
+ fi
+}
+
+run_suite "static cc_binary"
diff --git a/src/test/shell/testenv.sh b/src/test/shell/testenv.sh
index fde278ee30..7594e5304f 100755
--- a/src/test/shell/testenv.sh
+++ b/src/test/shell/testenv.sh
@@ -30,6 +30,10 @@ function is_darwin() {
[[ "${PLATFORM}" =~ darwin ]]
}
+function is_linux() {
+ [[ "${PLATFORM}" =~ linux ]]
+}
+
function _log_base() {
prefix=$1
shift
diff --git a/tools/cpp/CROSSTOOL.tpl b/tools/cpp/CROSSTOOL.tpl
index e75e5e25dc..2b86bbb06e 100644
--- a/tools/cpp/CROSSTOOL.tpl
+++ b/tools/cpp/CROSSTOOL.tpl
@@ -129,6 +129,7 @@ toolchain {
%{opt_content}
}
linking_mode_flags { mode: DYNAMIC }
+%{link_content}
%{coverage}
diff --git a/tools/cpp/unix_cc_configure.bzl b/tools/cpp/unix_cc_configure.bzl
index 9814831db7..e7c099eeed 100644
--- a/tools/cpp/unix_cc_configure.bzl
+++ b/tools/cpp/unix_cc_configure.bzl
@@ -46,6 +46,29 @@ def _build_crosstool(d, prefix=" "):
return "\n".join(lines)
+def _build_link_content():
+ # `-static-libstdc++` is only supported when invoking GCC as `g++`, and
+ # `-lstdc++` forces dynamic linking of libstdc++. To get desired
+ # mostly-static behavior, invoke the link by explicitly naming a static
+ # library archive.
+ #
+ # https://github.com/bazelbuild/bazel/issues/2840
+ return """
+ linking_mode_flags {
+ mode: DYNAMIC
+ linker_flag: "-lstdc++"
+ }
+ linking_mode_flags {
+ mode: FULLY_STATIC
+ linker_flag: "-lstdc++"
+ }
+ linking_mode_flags {
+ mode: MOSTLY_STATIC
+ linker_flag: "-l:libstdc++.a"
+ }
+ """
+
+
def _build_tool_path(d):
"""Build the list of %-escaped tool_path for the CROSSTOOL file."""
lines = []
@@ -174,7 +197,6 @@ def _crosstool_content(repository_ctx, cc, cpu_value, darwin):
"-std=c++0x",
] + _escaped_cplus_include_paths(repository_ctx),
"linker_flag": [
- "-lstdc++",
"-lm", # Some systems expect -lm in addition to -lstdc++
# Anticipated future default.
] + (
@@ -385,6 +407,7 @@ def configure_unix_toolchain(repository_ctx, cpu_value):
_build_tool_path(tool_paths),
"%{opt_content}": _build_crosstool(opt_content, " "),
"%{dbg_content}": _build_crosstool(dbg_content, " "),
+ "%{link_content}": _build_link_content(),
"%{cxx_builtin_include_directory}": "",
"%{coverage}": _coverage_feature(darwin),
"%{msvc_env_tmp}": "",
diff --git a/tools/cpp/windows_cc_configure.bzl b/tools/cpp/windows_cc_configure.bzl
index 666592622e..7e2532b024 100644
--- a/tools/cpp/windows_cc_configure.bzl
+++ b/tools/cpp/windows_cc_configure.bzl
@@ -313,6 +313,7 @@ def configure_windows_toolchain(repository_ctx):
"%{content}": _get_escaped_windows_msys_crosstool_content(repository_ctx),
"%{opt_content}": "",
"%{dbg_content}": "",
+ "%{link_content}": "",
"%{cxx_builtin_include_directory}": "",
"%{coverage}": "",
})