[CMake] acyclic subdirectory builds

Amitha Perera amitha-cmake at thepereras.org
Fri Apr 4 12:10:41 EDT 2008


Egon Kocjan wrote:
> I have a complicated situation :). I avoided the kind of approach, that 
> you suggest because it's not modular - main project file contains 
> add_subdirectory commands, which have to be maintained "by hand" - you 
> can see the non-modular information leak here: "add_subdirectory( liba )".

Perhaps we have different definitions of modular.  To me, the main 
CMakeLists.txt file doing nothing more than explicitly enumerating the 
nodes in your graph.  Presumably, that's easy to find, even 
automatically.  In fact, you can think of the add_subdirectory commands 
as the links of a tree-representation of your dependency graph.  The 
target_link_libraries specify the full dependencies *for a given node*. 
   It doesn't get more modular than that.

Instead of listing everything on a top level file, you could do 
add_subdirectory at lower levels.  The issue with this is that the 
add_subdirectory typically corresponds to the build order.  With visual 
studio, it doesn't matter as much, since the IDE will re-order things 
anyway.  Even with Makefiles, CMake is clever enough to put rules to 
make sure dependencies are built first.  However, it's bad practice; 
it's much better if the build order corresponds to a correct subtree of 
your full dependency graph.

That said, you could probably do what you did in your original email by 
using some cache variables to mark a directory as already processed. 
This may require CMake 2.6, since the reading and writing of cache 
variables occurs in different phases in CMake 2.4.

> It would be nice to double-click on any project 
> in the graph and have the build system figure out the needed 
> dependencies from "lower" levels automatically. The reason that I want 
> to have subgraph builds is that VS would probably break if I included 
> the whole beast at once :).

This is what I referred to in my post when I wrote about "self-standing 
sub-project solutions".  Since you are beginning this CMake adventure, I 
strongly suggest you begin at CMake 2.6.  It fixes many, many quirks of 
2.4.  If, for example, you did

exea/CMakeLists.txt
   project( exea )
   ...
   add_executable( exea .. )
   target_link_libraries( exea liba libb )
   ...

You would (also) have a solution called "exea.sln".  Opening this would 
get you exea, liba, libb, and all of liba's and lib's dependencies. 
Pretty modular, I think.

If exea depends exclusively on a library libc, then you could add

exea/CMakeLists.txt
   ...
   add_subdirectory( libc )
   ...

and "hide" libc from the other targets, maintaining your modularity. 
However, if both exea and exeb depend on libc, then I don't think it 
makes sense for each to pretend that libc is "hidden".  From an overall 
build perspective, I think it's better to list libc *one* somewhere 
(e.g. at the top level), and just refer to that in exea and exeb.

On a philosophical note, I think you'll find that once you approach the 
problem in the CMake way (as opposed to forcing CMake to do it exactly 
as it was done before), you'll find that it works just as well.

 > The task is to convert ~100 projects with acyclic (non-tree)
 > dependencies to cmake.

I'll repeat again that the target_link_libraries is really what captures 
this dependency graph.  add_subdirectories is simply an enumeration of 
the nodes.  Ideally, the execution order of the add_subdirectories 
matches one of the tree traversals of your dependency graph, but it 
doesn't have to.  And I strongly suggest that you start with CMake 2.6. 
  It is at a release candidate stage now, but the issues that are being 
fixed are pretty complex corner cases that will not affect you getting 
your build system using CMake.


Cheers,
Amitha.



More information about the CMake mailing list