Berthold Heisterkamp
Berthold Heisterkamp

Reputation: 21

CMake - Make whole subtree depending on another target?

Consider a Project-layout like this:

CMakeLists.txt
  |
  |------/Project1
  |        |
  |        |-----CMakeLists.txt
  |        |
  |        |-----/Project1.lib1  //needs Project3.lib1
  |        |        |
  |        |        |-----CMakeLists.txt
  |        |        |-----lib1.cpp
  |        |
  |        |-----/Project1.lib2  //needs Project3.lib1
  |        |-----/Project1.lib3
  |        |-----...
  |        |-----/Project1.libn  //some need Project3.lib1
  |
  |------/Project2  //Totally independent
  |        |
  |        |-----/Project2.lib1
  |        |-----/Project2.lib2
  |
  |------/Project3
           |
           |-----/Project3.lib1

Of course, all subdirectories have CMakeLists.txt and code-files. And each CMakeLists.txt grabs all its corresponding subdirectories with add_subdirectory.

Each ProjectX.libY's CMakeLists has an add_library(name srcs) and some of them depend on Project3.lib1 . Unfortunately Project1 is very volatile and big and things change fast. There are plenty of sub-projects there and I am afraid that someone might forget to keep the dependencies to Project3 up-to-date. And it will be quite painfull to have a thousand add_dependencies(Project1.libY Project3.lib1) spread all over Project1. Especially when it comes to Multicore (make -j8) a correct dependency-tree is essential. Otherwise we could run into sporadic Problems that Project1.libY drops out because Project3 is not built yet, though needed. So what I would like to do is tell CMAKE to not even dive into Project1-Folder as long as Project3 is not built/updated yet. Something like

//Project1/CMakeLists.txt
#...
Project (Project1)
add_dependencies (Project1 Project3)
# or add_dependencies (Project1 Project3.lib1)
#...

You guys have any clue for me how to achieve that ?

Thanx a lot!

Upvotes: 2

Views: 700

Answers (1)

ComicSansMS
ComicSansMS

Reputation: 54609

First of all: Prefer target_link_libraries over add_dependencies whenever possible. Especially when expressing dependencies between libraries, it is almost always the better tool. Only resort to add_dependencies if you have good reasons to do so (eg. the target that you depend on not producing any trackable build artifacts of its own).

I know that this situation triggers a DRY reflex in most programmers, but keep in mind that build system code has different trade-offs than normal code. Being more explicit often increases maintainability of the overall system, even if it means repeating stuff a lot in your build scripts.

Also keep in mind that CMake is really designed to use targets as the fundamental concept of organizing your build. Determining dependencies from the physical layout of your build tree is therefore something that will likely cause severe headaches in the long run if you are not careful. So even if you are absolutely certain that you want to get rid of having to write out the dependency repeatedly, doing so based on the directory where the target was defined might not be the best approach.

All that being said, if you are still convinced that what you want to do is really the right solution for your project, link_libraries does exactly this.

As a final warning, I leave you with a quote from the manual for link_libraries:

Note: The target_link_libraries() command should be preferred whenever possible. Library dependencies are chained automatically, so directory-wide specification of link libraries is rarely needed.

You mentioned in your example that not all of the Project1.libNs do really carry a dependency on the Project3. This is a clear indication that you should model the dependencies explicitly on a per-target basis. As you said yourself, it is vital that the dependency tree reflects the actual dependencies of the project. The only way to ensure this is to write everything out correctly and make sure that your devs also understand how to do this.

Upvotes: 2

Related Questions