Search code examples
dockerrustarmraspbianalsa

ALSA linking when cross-compiling Rust program for ARM


I'm trying to cross-compile a simple Rust program to record sound with ALSA drivers on a Raspberry Pi Zero using the wavy crate inside a Docker container that has the libasound-dev library installed. However, the linker complains about:

 note: /opt/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lasound
          collect2: error: ld returned 1 exit status

It seems that Cargo is asking rustc to link against the asound lib dynamically with the argument -Bdynamic" "-lasound". How do I tell Cargo where to look for these ALSA libraries?

Update: I added the following to my Cargo.toml file and added --features "alsa-backend" to my cargo build command which seems to have progressed the build:

[features]
alsa-backend = ["alsa"]

[dependencies]
alsa            = { version = "0.2.1", optional = true }

It now throws:

note: /usr/lib/x86_64-linux-gnu/libasound.so: file not recognized: File format not recognized
          collect2: error: ld returned 1 exit status

OK, so it's linking against the x86_64 version of libasound.so. I typed dpkg -L libasound-dev in my Docker container and indeed, it lists /usr/lib/x86_64-linux-gnu/libasound.so instead of an ARM version.

How do I tell the Raspbian Docker container to link against the ARM version of libasound.so?


Solution

  • Solution:

    1. Install the armhf version of libasound-dev to your Raspbian docker image:
    apt-get install libasound-dev -y
    apt-get install libasound-dev:armhf -y
    

    (If you only install libasound-dev:armhf, it will complain about alsa-sys linker errors.)

    1. Add alsa dependency to Cargo.toml:
    [dependencies]
    alsa = { version = "0.2.1", optional = true }
    wavy = { path = "./wavy" }
    
    1. Set alsa-backend flag in Cargo.toml:
    [features]
    alsa-backend = ["alsa"]
    
    1. Pass --features "alsa-backend" to cargo build --target arm-unknown-linux-gnueabihf (target should be applied)

    2. Tell rustc to use the armhf version in .cargo/config:

    [build]
    
    [target.arm-unknown-linux-gnueabihf.libasound]
    linker = "arm-linux-gnueabihf-gcc"
    rustc-link-lib = ["libasound"]
    rustc-link-search = ["/usr/lib/arm-linux-gnueabihf"]
    

    (Depending on the order it links, it may try to use the x86 version instead of the armhf version.)