The first thing I attempted was to install the necessary toolchain that should, in theory, allow me to cross-compile the Rust project on my Mac and target Linux. This did not go as smoothly as I would have loved. The first issue I encountered was with OpenSSL. After fixing that, the next issue was with backtrace-sys with the build failing with `error: failed to run custom build command for backtrace-sys v0.1.34`
This looks like I probably do not have the right environment/toolchain/dependencies installed.
I had the option of trying to identify all the required dependencies, but I was really running out of time and frankly, hunting around for the correct dependencies needed to set up a working compiler toolchain is also not fun. So I ended up making use of Docker to help with the build processes.
What I did was to create an image based on alpine Linux with the required toolchain. I then use the container spurn based on the image for the build processes. The procedure is as follows:
The Dockerfile:
FROM alpine:3.11 AS build LABEL maintainer="Dadepo Aderemi" # # -- Install Rust build toolchain # ENV RUSTFLAGS="-C target-feature=+crt-static" RUN apk add rust cargo openssl-dev
The +crt-static ensures statically linking of runtime dependencies. For more on this see Static and dynamic C runtimes
Now make sure to be in the same directory the docker file is located and create the image by running:
docker build -t rust-linux-builder .
Once built, run and connect into the container with the source code of the project mounted as volume by running:
docker run -it --rm --net=host -v $(pwd):/build rust-linux-builder
Note using $(pwd) assumes your current directory is where the source of the project is located. Also the use of the --rm flag ensures the container is removed automatically on exit. No need to keep the container around after finishing with the build.
Once in the container, switch to /build then run the build command:
/ # cd /build/ /build # cargo build --target x86_64-alpine-linux-musl --release
Once the build completes, exit the container and the binary would be found within the /target directory. Which can then be copied and installed on the linux server where it would be executed.
As you can see, there is nothing complicated in the Dockerfile and you can easily create your own, with your modification if need be. But in case you do not want to do that, I pushed the Docker image to Docker hub. This means you can easily get your rust project, targeting Linux by running:
docker run -it --rm --net=host -v $(pwd):/build dadepo/rust-linux-builder
...and follow the steps outlined above.
Hi
ReplyDeleteI'm just learning docker so your post was very useful to me. Thanks.
One small improvement, I think, is to add the following to the Dockerfile:
WORKDIR /build
That way you don't have to "cd /build" before running cargo. This also makes it possible to run it directly like this:
$ docker run --rm --net=host -v $(pwd):/build rust-linux-builder cargo build
Compiling hello v0.1.0 (/build)
Finished dev [unoptimized + debuginfo] target(s) in 2.52s