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

Experimental MUSL target support for the compiler #24777

Merged
merged 10 commits into from
Apr 28, 2015

Conversation

alexcrichton
Copy link
Member

These commits build on some great work on reddit for adding MUSL support to the compiler. This goal of this PR is to enable a --target x86_64-unknown-linux-musl argument to the compiler to work A-OK. The outcome here is that there are 0 compile-time dependencies for a MUSL-targeting build except for a linker. Currently this also assumes that MUSL is being used for statically linked binaries so there is no support for dynamically linked binaries with MUSL.

MUSL support largely just entailed munging around with the linker and where libs are located, and the major highlights are:

  • The entirety of libc.a is included in liblibc.rlib (statically included as an archive).
  • The entirety of libunwind.a is included in libstd.rlib (like with liblibc).
  • The target specification for MUSL passes a number of ... flavorful options! Each option is documented in the relevant commit.
  • The entire test suite currently passes with MUSL as a target, except for:
    • Dynamic linking tests are all ignored as it's not supported with MUSL
    • Stack overflow detection is not working MUSL yet (I'm not sure why)
  • There is a language change included in this PR to add a target_env #[cfg] directive. This is used to conditionally build code for only MUSL (or for linux distros not MUSL). I highly suspect that this will also be used by Windows to target MSVC instead of a MinGW-based toolchain.

To build a compiler targeting MUSL you need to follow these steps:

  1. Clone the current MUSL repo from git://git.musl-libc.org/musl. Build this as usual and install it.
  2. Clone and build LLVM's libcxxabi library. Only the libunwind.a artifact is needed. I have tried using upstream libunwind's source repo but I have not gotten unwinding to work with it unfortunately. Move libunwind.a adjacent to MUSL's libc.a
  3. Configure a Rust checkout with --target=x86_64-unknown-linux-musl --musl-root=$MUSL_ROOT where MUSL_ROOT is where you installed MUSL in step 1.

I hope to improve building a copy of libunwind as it's still a little sketchy and difficult to do today, but other than that everything should "just work"! This PR is not intended to include 100% comprehensive support for MUSL, as future modifications will probably be necessary.

@rust-highfive
Copy link
Collaborator

r? @pcwalton

(rust_highfive has picked a reviewer for you, use r? to override)

@alexcrichton
Copy link
Member Author

r? @brson

@rust-highfive rust-highfive assigned brson and unassigned pcwalton Apr 24, 2015
@brson
Copy link
Contributor

brson commented Apr 24, 2015

Why 'x86_64-unknown-linux-musl'? It seems reasonable to me, but Google doesn't have a lot of hits for it.

@nikomatsakis
Copy link
Contributor

Neat!

@alexcrichton
Copy link
Member Author

@brson I found it followed clang's target triple format, but I personally got the idea from the reddit post.

@brson
Copy link
Contributor

brson commented Apr 24, 2015

r=me

@alexcrichton
Copy link
Member Author

@brson I've pushed some more commits clarifying some documentation and also feature gating target_env by just not defining it unless the gate is turned on. I've avoided rebasing for now but I'll rebase all the commits up after review.

@alexcrichton
Copy link
Member Author

@bors: r=brson 01963a6

@bors
Copy link
Contributor

bors commented Apr 25, 2015

⌛ Testing commit 01963a6 with merge 9e28730...

@bors
Copy link
Contributor

bors commented Apr 25, 2015

💔 Test failed - auto-win-64-nopt-t

This adds a new `#[cfg]` matcher against the `target_env` property of the
destination target triple. For example all windows triples today end with `-gnu`
but we will also hopefully support non-`gnu` targets for Windows, at which point
we'll need to differentiate between the two. This new `target_env` matches is
provided and filled in with the target's environment name.

Currently the only non-empty value of this name is `gnu`, but `musl` will be
shortly added for the linux triples.
This commit adds support to the makefiles, configuration script, and build
system to understand MUSL. This is broken up into a few parts:

* Any target of the form `*-musl` requires the `--musl-root` option to
  `./configure` which will indicate the root of the MUSL installation. It is
  also expected that there is a libunwind build inside of that installation
  built against that MUSL.

* Objects from MUSL are copied into the build tree for Rust to be statically
  linked into the appropriate Rust library.

* Objects for binary startup and shutdown are included in each Rust installation
  by default for MUSL. This requires MUSL to only be installed on the machine
  compiling rust. Only a linker will be necessary for compiling against MUSL on
  a target machine.

Eventually a MUSL and/or libunwind build may be integrated by default into the
build but for now they are just always assumed to exist externally.
This commit adds support for x86_64-unknown-linux-musl as a target of the
compiler. There's some comments in the commit about some of the more flavorful
flags passed to the linker as it's not quite as trivial as the normal specs.
MUSL for example provides its own start/end objects in place of the standard
ones shipped by gcc.
This commit modifies the standard library and its dependencies to link correctly
when built against MUSL. This primarily ensures that the right libraries are
linked against and when they're linked against they're linked against
statically.
MUSL support is currently only with static builds, so building a dylib will
always fail.
Statically linked executables do not succeed (aka MUSL-based executables).
Add the ability to ignore a test based on the environment of the triple being
used.
@alexcrichton
Copy link
Member Author

@bors: r=brson faa1a81

@bors
Copy link
Contributor

bors commented Apr 28, 2015

⌛ Testing commit faa1a81 with merge a574d45...

@bors
Copy link
Contributor

bors commented Apr 28, 2015

💔 Test failed - auto-win-32-nopt-t

There were a few test cases to fix:

* Dynamic libraries are not supported with MUSL right now, so all of those
  related test which force or require dylibs are ignored.
* Looks like the default stack for MUSL is smaller than glibc, so a few stack
  allocations in benchmarks were boxed up (shouldn't have a perf impact).
* Some small linkage tweaks here and there
* Out-of-stack detection does not currently work with MUSL
@alexcrichton
Copy link
Member Author

@bors: r=brson 247842b

bors added a commit that referenced this pull request Apr 28, 2015
These commits build on [some great work on reddit](http://www.reddit.com/r/rust/comments/33boew/weekend_experiment_link_rust_programs_against/) for adding MUSL support to the compiler. This goal of this PR is to enable a `--target x86_64-unknown-linux-musl` argument to the compiler to work A-OK. The outcome here is that there are 0 compile-time dependencies for a MUSL-targeting build *except for a linker*. Currently this also assumes that MUSL is being used for statically linked binaries so there is no support for dynamically linked binaries with MUSL.

MUSL support largely just entailed munging around with the linker and where libs are located, and the major highlights are:

* The entirety of `libc.a` is included in `liblibc.rlib` (statically included as an archive).
* The entirety of `libunwind.a` is included in `libstd.rlib` (like with liblibc).
* The target specification for MUSL passes a number of ... flavorful options! Each option is documented in the relevant commit.
* The entire test suite currently passes with MUSL as a target, except for:
  * Dynamic linking tests are all ignored as it's not supported with MUSL
  * Stack overflow detection is not working MUSL yet (I'm not sure why)
* There is a language change included in this PR to add a `target_env` `#[cfg]` directive. This is used to conditionally build code for only MUSL (or for linux distros not MUSL). I highly suspect that this will also be used by Windows to target MSVC instead of a MinGW-based toolchain.

To build a compiler targeting MUSL you need to follow these steps:

1. Clone the current MUSL repo from `git://git.musl-libc.org/musl`. Build this as usual and install it.
2. Clone and build LLVM's [libcxxabi](http://libcxxabi.llvm.org/) library. Only the `libunwind.a` artifact is needed. I have tried using upstream libunwind's source repo but I have not gotten unwinding to work with it unfortunately. Move `libunwind.a` adjacent to MUSL's `libc.a`
3. Configure a Rust checkout with `--target=x86_64-unknown-linux-musl --musl-root=$MUSL_ROOT` where `MUSL_ROOT` is where you installed MUSL in step 1.

I hope to improve building a copy of libunwind as it's still a little sketchy and difficult to do today, but other than that everything should "just work"! This PR is not intended to include 100% comprehensive support for MUSL, as future modifications will probably be necessary.
@bors
Copy link
Contributor

bors commented Apr 28, 2015

⌛ Testing commit 247842b with merge cadc67e...

@aidanhs
Copy link
Member

aidanhs commented May 10, 2015

@alexcrichton got any details of the issues you had with libunwind upstream? I only ask because a toy program I tried seemed to work ok, so I guess it's related to the additional complexity in the compiler?

@alexcrichton
Copy link
Member Author

@aidanhs unfortunately I could never get any more detail other than "unwinding didn't work". I was able to build libunwind upstream with musl-gcc (aka build it against MUSL's libc.a), and it was also correctly linked into the standard library and Rust programs. When running, however, it either couldn't find the unwind tables or couldn't find the handler for the unwind, as all attempts to unwind failed with "handler not found".

In your test program, did you trigger an unwind, or was it just running as usual? Also, did you configure libunwind with any special flags or anything?

let lib = match DynamicLibrary::open(None) {
Ok(l) => l,
Err(..) => return,
};
Copy link
Member

Choose a reason for hiding this comment

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

This might be why stack overflow detection is not working.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hm, could you elaborate a little more? This should in theory just affect the return value of this function, which I'm not sure how connected it is to stack sizes.

Copy link
Member

Choose a reason for hiding this comment

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

Before it failed loud and clear when this didn’t work, but now min_stack_size returns PTHREAD_STACK_MIN instead which might or might not be a correct value to use in the stack size calculations.

/me shrugs.

@aidanhs
Copy link
Member

aidanhs commented May 10, 2015

@alexcrichton oops, I didn't get unwinding working (though normal execution worked). I did get a different error to you though:

$ ./target/debug/binary
thread '<main>' panicked at 'mypanic', src/main.rs:28
fatal runtime error: Could not unwind stack, error = 5
Illegal instruction (core dumped)

Sorry for the noise!

@alexcrichton
Copy link
Member Author

I did get a different error to you though:

Ah that's actually the same error that I was seeing, oh well!

@asaaki asaaki mentioned this pull request Aug 4, 2015
@ranma42 ranma42 mentioned this pull request Oct 28, 2015
Centril added a commit to Centril/rust that referenced this pull request Jan 14, 2019
…dor, r=joshtriplett,Centril

Stabilize cfg_target_vendor

This stabilizes the use of `cfg(target_vendor = "...")` and removes the corresponding `cfg_target_vendor` feature. Other unstable cfgs remain behind their existing feature gates.

This functionality was added back in 2015 in rust-lang#28612 to complete the coverage of target tuples (`<arch><sub>-<vendor>-<os>-<env>`). [RFC 131](https://github.com/rust-lang/rfcs/blob/master/text/0131-target-specification.md) governs the target specification, not including `target_vendor` seems to have just been an oversight. `target_os`, `target_family`, and `target_arch` are stable as of 1.0.0. `target_env` was also not mentioned in RFC 131, was added in rust-lang#24777, never behind a feature_gate, and insta-stable at 1.1.0.

The functionality is tested in [test/run-pass/cfg/cfg-target-vendor.rs](https://github.com/rust-lang/rust/blob/master/src/test/run-pass/cfg/cfg-target-vendor.rs).

Closes rust-lang#29718
Centril added a commit to Centril/rust that referenced this pull request Jan 14, 2019
…dor, r=joshtriplett,Centril

Stabilize cfg_target_vendor

This stabilizes the use of `cfg(target_vendor = "...")` and removes the corresponding `cfg_target_vendor` feature. Other unstable cfgs remain behind their existing feature gates.

This functionality was added back in 2015 in rust-lang#28612 to complete the coverage of target tuples (`<arch><sub>-<vendor>-<os>-<env>`). [RFC 131](https://github.com/rust-lang/rfcs/blob/master/text/0131-target-specification.md) governs the target specification, not including `target_vendor` seems to have just been an oversight. `target_os`, `target_family`, and `target_arch` are stable as of 1.0.0. `target_env` was also not mentioned in RFC 131, was added in rust-lang#24777, never behind a feature_gate, and insta-stable at 1.1.0.

The functionality is tested in [test/run-pass/cfg/cfg-target-vendor.rs](https://github.com/rust-lang/rust/blob/master/src/test/run-pass/cfg/cfg-target-vendor.rs).

Closes rust-lang#29718
@jsarenik
Copy link

Is there any update with this, please? I am getting Illegal instruction on Alpine Linux x86_64.

$ uname -mrv
5.10.27-0-lts #1-Alpine SMP Wed, 31 Mar 2021 06:03:59 +0000 x86_64
$ rustc --version
rustc 1.51.0

The freshly and successfully compiled binary is of electrs.

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.

9 participants