Skip to content

Commit

Permalink
When linking mostly-static Linux binaries, link libstdc++.a explicitly.
Browse files Browse the repository at this point in the history
This allows libstdc++ to be statically linked, which is normally only
possible when invoking GCC as `g++` with the `-static-libstdc++` flag.

Fixes #2840

See envoyproxy/envoy#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
  • Loading branch information
jmillikin-stripe authored and Copybara-Service committed Dec 12, 2017
1 parent d7f87aa commit 2aeaeba
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/test/shell/bazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,13 @@ sh_test(
data = [":test-deps"],
)

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",
Expand Down
89 changes: 89 additions & 0 deletions src/test/shell/bazel/cc_static_binary_test.sh
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 4 additions & 0 deletions src/test/shell/testenv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ function is_darwin() {
[[ "${PLATFORM}" =~ darwin ]]
}

function is_linux() {
[[ "${PLATFORM}" =~ linux ]]
}

function _log_base() {
prefix=$1
shift
Expand Down
1 change: 1 addition & 0 deletions tools/cpp/CROSSTOOL.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ toolchain {
%{opt_content}
}
linking_mode_flags { mode: DYNAMIC }
%{link_content}

%{coverage}

Expand Down
25 changes: 24 additions & 1 deletion tools/cpp/unix_cc_configure.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down Expand Up @@ -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.
] + (
Expand Down Expand Up @@ -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}": "",
Expand Down
1 change: 1 addition & 0 deletions tools/cpp/windows_cc_configure.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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}": "",
})
Expand Down

0 comments on commit 2aeaeba

Please sign in to comment.