ninja-build/ninja

Spurious error parsing depfiles: inputs may not also have inputs?

asutton opened this issue · 6 comments

I'm trying to get C++20 modules working with CMake/Ninja, for some definition of "working". I'm using GCC, CMake, and Ninja compiled from github (today). The compilation rule for a single file is this:

~/opt/bin/g++   -I../. -fmodules-ts -std=gnu++2a -MD -MT project/CMakeFiles/project-core.dir/core/module.cpp.o -MF project/CMakeFiles/project-core.dir/core/module.cpp.o.d -o project/CMakeFiles/project-core.dir/core/module.cpp.o -c ../project/core/module.cpp

Which produces the following .d file:

project/CMakeFiles/project-core.dir/core/module.cpp.o \
 gcm.cache/project.core.gcm: ../project/core/module.cpp \
 /usr/include/stdc-predef.h
project.core.c++m: gcm.cache/project.core.gcm
.PHONY: project.core.c++m
gcm.cache/project.core.gcm:| \
 project/CMakeFiles/project-core.dir/core/module.cpp.o

The error happens on the last line. The input is poisoned on the line above because gcm.cache/project.core.gcm is registered as an input for the phony project.core.c++m target. And apparently, there's some prohibition against inputs (dependencies) also appearing as outputs (targets), but apparently, not the reverse. Or at least maybe all outputs need to appear lexically before their appearance as inputs?

I'm also not sure why GCC is producing a secondary dependency for the gcm target. It might have something to do with building module interface partitions. I'm currently looking at GCC to see why it's producing these things and in this order.

I'd submit a PR disabling the error, but I'm pretty sure that's not the right solution. I don't know enough about the internals of ninja to propose a better resolution.

Do you think this is a different bug?

I have a module waarudo.details.std which imports the importable header "waarudo.details.std.headers.hpp".

When I compile the module without a dependency on the importable header, I do get

inputs may not also have inputs

But when I compile with parallelization, I get

error: failed to read compiled module: No such file or directory

because the module builds in parallel with the importable header, even though I have set the build dependency in CMake (even with -j1 because the module compiles before the importable header).
Then, when I attempt to recompile (note that the importable header successfully compiled in parallel in the first attempt), I then get:

ninja: error: dependency cycle: CMakeFiles/waarudo.details.std.headers.dir/waarudo.details.std.headers.hpp.o -> /home/johel/Documents/C++/Repos/Waarudo-builds/gcc-trunk-Release/JEGPModules/waarudo.details.std.headers.gcm -> CMakeFiles/waarudo.details.std.headers.dir/waarudo.details.std.headers.hpp.o

even though GCC doesn't generate an object file for an importable header.

FYI, -fdeps-format=p1689r5 will suppress this extra information.

I'm also not sure why GCC is producing a secondary dependency for the gcm target.

It has to do with Nathan's GNU make work to support modules. See this paper: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1602r0.pdf

FYI, -fdeps-format=p1689r5 will suppress this extra information.

This is useful, but really a proper fix. Things like this should work out of the box with default values

I am also disappointed at the depfiles being more Make syntax by default as well (I believe I expressed this to Nathan at the time in 2019, but it had already been merged by then).