When building a project using CMake and Make, you can execute make
from a subdirectory of your build tree (i.e. from a directory below whatever directory contains your top-level Makefile
), and make
will (as far as I can tell) build all targets at or below that directory. This is because CMake generates a Makefile
for every directory that contains targets, so when you're in a directory with targets, make
finds the Makefile
for building those targets.
When CMake generates Ninja files, however, it only generates one build.ninja
file, which is at the top level of the build tree. So calling ninja
from a directory other than the top-level directory fails (even the -f
option doesn't work because ninja
can't find the rules.ninja
file).
Is there any way to emulate the "make-like" behavior of building targets at and below a directory? As far as I can tell, there are no Ninja targets that correspond to "all targets at and below a particular directory." (This could be emulated using phony targets named after each directory that depend on all targets at and below that directory, but CMake does not generate such targets by default.)
ninja <DIR>/all
works with recent versions of Ninja (1.7.2). Version 1.3.4 does not allow this.I could not find a reference to this on the manual. However, CMake has this documented here:
Good question. I would like to know the answer if you find it. I am just in the process of transitioning to cmake+ninja myself.
I found that I could not create targets with the same name at different levels (if there is a way I would be interested to know). So I adopted a naming convention for different targets E.g.
name - builds program or library test.name - runs tests for the named program or library doxygen.name - build doxygen for the named program or library
For deeper hierarchies you can do something like:
doxygen.subproject doxygen.subproject.name
Using this pattern you can control precisely what is built but you have to issue the command from the top-level build directory. I think after I get used to this I will find it more productive as there is no need to change directory before you build or run something and though there is sometimes a little extra typing required the shell history generally has it covered.
This is implemented under the hood by using add_custom_target() and adding appropriate dependencies. I use a macro to do this automatically so that a macro "add_doxygen()" will add the doxygen target for the program and make the doxygen target at each higher level depend on it using add_dependencies().
This worked for me:
ninja -t targets all - lists all targets (including target type)
egrep "^${DIRECTORY}/" - filters list of targets to only include those in desired directory
egrep CXX_EXECUTABLE_LINKER - limits the targets to just C++ executables. You can remove or tweak this to get the set of targets you're interested in.
sed -e 's/:.*//g' - removes the target type e.g. ": CXX_EXECUTABLE_LINKER"
xargs ninja - invokes ninja to build the targets