The example-lib depends on a method in example-binding which depends on the C++ function example_cpp.
The following confuses me:
cargo test -p example-binding works and correctly links.
cargo test -p example-lib fails to link, with an error for "undefined reference to example_cpp" (the C++ function).
This behaviour happens on an x86 Ubuntu Github Actions runner and an Arm Debian based Pi; but weirdly both commands run without issue on MacOS. Using cargo -vv, the rustc command args don't miss anything obvious like env variables, or -L and --extern flags.
Would anyone have any hints on how to debug this further, or know something obvious that I've missed? I'd be interested in being able to log the linker commands during cargo build/test to see what differs in case there's a difference in cargo commands.
It was an issue from passing -flto during the cc compilation. I can't fully explain why it only manifested when linking the library indirectly on platforms that use the link arg --as-needed, since the symbol was still marked T under nm, but removing lto in the C++ compilation has solved an afternoon of confusion.
does it appear in the output of readelf -s though? lto symbols are treated differently.
it's nothing to do with --as-needed, it's just llvm lto is not compatible with gcc lto.
despite the name "link time optimization", what lto actually does is deferred codegen, i.e., instead of generating machine code directly for each translation unit, it saves some form of compiler's internal IR to the object file. the final machine code is generated from the combined IR of multiple tranlation units, so more optmization passed can be applied.
cross language lto is only possible for the same codegen backend, i.e. all gcc, or all llvm. the cc crate builds C/C++ using the system default compiler, which is typically gcc for linux, and clang for apple.
rust uses llvm, it cannot consume gcc lto symbols, I guess that's also the reason why it worked on macos but not linux.
Thanks for this reply and taking the time, I didn't realise lto symbols would be treated differently and vary between backends. I'll brush up on some reading! It's helped explain an entire afternoon of confusion working on the rapidhash crate, thank you.