Missing order-only dependencies cause samurai error
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.28)
project(ProjectName)
add_library(objectlib OBJECT /dev/null)
set_target_properties(objectlib PROPERTIES LINKER_LANGUAGE CXX)
add_library(lib empty.cc)
add_dependencies(lib objectlib)
$ echo > empty.cc
$ cmake -G Ninja .
[ ... ]
$ samu
samu: file is missing and not created by any action: 'CMakeFiles/objectlib.dir'
$ ls -l CMakeFiles/objectlib.dir
ls: cannot access 'CMakeFiles/objectlib.dir': No such file or directory
$ grep CMakeFiles/objectlib.dir build.ninja
build cmake_object_order_depends_target_objectlib: phony || CMakeFiles/objectlib.dir
$ rm -r CMakeCache.txt CMakeFiles
$ sed -i -e 's:/dev/null:empty.cc:' CMakeLists.txt
$ cmake -G Ninja .
[ ... ]
$ ls -al CMakeFiles/objectlib.dir
total 0
drwxr-xr-x 2 alex alex 40 Dec 20 17:15 .
drwxr-xr-x 7 alex alex 220 Dec 20 17:15 ..
$ samu
[1/3] Building CXX object CMakeFiles/lib.dir/empty.cc.o
[2/3] Building CXX object CMakeFiles/objectlib.dir/empty.cc.o
[3/3] Linking CXX static library liblib.a
$ cmake --version
cmake version 3.28.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).
$ samu --version
1.9
It appears that CMake skips creating object directories if no files are planned to be put there, but still adds an order-only dependency. The ninja documentation does not specify the behavior if order-only dependencies don't exist and can't be made; the reference implementation ignores it, but samurai issues an error. I would argue this is a bug in CMake, not samurai, for several reasons:
- The order-only dependency is actually built if a rule exists. "order-only" refers to the behavior when the dependency exists but is newer than the target, not the behavior when it doesn't exist.
- As far as I can tell, unbuildable order-only dependencies are useless.
- Order-only dependencies (probably) come from GNU make, which also issues an error:
$ cat Makefile
b: | a
$ make
make: *** No rule to make target 'a', needed by 'b'. Stop.
$ make --version
GNU Make 4.4.1
By my reckoning, CMake shouldn't emit order-only dependencies without a rule to create the dependency.