14

When a Rust binary (executable or dylib) is built, the version information configured in Cargo.toml has no effect on the binary built, meaning the configured version is not stored inside the binary file.

In Linux, when I use readelf -V for a .so file, you can see the supported interface (SO Name) is stored under the Version definition section '.gnu.version_d' of the ELF file. For example, the output of readelf -V /lib/libnss_files-2.12.so:

Version definition section '.gnu.version_d' contains 2 entries:
   Addr: 0x0000000000001540  Offset: 0x001540  Link: 5 (.dynstr)
   000000: Rev: 1  Flags: BASE   Index: 1  Cnt: 1  Name: libnss_files.so.2
   0x001c: Rev: 1  Flags: none  Index: 2  Cnt: 1  Name: GLIBC_PRIVATE

The /lib/libnss_files-2.12.so file is implementing interface version libnss_files.so.2

The readelf -V output for a Rust or Cargo generated dylib or executable has no such version information. The version config in Cargo.toml is only used by crates.io.

Moreover, Windows DLLs support storing the version information, not the SONAME interface version name like Linux. A cross-compiled Windows DLL also has no version info. Perhaps this is another question, but I thought I'd raise the point here first.

palazzo train
  • 3,229
  • 1
  • 19
  • 40
  • It was [cross posted to reddit](https://www.reddit.com/r/rust/comments/3zi8xh/no_rust_version_info_stored_in_dylib_dynamic_link/) – palazzo train Jan 05 '16 at 03:21

3 Answers3

12

While I don't think there is an immediate way to use ELF facilities for versioning (they are not cross-platform anyway), it is possible to use version information from Cargo:

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

VERSION will now be equal to the version specified in the manifest when cargo build is run. Alternatively, you can use env_opt!() if you want to build your program without Cargo:

const VERSION: Option<&'static str> = env_opt!("CARGO_PKG_VERSION");
Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
  • Then how can i read the version info after I get the final built binary? – palazzo train Jan 06 '16 at 01:09
  • Well, `VERSION` is just a regular constant, so make your program print it when you run it in a certain way, for example, by passing `-v` command line argument (like lots of CLI tools do): `your-program -v`. Again, as I said, this is not related to version information specific to the binary format (ELF headers, PE headers or anything else). – Vladimir Matveev Jan 06 '16 at 10:46
  • Ok, that means I cannot view the version without run the code in the lib. But it's ok to know about this fact. Do you know is there any plan Cargo/Rust use the OS's native facilities for versioning? – palazzo train Jan 11 '16 at 07:59
  • @palazzotrain, no, I haven't heard of any such plans. But you can always submit a feature request to [Cargo](https://github.com/rust-lang/cargo/issues) and [Rust](https://github.com/rust-lang/rust/issues) issue trackers. I think such change wouldn't require an RFC, though I may be wrong, of course. – Vladimir Matveev Jan 11 '16 at 08:56
  • 1
    I post a request to Cargo issue tracker. https://github.com/rust-lang/cargo/issues/2273. – palazzo train Jan 12 '16 at 07:31
2

To give an update on the accepted answer. In Rust 2021 the 2nd macro mentioned in the answer (env_opt) is now accessible via std::option_env

const CARGO_PKG_VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");

And afterwards, you may use it as like

info!("Booting up... VERSION={}", CARGO_PKG_VERSION.unwrap_or("NOT_FOUND"));

Furthermore, as a note, if you want to include, for example, a default config in the binary, the macro std::include_str might be of interest.

ndrsllwngr
  • 21
  • 4
1

use winres(https://github.com/mxre/winres) can set CARGO_PKG_VERSION to dll file version, maybe help for others