-
Notifications
You must be signed in to change notification settings - Fork 29
Rust: Create 3 logical ARM builds, based on support for VFP & Thumb2 #22
Rust: Create 3 logical ARM builds, based on support for VFP & Thumb2 #22
Conversation
Thanks for the PR @timonvo! Would it be possible to upstream these patches to LLVM first? I'm pretty wary of having us diverge even more from upstream as we're already pretty far ashore in terms of build systems :( |
I'm not sure if they'll want these patches. I'm not 100% clear on how they build libclang_rt.a for ARM for cross-compiling clang toolchains, but our needs already seem pretty different from theirs, at least right now while we still use both CMake and plain Make-based builds at the same time. Even if they'd take the patches, I'd rather land them here first and then try to upstream. I'm sorry but I'm just trying to finally land these ARM MUSL patches, I've had them lying around for a long time now. My last set of patches to upstream compiler-rt also took quite a while to land, unfortunately. So WDYT? Any way we can still land these anyway? |
Hm ok, this seems reasonably small enough that we don't need to worry too much about conflicts, should be easy enough to conceptually rebase I guess. It's a little weird that if you don't have thumb you don't get some intrinsics which means you may just flat out fail to compile, but I guess most of the time we use this library those intrinsics aren't actually used? Could you back out the makefile changes for now as well? In theory any new work into portability and such should go into CMake, which both our build systems will have to migrate to eventually as well. |
Yeah, it is a little weird that the presence of thumb2 support dictates whether or not you can use a specific built-in, especially since I don't think these builtins are thumb2 specific, it just so happens they're implemented using thumb 2 instructions (although maybe you can't implement them with plain ARM/Thumb1?). Either way, I think it's better to flat out fail to link rather than fail at runtime with a SIGILL error. If we ever do want to make this builtins available on <ARMv7 I think that'd have to be a separate change that should be upstreamed as well. As for the Makefiles, I'll revert them. And I'll look into using the cmake build system for our plain Make-based builds as well. |
The three types of `compiler-rt` builds we now support on ARM are: - `arm`: This is for targets like arm-unknown-linux-gnueabi. It assumes the target doesn't support hardware float (VFP), nor Thumb2 instructions. - `armhf`: This is for targets like arm-unknown-linux-gnueabihf (but also arm-linux-androideabi). It assumes the target supports VFP but not Thumb2 instructions. - `armv7`: This is for targets like armv7-unknown-linux-gnueabihf. It assumes the target supports both VFP and Thumb2 instructions. These three types (mostly) mirror the way Rust's ARM targets are named. The ones starting with `arm-` and ending with `eabi` fall in the `arm` bucket, the ones starting with `arm-` and ending with `eabihf` fall in the `armhf` bucket (although Android is an exception), and the ones starting with `armv7-` fall in the `armv7` bucket. This CL will have a couple of effects: - The CMake-based and plain Make-based builds would previously build different builtins for the same target triple. E.g. arm-linux-androideabi would have Thumb2 but not VFP builtins with the former, but VFP and not Thumb2 builtins with the latter. The CMake-based build is now consistent with the plain Make-based build. - The CMake-based build would *always* specific `-march=armv7-a` for any ARM build, even if it was for say, an ARMv6 target. This is now fixed and the build will use whatever CMAKE_C_FLAGS were specified during configuration instead. - The plain Make-based builds wouldn't build the ARM-specific builtins for targets triples like `arm-unknown-linux-gnueabi` before , because the `Arch` variable would get set to `arm`, which wasn't in the list of `OnlyArchs` in the `lib/builtins/arm/Makefile`. This was confusing though, because for part of the builtins (the non ARM-specific ones) we would use the `compiler-rt` implementation, while for others we would end up using the `libgcc` implementation. After this change, we'll always use the `compiler-rt` implementation. - For similar reasons, target triples like `arm-unknown-linux-musleabi` would not have the ARM-specific builtins built. For MUSL targets that is a problem though, since they won't link with `libgcc` at all, and hence the ARM-specific builtins symbols would be missing at link time. This is the reason why I started working on this change. This change will need an accompanying change in Rust's src/bootstrap/build/native.rs file to avoid breaking the Android build.
af9e2ca
to
2a051ea
Compare
Makefile changes reverted. |
Thanks! |
For posterity: I've been thinking, and I think the best way to fix this issue upstream in LLVM may be to:
That way, we could just always build the whole compiler-rt library with all of the ARM builtins, regardless of the compile target. The VFP builtins would always be included in the library but Rust/LLVM/GCC wouldn't generate any references to them if the compile target doesn't actually support VFP instructions, so they wouldn't have any effect when the library is used with those targets. |
The targets are: - `arm-unknown-linux-musleabi` - `arm-unknown-linux-musleabihf` - `armv7-unknown-linux-musleabihf` These mirror the existing `gnueabi` targets. All of these targets produce fully static binaries, similar to the x86 MUSL targets. For now these targets can only be used with `--rustbuild` builds, as rust-lang/compiler-rt#22 only made the necessary compiler-rt changes in the CMake configs, not the plain GNU Make configs. I've tested these targets GCC 5.3.0 compiled again musl-1.1.12 (downloaded from http://musl.codu.org/). An example `./configure` invocation is: ``` ./configure \ --enable-rustbuild --target=arm-unknown-linux-musleabi \ --musl-root="$MUSL_ROOT" ``` where `MUSL_ROOT` points to the `arm-linux-musleabi` prefix. Usually that path will be of the form `/foobar/arm-linux-musleabi/arm-linux-musleabi`. Usually the cross-compile toolchain will live under `/foobar/arm-linux-musleabi/bin`. That path should either by added to your `PATH` variable, or you should add a section to your `config.toml` as follows: ``` [target.arm-unknown-linux-musleabi] cc = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-gcc" cxx = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-g++" ``` As a prerequisite you'll also have to put a cross-compiled static `libunwind.a` library in `$MUSL_ROOT/lib`. This is similar to [how the x86_64 MUSL targets are built] (https://doc.rust-lang.org/book/advanced-linking.html).
The targets are: - `arm-unknown-linux-musleabi` - `arm-unknown-linux-musleabihf` - `armv7-unknown-linux-musleabihf` These mirror the existing `gnueabi` targets. All of these targets produce fully static binaries, similar to the x86 MUSL targets. For now these targets can only be used with `--rustbuild` builds, as rust-lang/compiler-rt#22 only made the necessary compiler-rt changes in the CMake configs, not the plain GNU Make configs. I've tested these targets GCC 5.3.0 compiled again musl-1.1.12 (downloaded from http://musl.codu.org/). An example `./configure` invocation is: ``` ./configure \ --enable-rustbuild --target=arm-unknown-linux-musleabi \ --musl-root="$MUSL_ROOT" ``` where `MUSL_ROOT` points to the `arm-linux-musleabi` prefix. Usually that path will be of the form `/foobar/arm-linux-musleabi/arm-linux-musleabi`. Usually the cross-compile toolchain will live under `/foobar/arm-linux-musleabi/bin`. That path should either by added to your `PATH` variable, or you should add a section to your `config.toml` as follows: ``` [target.arm-unknown-linux-musleabi] cc = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-gcc" cxx = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-g++" ``` As a prerequisite you'll also have to put a cross-compiled static `libunwind.a` library in `$MUSL_ROOT/lib`. This is similar to [how the x86_64 MUSL targets are built] (https://doc.rust-lang.org/book/advanced-linking.html).
The targets are: - `arm-unknown-linux-musleabi` - `arm-unknown-linux-musleabihf` - `armv7-unknown-linux-musleabihf` These mirror the existing `gnueabi` targets. All of these targets produce fully static binaries, similar to the x86 MUSL targets. For now these targets can only be used with `--rustbuild` builds, as rust-lang/compiler-rt#22 only made the necessary compiler-rt changes in the CMake configs, not the plain GNU Make configs. I've tested these targets GCC 5.3.0 compiled again musl-1.1.12 (downloaded from http://musl.codu.org/). An example `./configure` invocation is: ``` ./configure \ --enable-rustbuild --target=arm-unknown-linux-musleabi \ --musl-root="$MUSL_ROOT" ``` where `MUSL_ROOT` points to the `arm-linux-musleabi` prefix. Usually that path will be of the form `/foobar/arm-linux-musleabi/arm-linux-musleabi`. Usually the cross-compile toolchain will live under `/foobar/arm-linux-musleabi/bin`. That path should either by added to your `PATH` variable, or you should add a section to your `config.toml` as follows: ``` [target.arm-unknown-linux-musleabi] cc = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-gcc" cxx = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-g++" ``` As a prerequisite you'll also have to put a cross-compiled static `libunwind.a` library in `$MUSL_ROOT/lib`. This is similar to [how the x86_64 MUSL targets are built] (https://doc.rust-lang.org/book/advanced-linking.html).
The three types of
compiler-rt
builds we now support on ARM are:arm
: This is for targets like arm-unknown-linux-gnueabi. Itassumes the target doesn't support hardware float (VFP), nor
Thumb2 instructions.
armhf
: This is for targets like arm-unknown-linux-gnueabihf (butalso arm-linux-androideabi). It assumes the target supports VFP
but not Thumb2 instructions.
armv7
: This is for targets like armv7-unknown-linux-gnueabihf.It assumes the target supports both VFP and Thumb2 instructions.
These three types (mostly) mirror the way Rust's ARM targets are
named. The ones starting with
arm-
and ending witheabi
fall inthe
arm
bucket, the ones starting witharm-
and ending witheabihf
fall in thearmhf
bucket (although Android is anexception), and the ones starting with
armv7-
fall in thearmv7
bucket.
This CL will have a couple of effects:
different builtins for the same target triple. E.g.
arm-linux-androideabi would have Thumb2 but not VFP builtins with
the former, but VFP and not Thumb2 builtins with the latter. The
CMake-based build is now consistent with the plain Make-based
build.
-march=armv7-a
forany ARM build, even if it was for say, an ARMv6 target. This is
now fixed and the build will use whatever CMAKE_C_FLAGS were
specified during configuration instead.
builtins for targets triples like
arm-unknown-linux-gnueabi
before , because the
Arch
variable would get set toarm
, whichwasn't in the list of
OnlyArchs
in thelib/builtins/arm/Makefile
. This was confusing though, becausefor part of the builtins (the non ARM-specific ones) we would use
the
compiler-rt
implementation, while for others we would end upusing the
libgcc
implementation. After this change, we'llalways use the
compiler-rt
implementation.arm-unknown-linux-musleabi
would not have the ARM-specificbuiltins built. For MUSL targets that is a problem though, since
they won't link with
libgcc
at all, and hence the ARM-specificbuiltins symbols would be missing at link time. This is the reason
why I started working on this change.
This change will need an accompanying change in Rust's
src/bootstrap/build/native.rs file to avoid breaking the Android
build. I have that ready to review next in rust-lang/rust@master...timonvo:update-compiler-rt.