Skip to content

Makefile.PL: make the -static-libstdc++ probe use the C++ runtime - #560

Merged
henry2cox merged 1 commit into
linux-test-project:masterfrom
r3wretrhy:fix/static-libstdcxx-probe-552
Oct 19, 2026
Merged

henry2cox merged 1 commit into
linux-test-project:masterfrom
r3wretrhy:fix/static-libstdcxx-probe-552

Conversation

@r3wretrhy

Copy link
Copy Markdown
Contributor

Fixes #552.

The -static-libstdc++ probe in lib/LcovUtil/Makefile.PL links an empty extern "C" function, so it never pulls anything out of libstdc++.a. It passes as long as the archive exists, even when the archive can't go into a shared object. That's what happens on NetBSD: libstdc++.a isn't built PIC, the probe passes, and the real link then fails on the R_X86_64_TPOFF32 relocation in eh_globals.o.

This makes the probe throw and catch an exception (the XS code uses exceptions too), so the trial link touches the same runtime pieces. When the static archive isn't usable, the existing rpath fallback is taken instead. I also changed the fallback message from "no static C++ library" to "no usable static C++ library", since there can be one that just doesn't work.

I don't have a NetBSD box, so I reproduced it on Linux (gcc 14.2, Debian) with a copy of libstdc++.a whose eh_globals.o was replaced by a non-PIC build using local-exec TLS, put in front with LCOV_CXX="g++ -L<dir>" (the dir also has a libstdc++.so symlink to the real shared library, like a normal system lib dir):

  • master: Makefile.PL picks -static-libstdc++, then make fails with libstdc++.a(eh_globals.o): relocation R_X86_64_TPOFF32 ... can not be used when making a shared object, the same error as in the issue.
  • this branch: Makefile.PL prints the rpath message, make succeeds, and LcovUtil loads.

With the normal toolchain, -static-libstdc++ is still chosen and the built LcovUtil.so has no dynamic libstdc++ dependency.

make check here gives 77 passed / 14 failed out of 91 on both master and this branch, with the same 14 failing on both (mostly genhtml tests hitting a fork/tempdir error in my environment, plus llvm2lcov), so nothing changes there.

The changed lines are perltidy-clean (Perl-Tidy 20221112 with the repo's .perltidyrc).

The trial link which decides whether to build the extension with
-static-libstdc++ used an empty function, so nothing was ever pulled out
of libstdc++.a and the probe succeeded even when that archive cannot go
into a shared object.  On NetBSD libstdc++.a is not position-independent,
so the probe passed and the real link then failed on a TPOFF32 relocation
in eh_globals.o.

Throw and catch an exception in the probe, so it links the same parts of
the runtime the extension does.  When the static archive is unusable the
existing rpath fallback is now taken.

Fixes linux-test-project#552

Signed-off-by: Zhaoqi Xu <lzy00419@outlook.com>
@henry2cox

Copy link
Copy Markdown
Collaborator

Would be good to understand why the tests fail. They are supposed to pass.
llvm2lcov uses LLVM if it exists in your environment - but skips those tests if it does not - so that should also not fail.

@henry2cox
henry2cox merged commit 4c0ca25 into linux-test-project:master Oct 19, 2026
7 checks passed
@r3wretrhy

Copy link
Copy Markdown
Contributor Author

Thanks for merging. I went back through tests/test.log from that run, and all 14 failures come from my box being short on dependencies, not from lcov. I also got the cause wrong in the description: it wasn't a fork/tempdir problem.

  • 8 tests (genhtml/simple/part1–part5, genhtml/errs/msgtest1, lcov/extract/extract2, lcov/parallel_parse) stop with Can't locate Memory/Process.pm. It isn't installed here, and the parallel runs need it.
  • 3 tests (genhtml/function, genhtml/insensitive, genhtml/synthesize) stop with required module GD.pm not found.
  • 3 tests (llvm2lcov/llvm2lcov, lcov/mcdc, genhtml/exception) get past the clang check and then fail with llvm-profdata: command not found. Debian's clang-19 puts clang on PATH, but llvm-profdata is only there as llvm-profdata-19 (or under /usr/lib/llvm-19/bin). So the skip in llvm2lcov.sh doesn't trigger: it checks for clang and not for llvm-profdata/llvm-cov.

The failing set was the same on master and on the branch.

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.

-static-libstdc++ breaks build

2 participants