Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Return version got from Cargo.toml in a static libreary generated with Rust

I have developed a library using Rust which exposes a function to be used by a C program which returns the library version based in Cargo metadata.

This is the function:

#[no_mangle]
pub extern "C" fn get_version() ->  *const libc::c_char {
    // Get Cargo metadata
    let metadata = cargo_metadata::MetadataCommand::new()
        .exec()
        .expect("Failed to get Cargo metadata");
    let root = metadata.root_package().unwrap();
    let version = root.version.to_string();

    return CString::new(version).unwrap().into_raw();
}

This is the Cargo.toml file (simplified):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[package]
name = "acme"
version = "0.1.0"
edition = "2021"

[dependencies]
...
libc = "0.2"
cargo_metadata = "0.18.1"

[lib]
crate-type=["staticlib"]

I generate the library using cargo build --release, which produces a binary file named libacme.a which I copy into my /usr/local/lib directory (so my C compiler can link properly my C program using it).

So far, so good.

I can compile and link my C program without problems but when I run it I get this error:

thread '<unnamed>' panicked at src/lib.rs:376:10:
Failed to get Cargo metadata: CargoMetadata { stderr: "error: could not find `Cargo.toml` in `/home/fermin/src/mycproject` or any parent directory\n" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5
Abort

I understand this is due to the current approach expects to get the version at runtime, from the Cargo.toml file. But I don’t have a Cargo.toml file at this point (I only have the statically linked libacme.a binary file).

Is there any way of solving this problem (e.g. implement get_version() in a way the version number gets included in the static library)?

>Solution :

Cargo sets the CARGO_PKG_VERSION environment variable for compiled crates, and you can retrieve its value using env!(). You can even create a constant &CStr:

use core::ffi::CStr;

#[no_mangle]
pub extern "C" fn get_version() -> *const libc::c_char {
    const VERSION: &CStr =
        match CStr::from_bytes_with_nul(concat!(env!("CARGO_PKG_VERSION"), "\0").as_bytes()) {
            Ok(version) => version,
            Err(_) => panic!("package version contains null bytes??"),
        };

    VERSION.as_ptr()
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading