[CMake] In add_subdirectory( binary_dir), binary_dir/ is just a decoy when there's no sub-target

Marc Herbert marc.herbert at gmail.com
Tue Jun 4 15:05:29 EDT 2019


tl;dr: should there be at least one target per CMakeLists.txt?

https://cmake.org/cmake/help/v3.14/command/add_subdirectory.html
> add_subdirectory(source_dir [binary_dir] )
> "The binary_dir specifies the directory in which to place the output
files. [...] If binary_dir is not specified, the value of source_dir,
before expanding any relative path, will be used (the typical usage)."

I found this part of the documentation to be correct ONLY when the
subdirectory defines and uses its own "sub-"target(s). If the subdirectory
refers to higher main targets instead then binary_dir/ is just a decoy: the
subdirectory build happens elsewhere. binary_dir is a decoy whether it's
explicit or default. It exists but there are only totally generic and
unused files there.

Example:

mainsrc/
├── CMakeLists.txt
├── inmodule
│   ├── CMakeLists.txt
│   ├── infile.c
└── mainfile.c


# mainsrc/CMakeLists.txt
add_executable(mainexe mainfile.c)
add_subdirectory(inmodule [ decoy_binary_dir ] )

# mainsrc/inmodule/CMakeLists.txt
target_sources(mainexe PRIVATE infile.c) # <= direct reference, no
sub-target


cmake -GNinja -B build -S mainsrc && ninja -C build

build
├── CMakeFiles
│   ├──
│   ├── mainexe.dir
│   │   ├──
│   │   ├──
│   │   ├── inmodule       <= ACTUAL binary_dir!
│   │   │   └── infile.c.o
│   │   ├── mainfile.c.o
│   │   ├──
│   │   :
│   ├──
│   :
├── inmodule       <= decoy with unused, boilerplate files and no reference
to any code
│   ├── CMakeFiles/
│   ├── cmake_install.cmake


The midly irritating part is that cmake complains about the lack of a
binary_dir argument if the module is an _out-of-tree_ subdirectory:

CMake Error at CMakeLists.txt:5 (add_subdirectory):
  add_subdirectory not given a binary directory but the given source
  directory "~/cmake-test/outmodule" is not a subdirectory of
  "~/cmake-test/maindir".  When specifying an out-of-tree source
  a binary directory must be explicitly specified.

That request makes sense of course except... when given that binary_dir
argument it requested, it's still becomes a decoy as described above.
This is the actual (and funny) binary_dir /in this out-of-tree case:
build
├── CMakeFiles
│   ├── mainexe.dir
│   │   └── home
│   │       └── joe
│   │           └── cmake-test
│   │               └── outmodule
│   │                   └── outfile.c.o



Reproduced with cmake version 3.14.4. No difference between make and ninja.

Researching the interwebs most people, tutorials and other documents seem
to assume (at least) one target per CMakeLists.txt. Should such a
recommendation be made more official to avoid the sort of confusion above?
Could this recommendation avoid other, unrelated problems I haven't
experienced? Yet?

Marc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20190604/1f594906/attachment.html>


More information about the CMake mailing list