CMake: how best to build multiple (optional) subprojects?

John Zwinck picture John Zwinck · Jun 23, 2011 · Viewed 10k times · Source

Imagine an overall project with several components:

  • basic
  • io
  • web
  • app-a
  • app-b
  • app-c

Now, let's say web depends on io which depends on basic, and all those things are in one repo and have a CMakeLists.txt to build them as shared libraries.

How should I set things up so that I can build the three apps, if each of them is optional and may not be present at build time?

One idea is to have an empty "apps" directory in the main repo and we can clone whichever app repos we want into that. Our main CMakeLists.txt file can use GLOB to find all the app directories and build them (not knowing in advance how many there will be). Issues with this approach include:

  • Apparently CMake doesn't re-glob when you just say make, so if you add a new app you must run cmake again.
  • It imposes a specific structure on the person doing the build.
  • It's not obvious how one could make two clones of a single app and build them both separately against the same library build.

The general concept is like a traditional recursive CMake project, but where the lower-level modules don't necessarily know in advance which higher-level ones will be using them. Yet, I don't want to require the user to install the lower-level libraries in a fixed location (e.g. /usr/local/lib). I do however want a single invocation of make to notice changed dependencies across the entire project, so that if I'm building an app but have changed one of the low-level libraries, everything will recompile appropriately.

Answer

trenki picture trenki · Nov 15, 2011

My first thought was to use the CMake import/export target feature.

Have a CMakeLists.txt for basic, io and web and one CMakeLists.txt that references those. You could then use the CMake export feature to export those targets and the application projects could then import the CMake targets.

When you build the library project first the application projects should be able to find the compiled libraries automatically (without the libraries having to be installed to /usr/local/lib) otherwise one can always set up the proper CMake variable to indicate the correct directory.

When doing it this way a make in the application project won't do a make in the library project, you would have to take care of this yourself.