Skip to content

Emit a depfile for -MMD, not only for -MD - #33

Open
dkulp wants to merge 1 commit into
VKCOM:masterfrom
FalconChristmas:fix-mmd-depfile
Open

Emit a depfile for -MMD, not only for -MD#33
dkulp wants to merge 1 commit into
VKCOM:masterfrom
FalconChristmas:fix-mmd-depfile

Conversation

@dkulp

@dkulp dkulp commented Aug 19, 2026

Copy link
Copy Markdown

The bug

func (deps *DepCmdFlags) ShouldGenerateDepFile() bool {
	return deps.flagMD || deps.flagMF != ""
}

An invocation carrying only -MMD produces no .d file at all.

-MMD is not a modifier on -MD; the two are alternatives that differ only in whether system headers are listed, and both emit a dependency file as a side effect of compilation. nocc strips -MMD off cxxArgs along with the rest of the dep flags and generates the file itself on the client, so when this predicate is false nothing generates it — neither nocc nor the compiler on the server.

Why it goes unnoticed

-MMD -MP with no -MF is the usual hand-written-Makefile spelling, as opposed to the -MD -MT ... -MF ... that CMake emits. Such a project built through nocc silently ends up with zero .d files and no header dependency tracking: editing a header rebuilds nothing.

The failure is invisible, because a missing .d is not an error to make — the -include of the dep files just matches nothing.

Why the existing tests did not catch it

Every case in tests/depfiles_test.go also passes -MD, including the two that pass -MMD (Test_MDMTMFMPMMD, Test_MQMQMQMQMMP, Test_MTMTMTMTMMP). So flagMD was always true and the predicate was never exercised with -MMD on its own.

Test

Two cases added in the same style as the rest of the file, comparing contents against real g++ output:

func Test_MMDMP(t *testing.T) {
	var cmdLineStr = "g++ -MMD -MP -o dt/dep1/1.cpp.o -c dt/dep1/1.cpp"
	...
}

func Test_MMDOnly(t *testing.T) {
	var cmdLineStr = "g++ -MMD -o dt/dep1/1.cpp.o -c dt/dep1/1.cpp"
	...
}

Both fail against current master with:

Error parsing dt/dep1/1.cpp.d after nocc: open dt/dep1/1.cpp.d: no such file or directory

and pass with this change. The rest of the suite is unaffected — same results as master on my machine.

The system-header filtering that -MMD asks for was already implemented in calcDepListFromHFiles and keys off flagMMD, so it applies as soon as the file is generated.

ShouldGenerateDepFile() tested flagMD || flagMF, so an invocation carrying only
-MMD produced no .d file at all.

-MMD is not a modifier on -MD; the two are alternatives that differ only in
whether system headers are listed, and both emit a dependency file as a side
effect of compilation. nocc strips -MMD off cxxArgs along with the rest of the
dep flags and generates the file itself on the client, so when this predicate is
false nothing generates it -- neither nocc nor the compiler on the server.

"-MMD -MP" with no -MF is the usual hand-written-Makefile spelling (as opposed
to the "-MD -MT ... -MF ..." that CMake emits), so such a project built through
nocc silently ends up with zero .d files and no header dependency tracking:
editing a header rebuilds nothing. The failure is invisible, because a missing
.d is not an error to make -- the -include of the dep files just matches
nothing.

Every existing case in tests/depfiles_test.go passes -MD as well, including the
two that also pass -MMD, so the predicate was never exercised with -MMD on its
own. Add the two cases that were missing; both fail against the current code
with "Error parsing dt/dep1/1.cpp.d after nocc: no such file or directory" and
pass with this change, comparing contents against real g++ output as the rest of
the file does.

The system-header filtering that -MMD asks for was already implemented in
calcDepListFromHFiles and keys off flagMMD, so it applies as soon as the file is
generated.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Copilot AI lite review requested due to automatic review settings August 19, 2026 20:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a bug in nocc’s depfile generation logic where passing -MMD (without -MD or -MF) would result in no dependency file being produced, because nocc strips dep flags from the remote compile and relies on the client-side generator.

Changes:

  • Treat -MMD as a depfile-emitting flag in ShouldGenerateDepFile() (same as -MD).
  • Add test coverage for -MMD-only and -MMD -MP command lines, comparing nocc output to real g++ output.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
internal/client/dep-cmd-flags.go Fixes the depfile-generation predicate to include -MMD.
tests/depfiles_test.go Adds regression tests ensuring depfiles are emitted for -MMD without -MD / -MF.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants