zonyitoo/context-rs

Does not cross-compile for `x86_64-unknown-linux-musl` on Mac OS X El Capitan

raphaelcohn opened this issue · 4 comments

Thank you for your work on context-rs - it's a great library, and a wonderful example of how to make something difficult to implement and reason about simple to use!

It works absolutely fine on Mac OS X El Capitan, but when trying to cross-compile using cargo build --target x86_64-unknown-linux-musl (from a crate using it as an upstream dependency) on the same, there's a build script error - primarily because the build script looks for musl-gcc.

As an aside, looking for musl-gcc won't work even on some Linux platforms where musl is the default lib. That's because when the system library's musl, musl-gcc doesn't exist. That also is true for any system using musl-cross-make, the musl author's own build system for making musl-based system compilers. I don't know if this a context issue or something deeper in cargo / rustc / rustup. If this is misdirected, I'm happy to file against the correct component and close this issue.

Alternatively, would it be possible to embed the assembler you're compiling with Rust's asm macro? I'm not sure how mature this macro is, or how to use it, so I might be suggesting something inappropriate.

Actual Error:-

   Compiling context v1.0.0
     Running `rustc /Users/raph/.cargo/registry/src/github.com-1ecc6299db9ec823/context-1.0.0/build.rs --crate-name build_script_build --crate-type bin -g -C metadata=27e11b7b5bc898d2 --out-dir /Volumes/Source/GitHub/lemonrock/netio/.cargo/target/debug/build/context-27e11b7b5bc898d2 --emit=dep-info,link -L dependency=/Volumes/Source/GitHub/lemonrock/netio/.cargo/target/debug/deps --extern gcc=/Volumes/Source/GitHub/lemonrock/netio/.cargo/target/debug/deps/libgcc-d21f77bcf393feb8.rlib --cap-lints allow`
     Running `/Volumes/Source/GitHub/lemonrock/netio/.cargo/target/debug/build/context-27e11b7b5bc898d2/build-script-build`
error: failed to run custom build command for `context v1.0.0`
process didn't exit successfully: `/Volumes/Source/GitHub/lemonrock/netio/.cargo/target/debug/build/context-27e11b7b5bc898d2/build-script-build` (exit code: 101)
--- stdout
TARGET = Some("x86_64-unknown-linux-musl")
OPT_LEVEL = Some("0")
PROFILE = Some("debug")
TARGET = Some("x86_64-unknown-linux-musl")
debug=true opt-level=0
HOST = Some("x86_64-apple-darwin")
TARGET = Some("x86_64-unknown-linux-musl")
TARGET = Some("x86_64-unknown-linux-musl")
HOST = Some("x86_64-apple-darwin")
CC_x86_64-unknown-linux-musl = None
CC_x86_64_unknown_linux_musl = None
TARGET_CC = None
CC = None
HOST = Some("x86_64-apple-darwin")
TARGET = Some("x86_64-unknown-linux-musl")
HOST = Some("x86_64-apple-darwin")
CFLAGS_x86_64-unknown-linux-musl = None
CFLAGS_x86_64_unknown_linux_musl = None
TARGET_CFLAGS = None
CFLAGS = None
running: "musl-gcc" "-O0" "-ffunction-sections" "-fdata-sections" "-g" "-m64" "-fPIC" "-static" "-DBOOST_CONTEXT_EXPORT" "-o" "/Volumes/Source/GitHub/lemonrock/netio/.cargo/target/x86_64-unknown-linux-musl/debug/build/context-27e11b7b5bc898d2/out/src/asm/jump_x86_64_sysv_elf_gas.o" "-c" "src/asm/jump_x86_64_sysv_elf_gas.S"


failed to execute command: No such file or directory (os error 2)
Is `musl-gcc` not installed?



--- stderr
thread 'main' panicked at 'explicit panic', /Users/raph/.cargo/registry/src/github.com-1ecc6299db9ec823/gcc-0.3.35/src/lib.rs:897
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Like most Rust projects we use the gcc crate to compile non-Rust code. The name "gcc" is a bit misleading here though, since it supports almost all relevant platforms and compilers.

This is our build script, which uses the TARGET env var to calculate the set of files from here to be compiled with the gcc crate.
In your case it basically passes the paths of the (jump|make|ontop)_x86_64_sysv_elf_gas.S files to the gcc crate which then does the rest to compile it into a single archive.
So in the end I think gcc is at fault here and I believe you should open an issue there. Their logic to split the TARGET env var into a compiler name is probably flawed somewhere. I'm pretty sure other projects using the gcc crate should fail too for you, right?

But since resolving that can take a while you should try to set the CC and/or TARGET_CC env vars. Using those you should be able to manually specify the correct compilers and successfully build this project.

Regarding inline-asm: If you do context switching you have to make very specific assumptions about how your CPU works. For instance look at this. If you know x86_64 assembler you will notice that it's missing the standard function prologue and epilogue. This is not just done because it would be a performance hit (since we have to save %rbx anyways for instance), but also because it would mess with the way we want to store the CPU state in memory (more or less depending on the platform).
What you'd need to do to embed this using inline-asm is to use "naked functions" (#[naked]), which is an unstable and thus still a nightly-only feature right now. Since we still want to support stable Rust releases we are still using gcc and whenever it lands in stable Rust we will try to make this work without this extra compilation step. But you're of course welcome to try this out right now by pasting those 3 assembly files above into 3 naked Rust functions and post your findings at #16. 🙂

Thank you for a very prompt and thorough explanation! I have had minor issues with the gcc crate finding binaries before, so this makes a lot of sense. It's difficult for them having to 'call out' to C-land, as cross compilation and system compilers traditionally haven't played together very nicely. I'll take a punt at using CC and TARGET_CC for now. It may cause a bit of pain later (particularly if any future crate dependencies decide to try to compile a third-party C library whose make/cmake/autocruft infrastructure does funky things with env vars), but we don't have any for now.

Regarding inline-asm: that's a great explanation of the problem. I'm happy to try nightly, as I use a number of unstable features from there anyway (associated consts, etc). I do hope #[naked] becomes stable - hopefully that might enable a longer-term way forward to drop dependencies on libc (at least on Linux and the BSDs) and so on.

Thanks again.

@raphaelcohn I'm encountering the exact same problem as yours — if you still remember, could you explain to what values you ended up setting CC and TARGET_CC options in order to make it work?

@JivanRoquet Oh gosh it was a long time ago. Typically I work with musl-cross with CROSS_COMPILE=x86_64-linux-musl- cargo build --target=x86_64-unknown-linux-musl nowadays.