[CMake] Ninja generator emits order-only dependencies for custom commands

melak47 melak47 at posteo.net
Fri Sep 27 23:24:45 EDT 2019


I'm using add_custom_command with the Ninja generator on Windows to
invoke mc.exe on an .mc file,
to generate an .rc file, to create a resource DLL.
The full example is here:
https://gist.github.com/melak47/f7d83046c6d57b338d633468d078f5b1

The problem is, changing the .mc file and rebuilding only causes mc.exe
to rerun,
anything depending on the generated .rc file is not rebuilt.
I think this happens because cmake generates some order-only
dependencies for the generated files.

Some of the relevant build statements that are generated:


#
=============================================================================
# Object build statements for MODULE_LIBRARY target example


#############################################
# Order-only phony target for example

build cmake_object_order_depends_target_example: phony || example.hpp
example.rc example_MSG00001.bin

build CMakeFiles\example.dir\example.rc.res: RC_COMPILER__example
D$:\repro\build\example.rc || cmake_object_order_depends_target_example
  DEFINES = -Dexample_EXPORTS
  DEP_FILE = CMakeFiles\example.dir\example.rc.res.d
  FLAGS = -DWIN32 -D_DEBUG
  OBJECT_DIR = CMakeFiles\example.dir
  OBJECT_FILE_DIR = CMakeFiles\example.dir
  TARGET_COMPILE_PDB = CMakeFiles\example.dir\
  TARGET_PDB = example.pdb


#
=============================================================================
# Link build statements for MODULE_LIBRARY target example


#############################################
# Link the shared module example.dll

build example.dll: CXX_MODULE_LIBRARY_LINKER__example
CMakeFiles\example.dir\example.rc.res
  LANGUAGE_COMPILE_FLAGS = /DWIN32 /D_WINDOWS /GR /EHsc /Zi /Ob0 /Od
/RTC1 -MDd
  LINK_FLAGS = /machine:x64 /debug /INCREMENTAL  /noentry
  LINK_LIBRARIES = kernel32.lib user32.lib gdi32.lib winspool.lib
shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
  OBJECT_DIR = CMakeFiles\example.dir
  POST_BUILD = cd .
  PRE_LINK = cd .
  TARGET_COMPILE_PDB = CMakeFiles\example.dir\
  TARGET_FILE = example.dll
  TARGET_IMPLIB = example.lib
  TARGET_PDB = example.pdb


#############################################
# Custom command for example.rc

build example.rc example.hpp example_MSG00001.bin: CUSTOM_COMMAND
..\example.mc
  COMMAND = cmd.exe /C "cd /D D:\repro\build && "C:\Program Files
(x86)\Windows Kits\10\bin\10.0.18362.0\x64\mc.exe" -b -e hpp -h
D:/repro/build -r D:/repro/build D:/repro/example.mc"
  DESC = Generating example.rc, example.hpp, example_MSG00001.bin
  restat = 1


#############################################
# Assume dependencies for generated source file.

build D$:\repro\build\example.rc: CUSTOM_COMMAND ||
cmake_object_order_depends_target_example
  COMMAND = cmd.exe /c
  restat = 1


As you can see, CMakeFiles\example.dir\example.rc.res depends on
D$:\repro\build\example.rc,
which depends on the actual example.rc through
cmake_object_order_depends_target_example as
an **order-only** dependency.
If I read the ninja manual correctly, this means changes to example.rc
will by design not cause depndees to be rebuilt.

If instead of an empty CUSTOM_COMMAND, cmake emitted a phony like:

build D$:\repro\build\example.rc: phony example.rc

example.rc.res and example.dll would be properly rebuilt.
(Also, a phony does not appear in the build log, unlike the empty
CUSTOM_COMMAND which just shows up as 'cmd /c')

Is this a bug, or is there some intent behind emitting a CUSTOM_COMMAND
here?


More information about the CMake mailing list