Skip to content

Commit

Permalink
Replace Envoy's custom unix_cc_configure with a wrapper script.
Browse files Browse the repository at this point in the history
The script checks for `--static-libstdc++` in argv, and if found
(1) switches to the `$CXX` compiler and (2) drops `-lstdc++` from argv.

This should let the main Envoy binary build normally, without
interfering with other build systems that treat C and C++ as different
languages.

Signed-off-by: John Millikin <jmillikin@stripe.com>
  • Loading branch information
jmillikin-stripe committed Feb 17, 2018
1 parent 0ab49ee commit 8ea835f
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 576 deletions.
85 changes: 38 additions & 47 deletions bazel/cc_configure.bzl
Original file line number Diff line number Diff line change
@@ -1,56 +1,48 @@
# This file was imported from https://github.com/bazelbuild/bazel at 3d00b2a. We apply a number of
# local modifications to deal with known issues in Bazel 0.10.0.
#
# * https://github.com/bazelbuild/bazel/issues/2840
# * (and potentially) https://github.com/bazelbuild/bazel/issues/2805
#
# See cc_configure.bzl.diff for the changes made in this fork.
load("@bazel_tools//tools/cpp:cc_configure.bzl", _upstream_cc_autoconf_impl = "cc_autoconf_impl")
load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value")
load("@bazel_tools//tools/cpp:unix_cc_configure.bzl", "find_cc")

# Copyright 2016 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.
"""Rules for configuring the C++ toolchain (experimental)."""
def _quiet_fake_which(program):
return struct(_envoy_fake_which = program)

def _noisy_fake_which(program):
return None

load("@bazel_tools//tools/cpp:windows_cc_configure.bzl", "configure_windows_toolchain")
load("@bazel_tools//tools/cpp:osx_cc_configure.bzl", "configure_osx_toolchain")
load("//bazel:unix_cc_configure.bzl", "configure_unix_toolchain")
load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value")
def _build_envoy_cc_wrapper(repository_ctx):
real_cc = find_cc(repository_ctx, {})
environ_cxx = repository_ctx.os.environ.get("CXX", "g++")
fake_os = struct(
environ = {"CC": environ_cxx},
)
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,
), {})
repository_ctx.template("envoy_cc_wrapper", repository_ctx.attr._envoy_cc_wrapper, {
"{ENVOY_REAL_CC}": repr(str(real_cc)),
"{ENVOY_REAL_CXX}": repr(str(real_cxx)),
})
return repository_ctx.path("envoy_cc_wrapper")

def cc_autoconf_impl(repository_ctx, overriden_tools = dict()):
repository_ctx.symlink(
Label("@bazel_tools//tools/cpp:dummy_toolchain.bzl"), "dummy_toolchain.bzl")
env = repository_ctx.os.environ
def cc_autoconf_impl(repository_ctx):
cpu_value = get_cpu_value(repository_ctx)
if cpu_value == "freebsd":
# This is defaulting to the static crosstool, we should eventually
# autoconfigure this platform too. Theorically, FreeBSD should be
# straightforward to add but we cannot run it in a docker container so
# skipping until we have proper tests for FreeBSD.
repository_ctx.symlink(Label("@bazel_tools//tools/cpp:CROSSTOOL"), "CROSSTOOL")
repository_ctx.symlink(Label("@bazel_tools//tools/cpp:BUILD.static"), "BUILD")
elif cpu_value == "x64_windows":
# TODO(ibiryukov): overriden_tools are only supported in configure_unix_toolchain.
# We might want to add that to Windows too(at least for msys toolchain).
configure_windows_toolchain(repository_ctx)
elif (cpu_value == "darwin" and
("BAZEL_USE_CPP_ONLY_TOOLCHAIN" not in env or env["BAZEL_USE_CPP_ONLY_TOOLCHAIN"] != "1")):
configure_osx_toolchain(repository_ctx, overriden_tools)
else:
configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools)
overriden_tools = {}
if cpu_value not in ["freebsd", "x64_windows", "darwin"]:
overriden_tools["gcc"] = _build_envoy_cc_wrapper(repository_ctx)
return _upstream_cc_autoconf_impl(repository_ctx, overriden_tools=overriden_tools)

cc_autoconf = repository_rule(
implementation = cc_autoconf_impl,
attrs = {
"_envoy_cc_wrapper": attr.label(default="@envoy//bazel:cc_wrapper.py"),
},
environ = [
"ABI_LIBC_VERSION",
"ABI_VERSION",
Expand All @@ -65,6 +57,7 @@ cc_autoconf = repository_rule(
"BAZEL_VC",
"BAZEL_VS",
"CC",
"CXX",
"CC_CONFIGURE_DEBUG",
"CC_TOOLCHAIN_NAME",
"CPLUS_INCLUDE_PATH",
Expand All @@ -82,8 +75,6 @@ cc_autoconf = repository_rule(
"VS120COMNTOOLS",
"VS140COMNTOOLS"])


def cc_configure():
"""A C++ configuration rules that generate the crosstool file."""
cc_autoconf(name="local_config_cc")
native.bind(name="cc_toolchain", actual="@local_config_cc//:toolchain")
33 changes: 0 additions & 33 deletions bazel/cc_configure.bzl.diff

This file was deleted.

54 changes: 54 additions & 0 deletions bazel/cc_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/python
import os
import sys
import tempfile

envoy_real_cc = {ENVOY_REAL_CC}
envoy_real_cxx = {ENVOY_REAL_CXX}

def sanitize_flagfile(in_path, out_fd):
with open(in_path, "rb") as in_fp:
for line in in_fp:
if line != "-lstdc++\n":
os.write(out_fd, line)

def main():
compiler = envoy_real_cc

# Debian's packaging of Clang requires `-no-canonical-prefixes` to print
# consistent include paths, but Bazel 0.10 only sets that option at compile
# time. We inject it here for the configuration of `@local_config_cc//`.
#
# https://github.com/bazelbuild/bazel/issues/3977
# https://github.com/bazelbuild/bazel/issues/4572
# https://bazel-review.googlesource.com/c/bazel/+/39951
if sys.argv[1:] == ["-E", "-xc++", "-", "-v"] and "clang" in compiler:
os.execv(envoy_real_cxx, [envoy_real_cxx, "-E", "-", "-v", "-no-canonical-prefixes"])

# `g++` and `gcc -lstdc++` have similar behavior and Bazel treats them as
# interchangeable, but `gcc` will ignore the `-static-libstdc++` flag.
# This check lets Envoy statically link against libstdc++ to be more
# portable between intalled glibc versions.
if "-static-libstdc++" in sys.argv[1:]:
compiler = envoy_real_cxx
argv = []
for arg in sys.argv[1:]:
if arg == "-lstdc++":
pass
elif arg.startswith("-Wl,@"):
# tempfile.mkstemp will write to the out-of-sandbox tempdir
# unless the user has explicitly set environment variables
# before starting Bazel. But here in $PWD is the Bazel sandbox,
# which will be deleted automatically after the compiler exits.
(flagfile_fd, flagfile_path) = tempfile.mkstemp(dir='./', suffix=".linker-params")
sanitize_flagfile(arg[len("-Wl,@"):], flagfile_fd)
os.close(flagfile_fd)
argv.append("-Wl,@" + flagfile_path)
else:
argv.append(arg)
else:
argv = sys.argv[1:]
os.execv(compiler, [compiler] + argv)

if __name__ == "__main__":
main()
Loading

0 comments on commit 8ea835f

Please sign in to comment.