Skip to content

Link statically when a .pc names an archive by file path - #195

Open
AlJohri wants to merge 1 commit into
rust-lang:masterfrom
AlJohri:static-link-archive-named-by-path
Open

AlJohri wants to merge 1 commit into
rust-lang:masterfrom
AlJohri:static-link-archive-named-by-path

Conversation

@AlJohri

@AlJohri AlJohri commented Sep 30, 2026 •

Copy link
Copy Markdown

When a .pc names a library by file path, the emitted cargo:rustc-link-lib=
drops the suffix extract_lib_from_filename already matched. If a .so of the
same base name sits in that directory, the linker picks it — silently, under
statik(true).

conda-forge's rdkafka-static.pc:

Libs: -L${libdir} ${pc_sysrootdir}${libdir}/librdkafka.a -llz4 -lm ...

librdkafka.a and librdkafka.so.1 are both in ${libdir}. On 0.3.34,
Config::new().statik(true).probe("rdkafka-static") emits
cargo:rustc-link-lib=rdkafka, and the binary comes out linked against
librdkafka.so.1. Library.link_files has the archive path; only the emission
loses it.

Fix: emit static= when the name ends in .a. A Windows .lib can be an
import library, so Windows is unchanged.

Not gated on statik — a path to libfoo.a states the kind on its own, and
this is not confined to Libs.private: the vcpkg Qt5 example in #134 names nine
archives in plain Libs:. Happy to gate it if you'd rather.

Tests: there was no fixture naming a library by file path, so #134's branch
had no coverage. Adds one, plus two unit tests. They assert on Library, not on
the emitted metadata — that goes to println! and nothing captures it, so the
changed line is still untested. cargo fmt --check clean, existing suite
unchanged. Not built against MSRV 1.63 locally.

Follow-up: verbatim

#134 found the right mechanism and stopped because it was unstable. It
stabilized in 1.67 (rust-lang/rust#104360). static:+verbatim=libfoo.a links the
named file, so the ambiguity can't arise. Written and verified against the same
case: AlJohri/pkg-config-rs@static-link-archive-named-by-path...static-link-archive-verbatim

One expression, plus an MSRV bump to 1.67 — which is why it isn't in this PR.
Say the word and I'll swap it in.

Related

Root cause: the file-path branch of parse_libs_cflags emits a bare
`rustc-link-lib=`, discarding the suffix that extract_lib_from_filename
already matched. When a shared library of the same base name sits in the
same directory, the linker picks it, so `Libs.private: /path/libfoo.a`
under statik(true) silently produces a dynamically linked binary.

Emit `static=` when the file name ends in `.a`. A Windows `.lib` can be an
import library, so the extension decides nothing there.

No fixture named a library by file path before this, so the branch behind
issue rust-lang#134 had no coverage.
@AlJohri
AlJohri marked this pull request as ready for review September 30, 2026 20:18

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant