Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue locating static libraries and parsing linker scripts? #1375

Closed
jsdw opened this issue Jan 25, 2025 · 9 comments
Closed

Issue locating static libraries and parsing linker scripts? #1375

jsdw opened this issue Jan 25, 2025 · 9 comments
Labels

Comments

@jsdw
Copy link

jsdw commented Jan 25, 2025

Hello!

Apologies if this is a dumb question; It's not an area I venture into super often!

I have some C code which I've been successfully compiling using the cc crate for a while now. The config in build.rs is nothing special and looks like this:

build_c
    .flag_if_supported("-Wno-sign-compare")
    .flag_if_supported("-Wno-unused-parameter")
    .flag_if_supported("-Wno-missing-field-initializers")
    .compile("readstat");

if cfg!(target_os = "macos") {
    println!("cargo:rustc-link-lib=m");
    println!("cargo:rustc-link-lib=z");
    println!("cargo:rustc-link-lib=iconv");
} else if cfg!(target_os = "linux") {
    println!("cargo:rustc-link-lib=static=m");
    println!("cargo:rustc-link-lib=static=z");
}

This still builds today without any issue in MacOS, but has started failing on linux (Ubuntu 22.04) with the error:

error: could not find native static library `m`, perhaps an -L flag is missing?

error: could not compile `readstat_sys` (lib) due to 1 previous error

Caused by:
  process didn't exit successfully: `/home/james/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name readstat_sys --edition=2021 readstat-sys/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=136 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs)' --check-cfg 'cfg(feature, values())' -C metadata=bdf86ead07f346d8 -C extra-filename=-bdf86ead07f346d8 --out-dir /home/james/Programming/tmp/statscloud-backend/target/debug/deps -C incremental=/home/james/Programming/tmp/statscloud-backend/target/debug/incremental -L dependency=/home/james/Programming/tmp/statscloud-backend/target/debug/deps -L native=/home/james/Programming/tmp/statscloud-backend/target/debug/build/readstat_sys-d19f84c9b6404601/out -l static=readstat -l static=m -l static=z` (exit status: 1)

I have a libm.a at the path /usr/lib/x86_64-linux-gnu/libm.a, which is a path specified in my /etc/ld.so.conf file (well, included via /etc/ld.so.conf.d/x86_64-linux-gnu.conf).

Nevertheless, I manually added this path to my build script like so:

println!("cargo:rustc-link-search=/usr/lib/x86_64-linux-gnu");

This now leads to a new error on trying to compile:

error: failed to add native library /usr/lib/x86_64-linux-gnu/libm.a: Unsupported archive identifier

error: could not compile `readstat_sys` (lib) due to 1 previous error

Caused by:
  process didn't exit successfully: `/home/james/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name readstat_sys --edition=2021 readstat-sys/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=136 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs)' --check-cfg 'cfg(feature, values())' -C metadata=bdf86ead07f346d8 -C extra-filename=-bdf86ead07f346d8 --out-dir /home/james/Programming/tmp/statscloud-backend/target/debug/deps -C incremental=/home/james/Programming/tmp/statscloud-backend/target/debug/incremental -L dependency=/home/james/Programming/tmp/statscloud-backend/target/debug/deps -L native=/home/james/Programming/tmp/statscloud-backend/target/debug/build/readstat_sys-d19f84c9b6404601/out -L /usr/lib/x86_64-linux-gnu -l static=readstat -l static=m -l static=z` (exit status: 1)

Weird! So just out of curiosity I cat /usr/lib/x86_64-linux-gnu/libm.a and see:

/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.35.a /usr/lib/x86_64-linux-gnu/libmvec.a )

Ok.. this is a linker script or something and not an actual static library. Based on this I try manually including the libm it shows here ie I add this to my build script (removing the original):

println!("cargo:rustc-link-lib=static=m-2.35");

My library now successfully compiles, hurrah! My new build.rs looks like:

build_c
    .flag_if_supported("-Wno-sign-compare")
    .flag_if_supported("-Wno-unused-parameter")
    .flag_if_supported("-Wno-missing-field-initializers")
    .compile("readstat");

if cfg!(target_os = "macos") {
    println!("cargo:rustc-link-lib=m");
    println!("cargo:rustc-link-lib=z");
    println!("cargo:rustc-link-lib=iconv");
} else if cfg!(target_os = "linux") {
    println!("cargo:rustc-link-search=/usr/lib/x86_64-linux-gnu");
    println!("cargo:rustc-link-lib=static=m-2.35");
    println!("cargo:rustc-link-lib=static=z");
}

But what I am now wondering is:

  • How can I ensure that my library builds on other ubuntu/debian machines and potentially different libm versions?
  • Why do I need to explicitly point at a library search path which should already be searched?
  • Does the linker in use not know how to handle the linker script thingy in libm.a?

Apologies if this is the complete wrong place to ask this (it probably is), but I wonder if you might have any insight?

@NobodyXu
Copy link
Collaborator

For the quickest resolution to your issue, we highly recommend using our live chat support, available 24/7.

I'm not aware of anything like this for cc-rs, the best I known is zulip.

@NobodyXu
Copy link
Collaborator

NobodyXu commented Jan 25, 2025

Why do I need to explicitly point at a library search path which should already be searched?

Not sure, honestly never seen this before.

Does the linker in use not know how to handle the linker script thingy in libm.a?

By default rustc invokes c compiler to invoke the system-wide linker with the correct arguments.

Maybe there's something different about your environment that rustc didn't take account of?

@madsmtm

This comment has been minimized.

@madsmtm
Copy link
Collaborator

madsmtm commented Jan 26, 2025

For the question itself, I think this may be more relevant on the rust-lang/rust repo? It sounds like you can reproduce it without cc-rs at all?

has started failing on linux

When? Can you try to narrow down the nightly rustc version and/or cc-rs version?

@rust-lang rust-lang deleted a comment Jan 27, 2025
@ChrisDenton

This comment has been minimized.

@jsdw
Copy link
Author

jsdw commented Jan 27, 2025

Thanks for the input!

I found that I sidestepped my issue by just dynamically linking instead on linux, ie removing the =static in the output build.rs stuff so:

println!("cargo:rustc-link-lib=m");
println!("cargo:rustc-link-lib=z");

FWIW this issue happened on a couple of WSL Ubuntus as well as my own Ubuntu machine and some other distro.

When? Can you try to narrow down the nightly rustc version and/or cc-rs version?

I develop on MacOS mainly so it might have gone unnoticed for a while, but yup I will look into it again at some point and work out when the breakage was and raise on rust-lang/rust!

Thanks guys!

@jsdw jsdw closed this as completed Jan 27, 2025
@NobodyXu
Copy link
Collaborator

NobodyXu commented Jan 27, 2025

I found that I sidestepped my issue by just dynamically linking instead on linux, ie removing the =static in the output build.rs stuff so:

cc @jsdw oops I just realized that you are trying to statically link to glibc, which is not supported by glibc.

Only musl libc can do that static linking.

And I'm not sure if you need to link if manually, rustc automatically link with libc and its libm on the final linking stage.

The compilation of a crate just creates an archive and doesn't do any linking.

@jsdw
Copy link
Author

jsdw commented Jan 28, 2025

oops I just realized that you are trying to statically link to glibc, which is not supported by glibc.

Maybe I'm misunderstanding, but I am only trying to statically link to libm and libz, not libc itself?

Also, this code has worked without issue for a couple of years, and only recently started failing; I'd have assumed it would always have failed if there was something more fundamental like that wrong with it?

@NobodyXu
Copy link
Collaborator

Maybe I'm misunderstanding, but I am only trying to statically link to libm and libz, not libc itself?

For libm, I believe it is part of libc, so glibc and musl libc provides different libm as part of their libc distr.

I'd have assumed it would always have failed if there was something more fundamental like that wrong with it?

Maybe it's the gnu ld script?

Perhaps old versions of glibc doesn't use them which is why they worked


/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.3u

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants