[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