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

Rust can be compiled against musl libc without cross-compilation from glibc #7

Closed
frol opened this issue Apr 3, 2016 · 16 comments
Closed

Comments

@frol
Copy link
Contributor

frol commented Apr 3, 2016

According to this resolved issue: rust-lang/rust#28667, Rust should be able to be compiled against musl libc on a musl libc-based OS. It seems it is time to build an Alpine package: https://bugs.alpinelinux.org/issues/3949

@antoineco
Copy link

Did you find a way to do so? My compilation always fails with

make: compiler-rt
make[1]: Entering directory '/rust-master/src/compiler-rt'
make[1]: *** No rule to make target 'triple-builtins'.  Stop.
make[1]: Leaving directory '/rust-master/src/compiler-rt'
/rust-master/mk/rt.mk:404: recipe for target 'x86_64-unknown-linux-gnu/rt/libcompiler-rt.a' failed
make: *** [x86_64-unknown-linux-gnu/rt/libcompiler-rt.a] Error 2

I used the following Dockerfile for reference:

FROM alpine:3.3

RUN apk add --no-cache curl

# build Rust
RUN curl -LO https://github.com/rust-lang/rust/archive/master.zip \
  && unzip master.zip \
  && rm master.zip \
  && cd rust-master \
  && apk add --no-cache --virtual .build-deps \
      python \
      file \
      make \
      g++ \
      llvm-dev \
      musl-dev \
  && apk add libunwind-dev --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ \
  && ./configure \
       --target=x86_64-unknown-linux-musl \
       --musl-root=/usr \
       --llvm-root=/usr \
       --disable-codegen-tests \
       --disable-docs \
  && make

@frol
Copy link
Contributor Author

frol commented Apr 13, 2016

Nope, I haven't had time yet to try. May be you ask this question in that issue discussion?

@antoineco
Copy link

Sure, I was just curious. It seems like it's still necessary to cross compile using a glibc.

@sanmai-NL
Copy link

With some hacks to the Dockerfile, I got a tiny bit further: in the end I ran into rust-lang/rust#28667.

The configure parameters --enable-dist-host-only, --enable-llvm-static-stdcpp that I thought could be relevant seem not to be, the build failure is the same with or without. Using --llvm-root I bumped into rust-lang/rust#27254, so I dropped that.

FROM alpine:3.3

RUN apk add --no-cache 'curl'
# TODO: Verify download.
RUN curl -LOsS 'https://static.rust-lang.org/dist/rustc-1.8.0-src.tar.gz' \
  && tar -xzvf 'rustc-1.8.0-src.tar.gz' \
  && cd 'rustc-1.8.0/' \
  && apk add --no-cache --virtual '.build-deps' \
      'tree' \
      'python' \
      'file' \
      'make' \
      'g++' \
      'llvm-dev' \
      'musl-dev' \
  && apk add 'libunwind-dev' --no-cache --repository 'http://nl.alpinelinux.org/alpine/edge/testing/'
RUN ln -vsf '/bin/true' '/usr/bin/FileCheck' \
  && chmod a+x '/usr/bin/FileCheck'
RUN cd 'rustc-1.8.0/' \
  && ./configure \
       --enable-dist-host-only \
       --enable-llvm-static-stdcpp \
       --target='x86_64-unknown-linux-musl' \
       --musl-root='/usr' \
       --prefix='/usr'
  && make install
make[3]: Entering directory '/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm/lib/Support'
llvm[3]: Compiling APFloat.cpp for Release build
llvm[3]: Compiling APInt.cpp for Release build
llvm[3]: Compiling APSInt.cpp for Release build
llvm[3]: Compiling ARMBuildAttrs.cpp for Release build
llvm[3]: Compiling ARMWinEH.cpp for Release build
llvm[3]: Compiling Allocator.cpp for Release build
llvm[3]: Compiling Atomic.cpp for Release build
llvm[3]: Compiling BlockFrequency.cpp for Release build
llvm[3]: Compiling BranchProbability.cpp for Release build
llvm[3]: Compiling COM.cpp for Release build
llvm[3]: Compiling CommandLine.cpp for Release build
llvm[3]: Compiling Compression.cpp for Release build
llvm[3]: Compiling ConvertUTF.c for Release build
llvm[3]: Compiling ConvertUTFWrapper.cpp for Release build
llvm[3]: Compiling CrashRecoveryContext.cpp for Release build
llvm[3]: Compiling DAGDeltaAlgorithm.cpp for Release build
llvm[3]: Compiling DataExtractor.cpp for Release build
llvm[3]: Compiling DataStream.cpp for Release build
llvm[3]: Compiling Debug.cpp for Release build
llvm[3]: Compiling DeltaAlgorithm.cpp for Release build
llvm[3]: Compiling Dwarf.cpp for Release build
llvm[3]: Compiling DynamicLibrary.cpp for Release build
/rustc-1.8.0/src/llvm/lib/Support/DynamicLibrary.cpp: In static member function 'static void* llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(const char*)':
/rustc-1.8.0/src/llvm/lib/Support/DynamicLibrary.cpp:148:21: error: invalid conversion from 'const void*' to 'void*' [-fpermissive]
     EXPLICIT_SYMBOL(stderr);
                     ^
/rustc-1.8.0/src/llvm/lib/Support/DynamicLibrary.cpp:141:43: note: in definition of macro 'EXPLICIT_SYMBOL'
    if (!strcmp(symbolName, #SYM)) return &SYM
                                           ^
/rustc-1.8.0/src/llvm/lib/Support/DynamicLibrary.cpp:149:21: error: invalid conversion from 'const void*' to 'void*' [-fpermissive]
     EXPLICIT_SYMBOL(stdout);
                     ^
/rustc-1.8.0/src/llvm/lib/Support/DynamicLibrary.cpp:141:43: note: in definition of macro 'EXPLICIT_SYMBOL'
    if (!strcmp(symbolName, #SYM)) return &SYM
                                           ^
/rustc-1.8.0/src/llvm/lib/Support/DynamicLibrary.cpp:150:21: error: invalid conversion from 'const void*' to 'void*' [-fpermissive]
     EXPLICIT_SYMBOL(stdin);
                     ^
/rustc-1.8.0/src/llvm/lib/Support/DynamicLibrary.cpp:141:43: note: in definition of macro 'EXPLICIT_SYMBOL'
    if (!strcmp(symbolName, #SYM)) return &SYM
                                           ^
rm: can't remove '/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm/lib/Support/Release/DynamicLibrary.d.tmp': No such file or directory
/rustc-1.8.0/src/llvm/Makefile.rules:1524: recipe for target '/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm/lib/Support/Release/DynamicLibrary.o' failed
make[3]: Leaving directory '/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm/lib/Support'
make[3]: *** [/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm/lib/Support/Release/DynamicLibrary.o] Error 1
/rustc-1.8.0/src/llvm/Makefile.rules:883: recipe for target 'all' failed
make[2]: Leaving directory '/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm'
make[2]: *** [all] Error 1
make[1]: *** [/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm/Release/bin/llvm-config] Error 2
/rustc-1.8.0/mk/llvm.mk:95: recipe for target '/rustc-1.8.0/x86_64-unknown-linux-gnu/llvm/Release/bin/llvm-config' failed
make[1]: Leaving directory '/rustc-1.8.0'
make: *** [install] Error 2
/rustc-1.8.0/mk/install.mk:22: recipe for target 'install' failed
The command '/bin/sh -c cd 'rustc-1.8.0/'   && ./configure        --enable-dist-host-only        --enable-llvm-static-stdcpp        --target='x86_64-unknown-linux-musl'        --musl-root='/usr'        --prefix='/usr'        --disable-docs        --release-channel='stable'   && make install' returned a non-zero code: 2

@frol
Copy link
Contributor Author

frol commented Apr 15, 2016

@sanmai-NL Hmm. Have you read the threads and the follow-up fixes?

rust-lang/rust#28667 was fixed by introduction of codegen-tests configuration flag (in rust-lang/rust#32168), which can be switched off (!), and, in fact, it seems it should be switched off to avoid rust-lang/rust#28667 with musl libc.

Could you try to pass --disable-codegen-tests option to the ./configure?

@sanmai-NL
Copy link

That configure parameter --disable-codegen-tests was not available for stable Rust 1.8.0. I switched from master to that channel, just since I knew 1.8.0 builds okay in my personal experience. I then ran into rust-lang/rust#27254. I do not have time anymore currently, but you can try to adapt my and @antoineco's Dockerfiles further.

@frol
Copy link
Contributor Author

frol commented Apr 15, 2016

Yeap, that is exactly what I have just discovered. The fix went to the beta and newer branches. 1.8.0 doesn't have it. However, both beta and master fail fast on my attempts to make them:

cfg: version 1.9.0-dev
cfg: build triple x86_64-unknown-linux-gnu
cfg: host triples x86_64-unknown-linux-gnu
cfg: target triples x86_64-unknown-linux-gnu x86_64-unknown-linux-musl
cfg: non-build target triples x86_64-unknown-linux-musl
cfg: host for x86_64-unknown-linux-gnu is x86_64
cfg: host for x86_64-unknown-linux-musl is x86_64
cfg: os for x86_64-unknown-linux-gnu is unknown-linux-gnu
cfg: os for x86_64-unknown-linux-musl is unknown-linux-musl
cfg: have good valgrind for x86_64-unknown-linux-gnu
cfg: no good valgrind for x86_64-unknown-linux-musl
cfg: using CC=gcc (CFG_CC)
cfg: disabling valgrind run-pass tests
cfg: disabling doc build (CFG_DISABLE_DOCS)
fetch: x86_64-unknown-linux-gnu/stage0/bin/rustc
determined most recent snapshot: rust-stage0-2016-03-18-235d774-linux-x86_64-1273b6b6aed421c9e40c59f366d0df6092ec0397.tar.bz2
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 17.1M  100 17.1M    0     0   570k      0  0:00:30  0:00:30 --:--:--  581k
got download with ok hash
opening snapshot dl/rust-stage0-2016-03-18-235d774-linux-x86_64-1273b6b6aed421c9e40c59f366d0df6092ec0397.tar.bz2
extracting rust-stage0/bin/rustc
make: compiler-rt
make[1]: *** No rule to make target 'triple-builtins'.  Stop.
make: *** [x86_64-unknown-linux-gnu/rt/libcompiler-rt.a] Error 2
make[1]: Entering directory '/opt/rust/src/compiler-rt'
make[1]: Leaving directory '/opt/rust/src/compiler-rt'
/opt/rust/mk/rt.mk:404: recipe for target 'x86_64-unknown-linux-gnu/rt/libcompiler-rt.a' failed

P.S. I have tried to combine all configure options from the two provided Dockerfiles and the result is always the same: the mysterious triple-builtins rule cannot be found (and I don't see it in the code either).

@rainbreak
Copy link

@frol can you share your build script?

@rainbreak
Copy link

rainbreak commented Apr 22, 2016

Not sure how you're getting your triple-builtins error, but if you configure like this:

./configure --disable-codegen-tests --musl-root=/lib --enable-dist-host-only --enable-llvm-static-stdcpp --llvm-root=/usr

then you get past that and get a different error:

  FINAL-ARCHIVE: triple/builtins: /rustc-beta/x86_64-unknown-linux-gnu/rt/compiler-rt/triple/builtins/libcompiler_rt.a
make[1]: Leaving directory '/rustc-beta/src/compiler-rt'
cp: x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler-rt.a
rustc: x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore
/bin/sh: x86_64-unknown-linux-gnu/stage0/bin/rustc: not found
/rustc-beta/mk/target.mk:187: recipe for target 'x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib/stamp.core' failed
make: *** [x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib/stamp.core] Error 127
/rustc-beta # ls x86_64-unknown-linux-gnu/stage0/bin/rustc 

This is because the stage 0 compiler is linked against libc:

/rustc-beta # ldd x86_64-unknown-linux-gnu/stage0/bin/rustc 
    /lib64/ld-linux-x86-64.so.2 (0x55b7f98ba000)
    libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x55b7f98ba000)
    librt.so.1 => /lib64/ld-linux-x86-64.so.2 (0x55b7f98ba000)
    libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x55b7f98ba000)
    libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x55b7f98ba000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f78147c6000)
    libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x55b7f98ba000)
Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by x86_64-unknown-linux-gnu/stage0/bin/rustc)
Error relocating x86_64-unknown-linux-gnu/stage0/bin/rustc: mallinfo: symbol not found
Error relocating x86_64-unknown-linux-gnu/stage0/bin/rustc: __rawmemchr: symbol not found
Error relocating x86_64-unknown-linux-gnu/stage0/bin/rustc: __register_atfork: symbol not found

@dyerti
Copy link

dyerti commented Jul 6, 2016

I got rustc building in alpine with some serious hacks:
https://gist.github.com/dyerti/0afc38e42106b8f7ed5bbff8d7430968

Hoping to use this rustc in place of the bootstrapped stage0.

@andrew-d
Copy link
Owner

andrew-d commented Jul 7, 2016

Okay, I have a branch that properly builds rustc using the same hack from @dyerti (using Arch Linux's glibc to run the bootstrapped stage0). The only downside is that it doesn't appear to properly handle --target=x86_64-unknown-linux-musl; you need to pass -l static=gcc_eh to rustc for it to build. Also, the final compiler is itself not static - it's dynamically linking to musl.

I'm going to keep investigating this and see how much more I can get done :-) Another thing I want to try, instead of using Arch Linux's glibc, is this project. Ideally, we'll have the following:

  • The ability to run the stage0 compiler using a proper compatibility layer
  • A compiler that has both the x86_64-unknown-linux-musl and x86_64-unknown-linux-gnu targets

It would also be nice to have a statically-linked version of rustc itself...

@jirutka
Copy link

jirutka commented Jul 7, 2016

Related issue: rust-lang/rust#31322.

@frol
Copy link
Contributor Author

frol commented Oct 26, 2016

I have just noticed that @jirutka has managed to prepare an Alpine Linux package for Rust: https://github.com/alpinelinux/aports/tree/master/testing/rust

# apk add \
        --no-cache \
        --repository http://dl-cdn.alpinelinux.org/alpine/edge/main \
        --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing \
        rust cargo

At the moment, I have only one issue with it, it cannot build completely static binaries because of the package patch explicitly disabling static linkage:

$ rustc --target=x86_64-unknown-linux-musl ./qq.rs
$ ldd ./qq
        /lib/ld-musl-x86_64.so.1 (0x5623b42bc000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f4036f29000)
        libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x5623b42bc000)

@jirutka
Copy link

jirutka commented Apr 13, 2017

FYI, we have updated our rust package with proper support for both dynamic and static linking.

rustc on Alpine produces dynamically linked binary by default, but you can use option -C target-feature=+crt-static to produce statically linked PIE (!) binary instead. Please note that statically linked PIE (Position Independent Executable) binaries are a bit different than non-PIE, ldd reports them incorrectly like dynamically linked. However, they provides the same benefits as classic static binaries (i.e. no dependency on libc), just more secure. Read static-pie.patch and this post for more information.

@frol
Copy link
Contributor Author

frol commented May 11, 2017

@jirutka It seems that -C target-feature=+crt-static causes segfaults:

$ docker run -it --rm alpine sh
/ # apk add --no-cache \
        --repository http://dl-cdn.alpinelinux.org/alpine/edge/main \
        --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing \
        --repository http://dl-cdn.alpinelinux.org/alpine/edge/community \
        rust cargo
...
/ # cat qq.rs
fn main() { println!("Hello, world!"); }
/ # rustc qq.rs
/ # ./qq
Hello, world!
/ # rustc -C target-feature=+crt-static qq.rs
/ # ./qq
Segmentation fault (core dumped)

Any ideas?

P.S. --target=x86_64-unknown-linux-musl option doesn't work at all now:

error[E0463]: can't find crate for `std`
  |
  = note: the `x86_64-unknown-linux-musl` target may not be installed

error: aborting due to previous error

fatal runtime error: failed to initiate panic, error 5

@frol
Copy link
Contributor Author

frol commented May 26, 2017

Alpine 3.6 has been released, and it features Rust package in the main repo which can produce static binaries with -C target-feature=+crt-static just fine! Getting Rust on Alpine is as simple as apk add --no-cache rust cargo now, but since I use it for my own needs quite often I have created a Docker image frolvlad/alpine-rust, which works great for me and the image size is only 220MB total (I reuse my frolvlad/alpine-gcc image, so Rust compiler adds only 120MB on top of the GCC image)

@frol frol closed this as completed May 26, 2017
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

No branches or pull requests

7 participants