-
Notifications
You must be signed in to change notification settings - Fork 1.7k
chore: Build for x86_64-unknown-linux-musl with all features and optimized binary size #689
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
Conversation
Signed-off-by: Alexander Rodin <[email protected]>
Signed-off-by: Alexander Rodin <[email protected]>
Signed-off-by: Alexander Rodin <[email protected]>
Signed-off-by: Alexander Rodin <[email protected]>
Signed-off-by: Alexander Rodin <[email protected]>
@a-rodin this is fantastic! Thank you for doing this. I spent a considerable amount of time trying to do exactly this and was unsuccessful. In fact, I've been reaching out to our network to try and find someone to help with this, so I'm really happy to see this done. 😄 I'll have @LucioFranco review and then we can merge and get it fully integrated into our releases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fantastic! I pulled this down locally and ran the build, everything looks good. I'm very happy this was even possible! I have a few questions but nothing blocking.
I say we
@binarylogic I think we will have to build the new image and push it to docker hub before we can merge this?
# Nightly Rust is used because at the moment only nightly uses recent enough | ||
# LLVM version that supports libc++ with musl. It can be changed to a stable | ||
# version after Rust 1.38 release. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving a note here: we should open an issue for this.
cc @binarylogic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LucioFranco I was just trying to compile a musl Vector on a Linux x86_64 machine with cargo build --target x86_64-unknown-linux-musl --release --verbose
using Rust stable 1.36.0
and hit an openssl error. Is this problem related to this issue?
Any consideration of using Rust native rustls? See https://jbp.io/2019/07/01/rustls-vs-openssl-performance.html. This works well for rusoto https://github.com/rusoto/rusoto/blob/master/rusoto/core/README.md#usage-with-rustls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@moderation The OpenSSL error shouldn't be related to differences between nightly and stable Rust. Probably pkg-config
is installed on your system, but returns empty CFLAGS
and LIBS
for openssl
package. In that case setting environment variables OPENSSL_STATIC=1
and OPENSSL_INCLUDE_DIR
/OPENSSL_LIB_DIR
might help. See sfackler/rust-openssl#604 and https://github.com/timberio/vector/blob/master/distribution/docker/alpine/Dockerfile#L10-L13 for an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@a-rodin thanks for the tip. I'm now able to get through to the linking stage with env OPENSSL_STATIC=1 OPENSSL_INCLUDE_DIR="/usr/include" OPENSSL_LIB_DIR="/usr/lib/x86_64-linux-gnu" cargo build --target x86_64-unknown-linux-musl --release --verbose
. I get error: linking with
cc failed: exit code: 1
following by a large stack trace / error dump. Closer. Maybe need to wait for newer Rust releases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@moderation I've seen linker crashing when building native rdkafka
dependency without rdkafka/cmake_build
feature, it is unrelated to Rust at all and caused by linking unused dynamic library for librdkafka
. You can try cargo build --target x86_64-unknown-linux-musl --release --verbose --features="default rdkafka/cmake_build"
, in that case the library that makes C++ linker crash would just not be created at all.
# In order to be able to use the latest stable release with musl, | ||
# we need to backport unreleased changes from this PR: | ||
# https://github.com/libressl-portable/portable/pull/529/files. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what are the implications of this? Is there any follow up that we might need to do here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
program_invocation_short_name
is a global variable that contains short name of the program. It is not a part of standard C library, but a GNU extension. It is provided by musl
though. The original code in LibreSSL checks on Linux whether C library is glibc
and generates a compile-time error if it is not, even if program_invocation_short_name
is available. With the patch the error is not thrown and program_invocation_short_name
from musl
is used.
Because the issue is fixed in upstream by the mentioned PR, it should be possible to remove this patching after the next release of LibreSSL.
Everything looks great here. I'm going to merge and follow up with documentation changes. |
This PR enables all features, including those with native dependencies, for
x86_64-unknown-linux-musl
target. The resulting binary is fully statically linked, LTO-optimized, and stripped.The build toolchain is based on Clang and
libc++
from LLVM project, in addition tomusl
.libc++
is used byrdkafka
andleveldb
. Although it should be possible to link GNUlibstdc++
statically, it makes the resulting binaries licensed under LGPL, which might be not desirable as Vector's license is Apache 2. In contrast,libc++
is MIT/UIUC licensed.Clang is used not only because it is easy to pair with
libc++
, but also because it enables cross-language linker plugin LTO. Linker plugin LTO is different from LTO codegen option in Rust. Both types of LTO can be used together to reduce binary size and improve runtime performance.Here are the measurements of the binary size with different LTO combinations for
x86_64-unknown-linux-musl
target:lto=thin
lto
lto=thin
lto=thin
lto=thin
lto
lto
lto
From the results listed above it can be seen that Rust codegen LTO type
lto
and linker plugin LTO typelto
deliver the best size of compressed stripped binary. It theoretically should also have the best performance, as LTO reduces functions call overhead by inlining small functions.For comparison, a similar table for
x86_64-unknown-linux-gnu
:lto=thin
lto
As a result, Rust codegen LTO type
lto
and linker plugin LTO typelto
are used forx86_64-unknown-linux-musl
. Rust LTO type is not set inCargo.toml
, but is added at the build time because LTO significantly increases build times, and in my opinion it is better to start from enabling it only for certain build types in CI.Stripping of Vector binary is added for all target platforms because it can't hurt, but only reduce resulting binaries size.
Ref #661, #630, #654, #669