CMake's add_custom_command ninja doesnt trigger rebuild of library

Skip to first unread message


Dec 16, 2020, 3:43:03 AM12/16/20
to ninja-build


Iam using CMake together with ninja to build a library. The library is depending on some code which may be generated before-hand by a custom command. The source for this code is within the source-tree and it must stay there, I have no freedom here.

Here's my CMake code:

add_library(some_lib some_source.c)

#some_source.c may be modified by the following custom command


    COMMAND codegen.exe -i some_input.xml

    COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/generated"

    OUTPUT  ${CMAKE_BINARY_DIR}/generated

    DEPENDS some_input.xml


    COMMENT "Generating code ..."


add_custom_target(generate_something DEPENDS ${CMAKE_BINARY_DIR}/generated)

add_dependencies(some_lib generate_something)

Now if some_input.xml is changed I want to also rebuild some_lib. However in practice this code doesnt seem to work, the command is executed but after it is executed some_lib is not beeing rebuild, though the timestamps of the output files (some_source.c) of the custom command are newer than the library. Here's the output I get:

[1/7] Generating error handler code ...


So according to ninjas output there is more todo than just generating the code, however its not beeing executed.

Can someone give me a hint on what am I doing wrong or how I can achieve this? Or is there a problem with CMake and ninja?

Thanks in advance, if you need more information please let me know.


Claus Klein

Dec 16, 2020, 4:34:08 AM12/16/20
to skreyer, ninja-build
Hi Steve,

do it simple and clean, than it will work well:

cmake_minimum_required(VERSION 3.13...3.15)

project(test LANGUAGES C)

# some_source.c may be modified by the following custom command
    COMMAND touch ${CMAKE_BINARY_DIR}/generated/some_source.c
    OUTPUT  ${CMAKE_BINARY_DIR}/generated/some_source.c
    DEPENDS some_input.xml
    COMMENT "Generating code ..."

# the lib depens on xml via generated output from custom command
add_library(some_lib lib_source.c ${CMAKE_BINARY_DIR}/generated/some_source.c)

clausklein$ ninja -d explain -nv
ninja explain: restat of output generated/some_source.c older than most recent input ../some_input.xml (1608110646819070000 vs 1608110680774509000)
ninja explain: generated/some_source.c is dirty
ninja explain: generated/some_source.c is dirty
ninja explain: CMakeFiles/some_lib.dir/generated/some_source.c.o is dirty
ninja explain: libsome_lib.a is dirty
[1/3] cd /Users/clausklein/tmp/build && touch /Users/clausklein/tmp/build/generated/some_source.c
[2/3] /Applications/   -isysroot /Applications/ -MD -MT CMakeFiles/some_lib.dir/generated/some_source.c.o -MF CMakeFiles/some_lib.dir/generated/some_source.c.o.d -o CMakeFiles/some_lib.dir/generated/some_source.c.o -c generated/some_source.c
[3/3] : && /usr/local/Cellar/cmake/3.19.1/bin/cmake -E rm -f libsome_lib.a && /Applications/ qc libsome_lib.a  CMakeFiles/some_lib.dir/lib_source.c.o CMakeFiles/some_lib.dir/generated/some_source.c.o && /Applications/ libsome_lib.a && /usr/local/Cellar/cmake/3.19.1/bin/cmake -E touch libsome_lib.a && :


You received this message because you are subscribed to the Google Groups "ninja-build" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
To view this discussion on the web visit


Dec 18, 2020, 7:12:36 AM12/18/20
to, ninja-build
Hi Claus,

thanks for your answer. The problem with simple and clean is that this principle neglects the usage spec of my generator tool. The generator tool gets a whole directory where it will store its output artefacts as a parameter, not single files. Also this directory has to be in the source tree not in the binary tree. Thus, I would need to specify the directory in the binary tree and then afterwards copy its files into the source tree, which again isn't simple anymore.

But I found now what the problem what I forgot. I figured that the generator tool was not only modifying some_source.c but also some_source1.c which I forgot to specify as a BYPRODUCT. After specifying all potentially touched sources as BYPRODUCTS everything worked as expected.

The hint with "-d explain"-parameter is very good to know. Thanks much for this.

Kind regards, Steve
Reply all
Reply to author
0 new messages