Here’s a minimal example that demonstrates how a static library may get included twice on the linker line. It took much trial and error to distil down a much more complex system to this example.
Is this by design? Is there a simple way to avoid duplication without reversing the order? More importantly, is there a simple way to determine where the duplication came from (in a large CMake-based project) and what specifically needs to be reordered?
On many platforms, linkers do not re-scan static libraries from earlier on the link line to satisfy symbol dependencies of those later on the link line. target_link_libraries(two PRIVATE one) says that two’s symbols may depend on symbols from one. In order to satisfy this, CMake ensures that one appears on the link line after two. However, you also told CMake that main needs to link to one and then two. We always preserve the direct link dependencies in order, and then add transitive dependencies afterward. The only way to satisfy both requirements is to generate one two one on the link line.
IIRC, Apple’s linker does re-scan static libraries, so repeating them is not needed to satisfy dependencies. This is similar to how linkers treat shared libraries, which we do de-duplicate. That code could be updated to de-duplicate static libraries too when using the Apple linker.
This would be useful. I am encountering a situation where the duplicate library is -lc++, which is implicit, and I can’t seem to figure out any reordering of CMake commands that helps.