[CMake] How to add dependency relations between libs and executable

Chuck Atkins chuck.atkins at kitware.com
Tue Apr 19 13:56:34 EDT 2016


> cmake, the old top layer project is proj_a, which at the same layer with
> proj_b and proj_c, if I add an extra top layer as the root you mentioned,

the generated make file structure will be changed, top layer make file

will be root instead of proj_a.
>
> Is there any way to add the dependency at proj_a level?
>

If you want proj_a, proj_b, and proj_c to all be built by the same make
command, then it makes sense to have a top level organization that
encompasses them all.  Also, if proj_a, proj_b and proj_c don't make sense
on their own and only when paired with each-other, then I would take the
"project(...)" command out of each of them and only leave the top level.
Basically, anything that has a project(...) command can be configured and
built all on it's own without the rest of the tree.  In this case, it may
make sense to keep b and c as independent projects but a as not since it
needs b and c.  So for example, similar to Anatoly's example:

*folder*
CMakeLists.txt:
project(root)
add_subdirectory(proj_b)
add_subdirectory(proj_c)
add_subdirectory(proj_a)

*folder/proj_a*
CMakeLists.txt:
add_executable(*A *main.cpp)
target_link_libraries(*A B C*)

*folder/proj_b*
CMakeLists.txt:
project(proj_b)
add_library(B proj_b.cpp)

*folder/proj_c*
CMakeLists.txt:
project(proj_c)
add_library(*C *proj_c.cpp)


With this structure, you can configure and build just project b or c:

$ mkdir build_c
$ cd build_c
$ cmake /path/to/folder/proj_c
...
$ make
...

You end up with libC.a .  Similarly, you could do that for proj_b and get
libB.a.  Or, if you configure the top level project instead:

$ mkdir build_all
$ cd build_all
$ cmake /path/to/folder
...
$ make
Scanning dependencies of target B
[ 16%] Building CXX object proj_b/CMakeFiles/B.dir/proj_b.o
[ 33%] Linking CXX static library libB.a
[ 33%] Built target B
Scanning dependencies of target C
[ 50%] Building CXX object proj_c/CMakeFiles/C.dir/proj_c.o
[ 66%] Linking CXX static library libC.a
[ 66%] Built target C
Scanning dependencies of target A
[ 83%] Building CXX object proj_a/CMakeFiles/A.dir/main.o
[100%] Linking CXX executable A
[100%] Built target A
$

You end up with proj_b/libB.a, proj_c/libC.a, and proj_a/A which is linked
with libB.a and libC.a.  You can also do a parallel make with make
-j(whatever) adn the generated dependencies will make sure that targets and
individual files are built in the right order.  Technically speaking, you
don't *need* to have a CMakeLists.txt at each level and you could put it
all in to one top level CMakeLists.txt but it's generally considered poor
CMake code to do so.  A good rule of thumb is to have a CMakeLsits.txt file
at each level that a target (i.e. a library or executable) is built and a
top level CMakeLists.txt to tie it all together.  This is the same sort of
approach you see with autoconf where it's typical to have a Makefile.am at
each level.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20160419/65290eb6/attachment-0001.html>


More information about the CMake mailing list