2

I have been working on this simple example. This entire project is being compiled on a (Linux AArch64) Raspberry Pi 3B.

Say I have a simple assembly function (that does SIMD addition on AArch64) defined as so:

.text

.global _add_vecu8_16
.type _add_vecu8_16, %function

._add_vecu8_16:
    ldr q0, [x0]
    ldr q1, [x1]

    add v2.16b, v0.16b, v1.16b
    str q2, [x2]
    ret

I convert this into some static library (libneon.a) and import this function into a Rust library. This static library is inside the 'asm/build' folder, which is in the root folder of the project. The Rust code being:

#[link(name = "neon", kind = "static")]
unsafe extern "C" {
    pub(crate) fn _add_vecu8_16(v0: *const u8, v1: *const u8, result: *mut u8);
}

I have defined the VecU8_16 type. It also implements the Add trait.

#[derive(Clone, Copy)]
pub struct VecU8_16 {
    pub data: [u8; 16]
}

impl Add for VecU8_16 {
    type Output = VecU8_16;

    fn add(self, rhs: Self) -> Self::Output {
        let mut result = Self {
            data: [0; 16]
        };

        unsafe {
            _add_vecu8_16(&self.data[0], &rhs.data[0], &mut result.data[0]);
        }

        result
    }
}

I also add a unit-test function in Rust to test this setup. The test function looks like so:

#[test]
fn add_u8() {
    let v0 = VecU8_16 {
        data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
    };

    let v1 = VecU8_16 {
        data: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
    };

    assert_eq!([17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17], (v0 + v1).data);
}

The Rust library successfully finds the static library and successfully compiles with no errors when I use cargo build or cargo build --release.

This is my config.toml:

[target.aarch64-unknown-linux-gnu]
rustflags = ["-Lasm/build", "-lstatic=neon"]

However, when i run cargo test, it fails to load the static library for some reason and tells that '_add_vecu8_16' isnt resolved and recommends me to link to the library which has been done already.

On running cargo test --verbose, I get this:

Compiling neon-rs v0.1.0 (/home/radon/neon-rs)
     Running `/home/radon/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bin/rustc --crate-name neon_rs --edition=2024 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=80 --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --test --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=6f065afc968b0ba4 -C extra-filename=-04ee3bcf5bd69891 --out-dir /home/radon/neon-rs/target/debug/deps -C incremental=/home/radon/neon-rs/target/debug/incremental -L dependency=/home/radon/neon-rs/target/debug/deps -Lasm/build -lstatic=neon`
error: linking with `cc` failed: exit status: 1
  |
  = note:  "cc" "/tmp/rustc2UcG6o/symbols.o" "<25 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "-lneon" "<sysroot>/lib/rustlib/aarch64-unknown-linux-gnu/lib/{libtest-*,libgetopts-*,libunicode_width-*,librustc_std_workspace_std-*,libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "asm/build" "-L" "<sysroot>/lib/rustlib/aarch64-unknown-linux-gnu/lib" "-o" "/home/radon/neon-rs/target/debug/deps/neon_rs-04ee3bcf5bd69891" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs"
  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: /usr/bin/ld: /home/radon/neon-rs/target/debug/deps/neon_rs-04ee3bcf5bd69891.9gl10j5lzk7lvi88uj1o6po6t.rcgu.o: in function `neon_rs::vec_u8::<impl core::ops::arith::Add for neon_rs::types::VecU8_16>::add':
          /home/radon/neon-rs/src/vec_u8/mod.rs:14: undefined reference to `_add_vecu8_16'
          collect2: error: ld returned 1 exit status
          
  = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)

error: could not compile `neon-rs` (lib test) due to 1 previous error

Caused by:
  process didn't exit successfully: `/home/radon/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bin/rustc --crate-name neon_rs --edition=2024 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=80 --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --test --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=6f065afc968b0ba4 -C extra-filename=-04ee3bcf5bd69891 --out-dir /home/radon/neon-rs/target/debug/deps -C incremental=/home/radon/neon-rs/target/debug/incremental -L dependency=/home/radon/neon-rs/target/debug/deps -Lasm/build -lstatic=neon` (exit status: 1

Am I missing any test configurations?

Apart from this, I also wanted to know how a Rust binary project could use this Rust library. The Rust library depends on a local static library. So my best guess is that the static library is pre-compiled and shipped along with the library source (say if you'd want to put it in crates.io)? Or is it better to use build.rs and ship the assembly source?

Im using clang to compile those assembly files.

Some insight on this would be helpful.

14
  • Rust libraries are also static libraries, and static libraries can be compiled without finding their dependencies. The dep. libraries are only required when building dynamic libraries or executables. Can you run cargo test -v and edit your question to show the output? This will allow us to see if the flag is passed properly to the compiler. Commented Apr 11 at 6:36
  • Well, I am actually working with assembly and Rust. I will edit the question to my original problem. Commented Apr 11 at 12:17
  • @Jmb So does that mean the native static library is bundled with the Rust library (.rlib)? Or will the native library be bundled with the final executable? Commented Apr 11 at 13:15
  • When building the final executable, the linker will look in the static libraries and pick only the parts of the libraries that are used by the executable. Those parts, and only those parts, will be included in the executable. Commented Apr 11 at 13:32
  • @Jmb So whats happening with the unit tests then? Commented Apr 11 at 13:39

1 Answer 1

0

I got to realise that there were typos in my assembly code that was causing the tests to not compile. Thanks for the help.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.