Search code examples
performancecmakecompilationlinkerlibraries

avoid blocking by transitive dependencies when using cmake


I am building a cmake project with several transitive dependencies. E.g., say I have executable ex1 which dependends on lib1. lib1 requires lib2. This could be visualized as such: (ex1 -> lib1 -> lib2).

Hitherto I linked them publicly to express said dependencies. So the CMakeLists.txt for lib2 would have a line:

target_link_libraries(lib1 PUBLIC lib2)
target_link_libraries(ex1 PUBLIC lib1)

Thus lib1 has all includes form ex1 and lib1 all those from lib2. Linking order is ok etc. The problem with this approach is, that cmake waits until requirements are built before it proceeds. I.e. in the above example (ex1 -> lib1 -> lib2), I wait for lib1 until lib2 is built and ex1 build is not started until lib1 is built.

lib1 in this case is a library, not an executable. Though I need some information about linking order and lib1 needs lib2's include directories, it is not necessary for lib1 to wait until lib2 is compiled and linked. ex1 needs lib1 and lib2 when linking, but as long as there are no shenanigans in the source code, it is not necessary for ex1 to wait for the lib1 build to finish to start compiling and lib1 to wait for the lib2 build to finish before compiling.

The motivation behind this is, that a few source files take much longer to compile than the rest. I have access to a compile cluster and would like to task it to capacity to reduce built times. When those single-file-compilations take a long time, the compile cluster is basically compiling a single file on a single thread while it could proceed with the other hundreds of files.

Is there a straight forward way to achieve this in cmake?


Solution

  • @fabian is correct. The default generator on linux is Make. Ninja, for example, handles dependencies differently and leads to a significant speedup in my case.