CMake generates suboptimal linker commands
I wanted to understand the extent to which CMake saves me from having to think about the entire dependency graph of my projects. In particular, it wasn't clear to me if the order in which I list libraries in target_link_libraries
influences the linker commands that CMake generates for GCC. So I created this minimal demo. The following image depicts the dependencies between the three targets, and states the names of the functions that they define and use (the implementations of the functions are irrelevant, and can be ignored).
The CMakeLists.txt file states Main's dependencies in topologically sorted order, with the statement:
target_link_libraries(Main PRIVATE BLib ALib)
This causes CMake to generate the expected linker command:
/usr/bin/c++ -rdynamic CMakeFiles/Main.dir/Main/Main.cpp.o -o Main libBLib.a libALib.a
But if Main's dependencies are swapped:
target_link_libraries(Main PRIVATE ALib BLib)
then CMake generates the suboptimal linker command:
/usr/bin/c++ -rdynamic CMakeFiles/Main.dir/Main/Main.cpp.o -o Main libALib.a libBLib.a libALib.a
I first noticed this in CMake 3.5.1. I then cloned and built the latest revision from the master branch (v. 3.13.20190104-ge7a88, revision e7a88ce4) and found that that revision behaves the same way.
I don't know if the extra time that the linker spends processing suboptimal commands like this could ever be significant enough on large projects for it to be worth changing this behaviour. But I was surprised to see that it does this, because the fact that it appends libALib.a
in the second case suggests that CMake is already topologically sorting the targets. So I would have expected it to internally use the topological ordering of the list ALib BLib
, and hence generate the same linker command as the first case. I realise that dependency repetition is necessary when a project has cyclic dependencies, but when the dependency graph is a DAG (as in the attached demo), wouldn't topologically sorting the dependencies always produce the same result as the current behaviour?