I'm trying to cross-compile for amrv7-unknown-linux-gnueabihf
a rust binary based on the alsa crate.
For the cross-compilation, I'm using Cross with a custom Dockerfile to have the required dependencies:
FROM ghcr.io/cross-rs/armv7-unknown-linux-gnueabihf:0.2.5
RUN dpkg --add-architecture armhf && \
apt-get update && \
apt-get install -y --no-install-recommends \
libasound2-dev:armhf \
libudev-dev:armhf \
pkg-config:armhf
RUN apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
COPY .cargo/config.toml /root/.cargo/config.toml
I followed the instruction from this post about cross compiling for arm, by adding the following .cargo/config.toml
file:
[build]
[target.arm-unknown-linux-gnueabihf.libasound]
linker = "arm-linux-gnueabihf-gcc"
rustc-link-lib = ["libasound"]
rustc-link-search = ["/usr/lib/arm-linux-gnueabihf"]
But this leads to the following error, with pkg-config
complaining about not finding the alsa library:
ā alsa-cross git:(master) ā cross build --target armv7-unknown-linux-gnueabihf --features "alsa-backend" -v
+ cargo metadata --format-version 1 --filter-platform armv7-unknown-linux-gnueabihf --features alsa-backend
+ rustc --print sysroot
+ rustup toolchain list
+ rustup target list --toolchain stable-x86_64-unknown-linux-gnu
+ rustup component list --toolchain stable-x86_64-unknown-linux-gnu
+ /usr/bin/docker
+ "/gitrepos/alsa-cross" /usr/bin/docker build --label 'org.cross-rs.for-cross-target=armv7-unknown-linux-gnueabihf' --label 'org.cross-rs.workspace_root=/gitrepos/alsa-cross' --tag cross-custom-alsa-cross:armv7-unknown-linux-gnueabihf-7235a --build-arg 'CROSS_DEB_ARCH=armhf' --build-arg 'CROSS_BASE_IMAGE=ghcr.io/cross-rs/armv7-unknown-linux-gnueabihf:0.2.5' --file ./Dockerfile /gitrepos/alsa-cross
Sending build context to Docker daemon 30.33MB
Step 1/6 : FROM ghcr.io/cross-rs/armv7-unknown-linux-gnueabihf:0.2.5
---> 32cf786140f9
Step 2/6 : RUN dpkg --add-architecture armhf && apt-get update && apt-get install -y --no-install-recommends libasound2-dev:armhf libudev-dev:armhf pkg-config:armhf
---> Using cache
---> 8288951e6f23
Step 3/6 : RUN apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/*
---> Using cache
---> e0ba37616482
Step 4/6 : COPY .cargo/config.toml /root/.cargo/config.toml
---> Using cache
---> 68d32d3aa8f2
Step 5/6 : LABEL org.cross-rs.for-cross-target=armv7-unknown-linux-gnueabihf
---> Using cache
---> 42924a9ff180
Step 6/6 : LABEL org.cross-rs.workspace_root=/gitrepos/alsa-cross
---> Using cache
---> 98094b203092
[Warning] One or more build-args [CROSS_DEB_ARCH CROSS_BASE_IMAGE] were not consumed
Successfully built 98094b203092
Successfully tagged cross-custom-alsa-cross:armv7-unknown-linux-gnueabihf-7235a
+ /usr/bin/docker run --userns host -e 'PKG_CONFIG_ALLOW_CROSS=1' -e 'XARGO_HOME=/xargo' -e 'CARGO_HOME=/cargo' -e 'CARGO_TARGET_DIR=/target' -e 'CROSS_RUNNER=' -e TERM -e 'USER=florian' --rm --user 1000:1000 -v /home/florian/.xargo:/xargo:z -v /home/florian/.cargo:/cargo:z -v /cargo/bin -v /gitrepos/alsa-cross:/project:z -v /home/florian/.rustup/toolchains/stable-x86_64-unknown-linux-gnu:/rust:z,ro -v /gitrepos/alsa-cross/target:/target:z -w /project -i -t cross-custom-alsa-cross:armv7-unknown-linux-gnueabihf-7235a sh -c 'PATH=$PATH:/rust/bin cargo build --target armv7-unknown-linux-gnueabihf --features alsa-backend -v'
Fresh pkg-config v0.3.27
Fresh libc v0.2.145
Fresh bitflags v1.3.2
Fresh cfg-if v1.0.0
Compiling alsa-sys v0.3.1
Fresh nix v0.24.3
Running `/target/debug/build/alsa-sys-5b7e484eb5de5d94/build-script-build`
error: failed to run custom build command for `alsa-sys v0.3.1`
Caused by:
process didn't exit successfully: `/target/debug/build/alsa-sys-5b7e484eb5de5d94/build-script-build` (exit status: 101)
--- stdout
cargo:rerun-if-env-changed=ALSA_NO_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_armv7-unknown-linux-gnueabihf
cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_armv7_unknown_linux_gnueabihf
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS
cargo:rerun-if-env-changed=PKG_CONFIG_armv7-unknown-linux-gnueabihf
cargo:rerun-if-env-changed=PKG_CONFIG_armv7_unknown_linux_gnueabihf
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG
cargo:rerun-if-env-changed=ALSA_STATIC
cargo:rerun-if-env-changed=ALSA_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_armv7-unknown-linux-gnueabihf
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_armv7_unknown_linux_gnueabihf
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_armv7-unknown-linux-gnueabihf
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_armv7_unknown_linux_gnueabihf
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_armv7-unknown-linux-gnueabihf
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_armv7_unknown_linux_gnueabihf
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
--- stderr
thread 'main' panicked at '`PKG_CONFIG_ALLOW_SYSTEM_CFLAGS="1" PKG_CONFIG_ALLOW_SYSTEM_LIBS="1" PKG_CONFIG_PATH="/usr/lib/arm-linux-gnueabihf/pkgconfig/:" "pkg-config" "--libs" "--cflags" "alsa"` did not exit successfully: exit status: 2
error: could not find system library 'alsa' required by the 'alsa-sys' crate
--- stderr
/usr/bin/pkg-config: 1: /usr/bin/pkg-config: Syntax error: word unexpected (expecting ")")
', /cargo/registry/src/index.crates.io-6f17d22bba15001f/alsa-sys-0.3.1/build.rs:13:18
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+ rustup component list --toolchain stable-x86_64-unknown-linux-gnu
Do you have any lead about how to fix this error ?
I have tried the following:
.cargo/config.toml
as described in the same postI'm sure there is a way with cross
, but I personally didn't manage to achieve it.
I did, however, achieve this by using the cross-building functionality of cargo directly.
Create the following Dockerfile
:
ARG DEBIAN_VERSION="11.7"
FROM debian:${DEBIAN_VERSION}
# Install target compilation targets
RUN dpkg --add-architecture armhf
# Add cross compilers and dependencies
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --yes \
curl git crossbuild-essential-armhf pkg-config \
libasound2-dev:armhf \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Install Rust system-wide
ENV RUSTUP_HOME=/opt/rust
ENV CARGO_HOME=/opt/rust
ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path
ENV PATH="/opt/rust/bin:${PATH}"
# Add cross compilation target and set as default
RUN rustup target add armv7-unknown-linux-gnueabihf
ENV CARGO_BUILD_TARGET=armv7-unknown-linux-gnueabihf
# Configure Rust linkers for cross compilation
ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=/usr/bin/arm-linux-gnueabihf-gcc
# Configure pkg-config for cross compilation
ENV PKG_CONFIG_ALLOW_CROSS=1/
ENV PKG_CONFIG_PATH_armv7_unknown_linux_gnueabihf=/usr/lib/arm-linux-gnueabihf/pkgconfig/
# Set the working directory to /src, where we will mount our project
WORKDIR /src
Build the docker container (I named it armv7_cross
here):
docker build -t armv7_cross .
Then, inside of your project directory, you can do:
docker run -v $PWD:/src --user $(id -u):$(id -g) --rm -ti armv7_cross cargo build
This should build like normally, and you should get our output at target/armv7-unknown-linux-gnueabihf
.
Explanation of the docker run
flags:
-v $PWD:/src
- Mounts the current directory to /src
in your docker container
--user $(id -u):$(id -g)
- Configures user and group id, otherwise all your build outputs would be owned by root
--rm
- Destroys the docker container again after building
-ti
- Interactive terminal mode, to get some pretty colors
armv7_cross
- The name of the docker image
cargo build
- The command that gets executed inside of the container.
Note we already set armv7-unknown-linux-gnueabihf
as the default target inside our docker container, so we don't need to supply a --target
flag.