Ninja/Makefiles: Inconsistent behavior on first-build when add_custom_command OUTPUT exists
Unix Makefiles vs. Ninja build difference for add_custom_command (should Ninja respect OUTPUT param on first build)
I use the add_custom_command
/add_custom_target
combo to provide a target which can selectively generate content (in the source tree).
For example, I have a protobuf (foo.proto) file (in source) and I would like to generate an output stub (foo.c, also in source) if foo.c does NOT exist OR foo.proto changes.
This works as I would expect with the Unix Makefiles
. However, Ninja
always runs the custom target on a clean build (no entry for this target in the .ninja_log).
Questions:
- Can these two generators behave the same for a clean build?
- If so, which is correct?
Here is a simplified reproducer for Linux. FWIW, the described functionality is the same on Windows/Linux for Ninja.
source tree:
foo_src/
├── CMakeLists.txt
└── foo
CMakeLists.txt file:
cmake_minimum_required(VERSION 3.20)
project(test)
# Custom command to create/update the file 'foo'
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/foo
COMMAND echo "blah" >> ${CMAKE_CURRENT_SOURCE_DIR}/foo
COMMENT "Running a custom command"
)
# Custom target depends on the OUTPUT file 'foo' from the custom command
add_custom_target(gen_foo DEPENDS foo)
Build the gen_foo target with Unix Makefiles
From a clean build dir, the following build sees gen_foo as already built and the source file 'foo' is not updated
└──> cmake ../foo_src/ -G 'Unix Makefiles' && make gen_foo
-- The C compiler identification is GNU 10.3.0
-- The CXX compiler identification is GNU 10.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/lib/ccache/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/lib/ccache/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/foo_build
[100%] Built target gen_foo
Build the gen_foo target with Ninja
From a clean build dir, the following build runs the gen_foo target and updates the source file 'foo'
└──> cmake ../foo_src/ -G Ninja && ninja gen_foo
-- The C compiler identification is GNU 10.3.0
-- The CXX compiler identification is GNU 10.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/lib/ccache/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/lib/ccache/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/foo_build
[1/1] Running a custom command