Dumbo
Dumbo

Reputation: 75

How can I build a library from source and ship it inside a crate in Rust

This question is related to Trouble with undefined symbols in Rust's ffi when using a C/Fortran library I have a library pfapack to interface in Rust. The problem is this library is pretty niche, so it will not be found on a user's machine often. The best way to use it would be to just add it to the Cargo.toml and it compiles for the project. I want to output the object files in OUT_DIR so that crates that import pfapack-sys can link to the compiled library. To build the source, I have a makefile that I call from a build.rs.

I first used the OUT_DIR environment variable inside the makefile to output it directly to the OUT_DIR. Here is the example makefile:

CC = gcc
CFLAGS = -O3
C_DIR = $(OUT_DIR)/c_interface
OBJECTS= $(C_DIR)/skpfa.o $(C_DIR)/skpf10.o $(C_DIR)/skbpfa.o $(C_DIR)/skbpf10.o $(C_DIR)/sktrf.o $(C_DIR)/sktrd.o $(C_DIR)/skbtrd.o


all: $(OBJECTS)
    $(AR) rvu $(C_DIR)/libcpfapack.a $(OBJECTS)

clean:
    rm -f *.o
    rm -f libcpfapack.a

.SUFFIXES: .o .c

.c.o:
    $(CC) $(CFLAGS) -c $< -o $(C_DIR)/$@

And here is the build script:

// build script
use std::process::Command;
use std::path::Path;
use std::env;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir);
    let c_interface = out_dir.join(Path::new("c_interface"));
    let fortran = out_dir.join(Path::new("fortran"));

    // Compile source
    Command::new("make").output()
        .expect("Failed to make");


    println!("cargo:rustc-link-search={}", c_interface.display());
    println!("cargo:rustc-link-search={}", fortran.display());
    println!("cargo:rustc-link-lib=gfortran");
    println!("cargo:rustc-link-lib=lapack");
    println!("cargo:rustc-link-lib=blas");
}

The reasoning here is that adding the path to this directory will allow the other package to link the libpfapack.a and libcpfapack.a static libraries. The thing is, I can't seem to be able to link to these libraries from another crate, using rustc-link-lib=pfapack. Am I tackling this the right way? Can I use the build script this way?

Upvotes: 2

Views: 781

Answers (1)

Dumbo
Dumbo

Reputation: 75

This was the good idea, cargo does link correctly the static libraries. The problem here was in the makefile, as the build script does not show any output. The objects had no rules as the defined rule was the suffixe one, while the required objects were in the output dir.

Upvotes: 0

Related Questions