[CMake] CMake for many interdependent libraries/executables

Wiser, Tyson TWiser at logostech.net
Wed May 23 12:52:40 EDT 2012


We currently have a fair number of libraries, executables and external
dependencies with fairly complicated dependencies.  As a simplified example,
consider the following diagram where dependencies flow from top to bottom (i.e.
higher depends on lower).

    exe1                 exe2
    | | \               /|  |
    | |  \             / |  |
    | |   \           /  |  |
    | |    \         /   |  |
    | |     \    libd    |  |
    | |      \   |  \    |  |
    | |       \  |   \   |  |
    | |       |  |    \  |  |
    | |       |  |     \ |  |
    | libc    |  |    libb  |
    |     \   |  |   /   |  |
    |      \  |  |  /    |  |
    |       \ |  | /     |  |
    |        \|  |/      |  |
    |         liba       |  |
    |        /           |  |
    |       /            |  |
     \     /             |  |
      \   /              |  |
      ext1               ext2

We don't modify external dependencies, but we do need to check them out and
build them before building a library or executable that depends on them.
Sometimes a developer will be working in a single library or executable.
Sometimes he will be working in multiple libraries and/or executables.  You can
imagine that for a new developer it becomes very complicated to know which
libraries and executables need to be checked out and in which order they need
to be built in order to satisfy all the dependencies.  Even established
developers that have all the necessary dependencies checked out and modify a
library have trouble knowing which libraries need to be rebuilt, and in what
order, for the change to propagate up to an executable.

In my ideal world, given that we can't change the dependency graph, I would
have a build system set up so that if I wanted to work on libb, I could simply
check it out and build it and it would automatically check out and build liba,
ext1, and ext2.  Then if I made changes to liba, building libb would notice the
change in liba and trigger that build first.  If I then decided that I needed
to work on exe2 I could check it out and build it and it would checkout and
build libd but use the existing libb, liba, ext1, and ext2 (triggering builds
as necessary if they are changed).  To further complicate the situation, we
need to build on both Linux and Windows.  So far we have been manually
maintaining makefiles on Linux and Visual Studio projects on Windows.

Phrased another way, I would like our build system to be able to:
1) Manage makefiles and Visual Studio solution/project files for us.
2) For a given library/executable, checkout and build missing dependencies.
3) For a given library/executable, build dependencies that have changed.
4) For a given executable, relink with changed dependent libraries (i.e. I
   change libb and build it and then build exe2, which relinks with libb).
5) When building a given library/executable for the first time, use existing
   dependencies within a given workspace (directory structure).

I have been investigation alternatives to our current system and CMake so far
seems to be the most promising.  I have never used CMake before, however, so I
am not entirely sure that I can make it match my ideal world, though I think it
can.  My current thoughts on how to accomplish this follow.

I know that CMake can handily manage #1.

I think that, given a directory structure similar to the following and setting
{TMP|STAMP|SOURCE|BINARY}_DIR appropriately, the ExternalProject module can
handle #2, #3 and #5.
  workspace-folder
    src
      exe2
      ext1
      ext2
      liba
      libb
      libd
    build
      exe2
      ext1
      ext2
      liba
      libb
      libd
    stamp
      exe2
      ext1
      ext2
      liba
      libb
      libd
    tmp
      exe2
      ext1
      ext2
      liba
      libb
      libd

I think that a "add_library(x UNKOWN IMPORTED)" and "set_property(TARGET x
PROPERTY IMPORTED_LOCATION y)" combination can handle #4.

Does this seem reasonable?  Is there a better way of doing it?  Would
maintaining the ExternalProject "superbuild" CMakeLists.txt files separately
from the regular CMakeLists.txt files be the recommended approach?

Thanks in advance for any help.


More information about the CMake mailing list