[SOLVED] Linking asm into crate


#1

I have a Rust crate including asm files:

Cargo.toml:

[package]
name = "a"
version = "0.1.0"
authors = ["M Farkas-Dyck <strake888@gmail.com>"]
build = "build.rs"

build.rs:

use std::process::Command;
use std::env;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    if !(Command::new("as").args(&["-o", &(out_dir.clone() + "/a.o"),
                                   "src/a.s"])
                           .status().unwrap().success() &&
         Command::new("ar").args(&["-crus",
                                   &(out_dir.clone() + "/liba.a"),
                                   &(out_dir.clone() + "/a.o")])
                            .status().unwrap().success()) {
      panic!("failed");
    }
    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=static=a");
}

src/lib.rs:

extern "C" {
    fn a() -> usize;
}

#[test]
fn test_a() {
    assert_eq!(0, unsafe { a() });
}

src/a.s:

.intel_syntax noprefix

.text

a:
	xor rax, rax
	ret

but when i do cargo test this happens:

Compiling a v0.1.0 (file:///home/strake/a.rs)
error: linking with cc failed: exit code: 1
note: “cc” “-Wl,–as-needed” “-Wl,-z,noexecstack” “-m64” “-L” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib” “/home/strake/a.rs/target/debug/a-092a156f19993e2f.0.o” “-o” “/home/strake/a.rs/target/debug/a-092a156f19993e2f” “-Wl,–gc-sections” “-pie” “-nodefaultlibs” “-L” “/home/strake/a.rs/target/debug” “-L” “/home/strake/a.rs/target/debug/deps” “-L” “/home/strake/a.rs/target/debug/build/a-049bc247725cc2fd/out” “-L” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib” “-Wl,-Bstatic” “-Wl,–whole-archive” “-l” “a” “-Wl,–no-whole-archive” “-Wl,-Bdynamic” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libtest-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libterm-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgetopts-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_unicode-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-2f39a9bd.rlib” “/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-2f39a9bd.rlib” “-l” “dl” “-l” “pthread” “-l” “gcc_s” “-l” “pthread” “-l” “c” “-l” “m” “-l” “rt” “-l” “util” “-l” "compiler-rt"
note: /home/strake/a.rs/target/debug/a-092a156f19993e2f.0.o: In function a::test_a': /home/strake/a.rs/src/lib.rs:7: undefined reference toa’
collect2: error: ld returned 1 exit status

I can cargo build as usual, and objdump -t shows the symbol a defined in liba.a:

In archive target/debug/build/a-049bc247725cc2fd/out/liba.a:

a.o: file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l .text 0000000000000000 a

Why is it not seeing this symbol?


#2

Try adding .global a in your assembly file, otherwise the symbol will default to file-local (effectively the same as static in C).


#3

Derp. Thank you!