Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: support linking against libc++ on Linux. #5563

Merged
merged 19 commits into from
Jan 17, 2019

Conversation

PiotrSikora
Copy link
Contributor

Signed-off-by: Piotr Sikora piotrsikora@google.com

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
@PiotrSikora
Copy link
Contributor Author

PiotrSikora commented Jan 10, 2019

bazel/unix_cc_configure.bzl is a copy of Bazel's tools/cpp/unix_cc_configure.bzl with changes to support auto-detection of libc++ (see: bazelbuild/bazel#7074).

I've added libc++ build to the compile_time_options target on the CI, which means that now all its dependencies are rebuilt for each PR (since they must be linked against c++), though it didn't affect build times.

cc @mattklein123 @htuch @ggreenway @lizan

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason to do this the hacky way, before we have BAZEL_CXXOPTS? I.e. is this time sensitive? If not, I'd advocate not doing it, since it's extending the hard-to-maintain cc_configure.bzl fork, which wasn't great (but necessary) in the first place. CC @jmillikin-stripe

@PiotrSikora
Copy link
Contributor Author

It's not time sensitive (from my point of view), so I'm fine with putting it on hold, but the "hacky way" is basically 7 lines of dispatch code in cc_configure.bzl and a local copy of unix_cc_configure.bzl, so I'm not sure if that's problematic enough to justify blocking this.

Also, CentOS support is blocked on libc++, though I don't particularly care about that. cc @lizan

@htuch
Copy link
Member

htuch commented Jan 10, 2019

@PiotrSikora will we have BAZEL_CXXOPTS at the next point release? This is only a couple of weeks away last time I checked.

@PiotrSikora
Copy link
Contributor Author

@htuch I don't think so. I've opened bazelbuild/bazel#7074 a few hours ago, and I believe that the next release is already branched, so this will probably be available in February release (assuming it lands at all, since they are actively rewriting cc_configure nowadays).

Copy link
Contributor

@jmillikin-stripe jmillikin-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm opposed to vendoring unix_cc_configure.bzl into Envoy. That file is not part of Bazel's public API and version skew against the version in @bazel_tools was historically a source of substantial build toil for Envoy.

I also don't understand why BAZEL_CXXOPTS is being used here, and am in general uncomfortable with using environment variables to smuggle critical configuration past the Bazel crosstool. Why can't this be done with --cxxopt=-stdlib=libc++?

@PiotrSikora
Copy link
Contributor Author

@jmillikin-stripe BAZEL_CXXOPTS is being used when auto-detecting local CC toolchain, because you need to pass -stdlib=libc++ to $CC -E -xc++ - -v in order to get libc++ include paths, otherwise you get libstdc++ include paths, and no amount of --cxxopt and/or --linkopt is going to help you build against libc++, when your toolchain imports headers from different standard library, and libc++ headers are outside of Bazel sandbox.

See bazelbuild/bazel#7074.

@lizan
Copy link
Member

lizan commented Jan 10, 2019

It is not time sensitive for me either so I’m fine to hold it for a while. Is it possible to get around forked unix_configure by adding -stdlib=libc++ in our cc_wrapper.py conditionally?

@PiotrSikora
Copy link
Contributor Author

@lizan even though it should, cc_wrapper is actually never executed for those calls...

@htuch
Copy link
Member

htuch commented Jan 14, 2019

@PiotrSikora so there is no other way to divert to our cc_wrapper.py? This provides an accessible low-level insertion point as well.

@PiotrSikora
Copy link
Contributor Author

I've tried this again, and it turns out that my original test was wrong and cc_wrapper is being called after all (unix_cc_configure.bzl ignores repository_ctx.execute() exit status and continued with an empty response, so I assumed that cc_wrapper isn't called, but it was), so we can do it there.

I have something working, but it still needs CXXFLAGS="-stdlib=libc++" in the environment for the dependencies. I'll push it after some tests.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
@PiotrSikora
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

🔨 rebuilding ci/circleci: compile_time_options (failed build)

🐱

Caused by: a #5563 (comment) was created by @PiotrSikora.

see: more, trace.

@@ -6,6 +6,7 @@

envoy_real_cc = {ENVOY_REAL_CC}
envoy_real_cxx = {ENVOY_REAL_CXX}
envoy_cxxflags = {ENVOY_CXXFLAGS}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will change the content of the compiler wrapper when $CXXFLAGS changes, which will have significant negative impact on build caching.

When the crosstool bootstrap runs this script, does it propagate environment variables? If yes, then you can use envoy_cxxflags = os.environ.get("CXXFLAGS", "")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that's kind of the point, isn't it? Same is true for changing $CC and $CXX.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bazel won't cache when flags changed so I don't think it is negative anyway?

pass
if "-stdlib=libc++" in envoy_cxxflags:
arg.append("-lc++")
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need else and pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I've tried to be explicit that there are 2 cases we're supporting here. It's slightly more readable, IMHO, but I'm happy to remove it if you prefer it one way or another.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer removing unless you want to add a comment as well explaining this, one of these should be done IMHO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@@ -15,4 +15,6 @@ tar xf gperftools-"$VERSION".tar.gz
cd gperftools-"$VERSION"

LDFLAGS="-lpthread" ./configure --prefix="$THIRDPARTY_BUILD" --enable-shared=no --enable-frame-pointers --disable-libunwind
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need -lc++ here if stdlib is libc++, it overrides existing LDFLAGS and will result failure when I tried to build prebuilt deps with libc++.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, it works for me locally and on the CI.

How are you building that, exactly? Can you paste the command and/or environment you're building this in? Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have slightly modified build_container_common.sh to pass CXXFLAGS/LDFLAGS to build the image, and only this one will fail to link (as it compiled with libc++ but not linking).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does changing this to LDFLAGS="${LDFLAGS} -lpthread" fix your build?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that would be good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, let me know if this works for you.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
lizan
lizan previously approved these changes Jan 15, 2019
@PiotrSikora PiotrSikora changed the title build: allow linking against libc++ on Linux. build: support linking against libc++ on Linux. Jan 15, 2019
@PiotrSikora
Copy link
Contributor Author

@htuch this should be good to go, PTAL.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, just some minor nits, will merge when these are fixed unless @jmillikin-stripe has further objection.

if "-static-libstdc++" in sys.argv[1:] or "-stdlib=libc++" in envoy_cxxflags:
# Append CXXFLAGS to all C++ targets (this is mostly for dependencies).
if envoy_cxxflags and "-std=c++" in str(sys.argv[1:]):
argv = envoy_cxxflags.split(" ")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be using shlex.split here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't matter for CXXFLAGS, but sure, changed.

pass
if "-stdlib=libc++" in envoy_cxxflags:
arg.append("-lc++")
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer removing unless you want to add a comment as well explaining this, one of these should be done IMHO.

# Force Bazel to link using lld, since GNU ld has trouble linking against libc++fs.
export BAZEL_BUILD_OPTIONS="${BAZEL_BUILD_OPTIONS} --linkopt -fuse-ld=lld"
export BAZEL_TEST_OPTIONS="${BAZEL_TEST_OPTIONS} --linkopt -fuse-ld=lld"
echo "libc++ configured"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meta-question; do we have upstream Bazel tracking for a better way to select libc++ vs. libstdc++? Even if we can do what is needed in this PR, I think Bazel should add much cleaner support to handle this, it should be a simple CLI switch..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added it to bazelbuild/bazel#6926, since it seems that cc_configure is undergoing major rewrite.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll also add this to our Bazel team biweekly sync, thanks.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, one last ask, can you add a section in https://github.com/envoyproxy/envoy/blob/master/bazel/README.md explaining how developers can enable this on the build CLI? Ready to merge after that.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
bazel/README.md Outdated
```
Note: this assumes that both: clang compiler and libc++ library are installed in the system,
and that `clang` is available in `$PATH`. On some systems, this might need to be changed to
`CC="clang-7"` and `CXX="clang++-7"`.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@htuch Let me know if this looks reasonable.

To be honest, I'm kind of tempted to put all those commands in .bazelrc and expose this as --config=libc++, ideally hardcoding CC=clang-7 and CXX=clang++-7, though it would make overriding compilers a bit difficult.

What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, I think --action_env=CXX=clang++-7 would work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, everything works in --action_env, so the whole thing would boil down to bazel build --config=libc++ //source/... //test/...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

@lizan
Copy link
Member

lizan commented Jan 16, 2019

/retest

@repokitteh-read-only
Copy link

🔨 rebuilding ci/circleci: docs (failed build)
🔨 rebuilding ci/circleci: compile_time_options (failed build)

🐱

Caused by: a #5563 (comment) was created by @lizan.

see: more, trace.

@PiotrSikora
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

🔨 rebuilding ci/circleci: compile_time_options (failed build)

🐱

Caused by: a #5563 (comment) was created by @PiotrSikora.

see: more, trace.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Notably, tcmalloc_debug crashes without -ggdb3 -fno-omit-frame-pointer.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Copy link
Contributor

@jmillikin-stripe jmillikin-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@htuch htuch merged commit 6674c03 into envoyproxy:master Jan 17, 2019
fredlas pushed a commit to fredlas/envoy that referenced this pull request Mar 5, 2019
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Fred Douglas <fredlas@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants