Re: Question/Proposal: Incomplete debug graph output when using -o (--old-file)
WaitronCharm <[email protected]> Thu, 25 Jun 2026 12:35:14 +0000
| Newsgroups | gmane.comp.gnu.make.bugs |
|---|---|
| Message-ID | <YrplvZLfHIpyNlLSexdz5KTKoLICGCxrU46JeU-caiRb9XuPe4H3mffI1BgWiVCUW4qxTkG4JA5zkx5zeaKgjc0n6Na_6j_8dMiRtH_uNEE=@proton.me> |
Some illustrations to the different scenarios:
# Initial run, graph complete, node statuses according to the file system
$ make -f -
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
> t3
set -C; > t2
> t1
$ ls -l
total 0
-rw-r--r-- 1 ... 0 Jun 25 13:48 t1
-rw-r--r-- 1 ... 0 Jun 25 13:48 t2
-rw-r--r-- 1 ... 0 Jun 25 13:48 t3
$ make -d -n -f - | make2graph -d color=3Dred
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
digraph G {
n2 [label=3D"t1"];
n3 [label=3D"t2"];
n4 [label=3D"t3"];
n3 -> n2 ;
n4 -> n3 ;
}
# Independent prerequisite 't3' updated, graph complete, node statuses acco=
rding to the file system
$ touch t3
$ make -f -
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
set -C; > t2
/bin/sh: line 1: t2: cannot overwrite existing file
$ make -d -n -f - | make2graph -d color=3Dred
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
digraph G {
n2 [label=3D"t1", color=3Dred];
n3 [label=3D"t2", color=3Dred];
n4 [label=3D"t3"];
n3 -> n2 ;
n4 -> n3 ;
}
# Forcing status of 't2' with option '-o', node statuses as aimed but graph=
incomplete
$ make -f - -o t2
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
make: 't1' is up to date.
$ make -d -n -f - -o t2 | make2graph -d color=3Dred
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
digraph G {
n2 [label=3D"t1"];
n3 [label=3D"t2"];
n3 -> n2 ;
}
# Forcing status of 't2' with option '-W', re-make of 't3' correct, node st=
atuses not as aimed but graph complete
$ make -f - -W t2
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
> t1
$ ls -l
total 0
-rw-r--r-- 1 ... 0 Jun 25 13:57 t1
-rw-r--r-- 1 ... 0 Jun 25 13:48 t2
-rw-r--r-- 1 ... 0 Jun 25 13:53 t3
$ make -d -n -f - -W t2 | make2graph -d color=3Dred
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
digraph G {
n2 [label=3D"t1", color=3Dred];
n3 [label=3D"t2"];
n4 [label=3D"t3"];
n3 -> n2 ;
n4 -> n3 ;
}
# Forcing status of 't2' with option '-W', re-make of 't3' unnecessary, nod=
e statuses not as aimed but graph complete
$ make -f - -W t2
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
> t1
$ ls -l
total 0
-rw-r--r-- 1 ... 0 Jun 25 13:58 t1
-rw-r--r-- 1 ... 0 Jun 25 13:48 t2
-rw-r--r-- 1 ... 0 Jun 25 13:53 t3
$ make -d -n -f - -W t2 | make2graph -d color=3Dred
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
digraph G {
n2 [label=3D"t1", color=3Dred];
n3 [label=3D"t2"];
n4 [label=3D"t3"];
n3 -> n2 ;
n4 -> n3 ;
}
# Forcing status of 't2' with the theoretical option '--just-enough-up-to-d=
ate', node statuses as aimed, graph complete
$ cp -p t2 t2.bak
$ ls -l
total 0
-rw-r--r-- 1 ... 0 Jun 25 13:58 t1
-rw-r--r-- 1 ... 0 Jun 25 13:48 t2
-rw-r--r-- 1 ... 0 Jun 25 13:48 t2.bak
-rw-r--r-- 1 ... 0 Jun 25 13:53 t3
$ touch -r t3 t2=09# =3D make ... --just-enough-up-to-date t2
$ ls -l
total 0
-rw-r--r-- 1 ... 0 Jun 25 13:58 t1
-rw-r--r-- 1 ... 0 Jun 25 13:53 t2
-rw-r--r-- 1 ... 0 Jun 25 13:48 t2.bak
-rw-r--r-- 1 ... 0 Jun 25 13:53 t3
$ make -f -=09# =3D make ... --just-enough-up-to-date t2
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
make: 't1' is up to date.
$ make -d -n -f - | make2graph -d color=3Dred=09# =3D make ... --just-enoug=
h-up-to-date t2
.POSIX:
t1: t2; > $@
t2: t3; set -C; > $@
t3:; > $@
digraph G {
n2 [label=3D"t1"];
n3 [label=3D"t2"];
n4 [label=3D"t3"];
n3 -> n2 ;
n4 -> n3 ;
}
On Tuesday, June 23rd, 2026 at 7:36 PM, WaitronCharm <[email protected]=
e> wrote:
> Hello everyone
>=20
> I've spent some time digging into 'src/remake.c' to better understand how=
this behaves and wanted to share my findings, along with a potential logic=
change I am considering.
>=20
> To clarify the exact case driving this:
>=20
> 1. I have a specific target that can no longer be remade because it relie=
s on a web resource that is not available anymore.
> 2. However, it has other local prerequisites that still get updated regul=
arly. These updates would normally trigger a remake of this target and woul=
d not succeed in any meaningful way.
> 3. I would need to keep these prerequisites in a dependency graph (which =
I capture via 'makefile2graph').
> 4. Other higher targets rely on this outdated but locally still fine targ=
et. They can be updated at any time, but I don't want them constantly and e=
ndlessly rebuilding on every single make run.
>=20
> As noted before, using '-o' keeps the status clean but prunes the prerequ=
isites from the graph entirely. Conversely, '-W' (which I haven't tried but=
assume) would preserve the graph but constantly force higher rebuilds. I a=
lso cannot simply touch the target with a custom timestamp because its real=
modification date must remain strictly bound to its last effective, succes=
sful remake.
>=20
> This led me to the conclusion -- which might be wrong -- that make could =
internally fake this target's timestamp to be 'just good enough' (i.e., exa=
ctly equal to or one tick newer than its latest prerequisite).
>=20
> Doing so would:
>=20
> - Keep its prerequisites alive in the traversal graph.
> - Report a correctly faked 'up-to-date' status in the visual log.
> - Avoid triggering cascading rebuilds for higher targets.
>=20
> I am considering hacking together a local patch to introduce a new comman=
d-line option -- something along the lines of '--not-too-old-not-too-young-=
but-up-to-date=3DTARGET' -- to enable this behavior for specific targets. T=
he logic would essentially intercept the target, declare it up-to-date so n=
o recipe executes and dynamically set the file's internal modification date=
to match the highest timestamp of its prerequisites so subsequent processi=
ng runs smoothly.
>=20
> Could anyone familiar with 'src/remake.c' point me toward the correct pla=
ce where these specific date comparisons and status assignments happen? Tha=
nks.
>=20
> On Tuesday, May 26th, 2026 at 3:50 PM, WaitronCharm <WaitronCharm@proton.=
me> wrote:
>=20
> > To clarify further, simply removing -o and using -n (--just-print) inst=
ead is also not a viable workaround. While -n would traverse the prerequisi=
tes and make the graph structurally complete, the reported target build sta=
tuses would be wrong for this use case. The debug output would show targets=
as 'needing to be remade' rather than treating them as up-to-date via the =
-o override.
> >
> > There seems to be no combination of current options that yields both a =
fully traversed dependency graph and the correct target statuses in the deb=
ug logs.
> >
> > On Tuesday, May 26th, 2026 at 3:30 PM, WaitronCharm <WaitronCharm@proto=
n.me> wrote:
> >
> > > Hello,
> > >
> > > I am working on reconstructing the visual dependency graph of a build=
using GNU Make's --debug output. However, I have run into a limitation whe=
n combining debugging with the -o (--old-file) option.
> > >
> > > When a target is marked as old via -o, GNU Make seems to immediately =
optimize away the traversal of that target's prerequisites. Because these p=
rerequisites are not traversed, they are completely omitted from the debug =
log. This leaves the reconstructed visual graph incomplete.
> > >
> > > From an execution standpoint, optimizing out these checks makes perfe=
ct sense. However, for tooling and visualization, it creates a blind spot. =
Could the final decision to consider a target up-to-date (based on -o) be d=
eferred until after its prerequisites have been traversed in the graph?
> > >
> > > I tried using the -n (--just-print / dry-run) option as an alternativ=
e to see the full graph without executing commands, but it has a different =
limitation: rules that update included makefiles are still actively execute=
d under -n.
> > >
> > > This leaves a gap in the current options. There appears to be no comb=
ination of flags that allows a user to safely skip a target's execution whi=
le still fully discovering and dumping its underlying dependency tree in th=
e debug output.
> > >
> > > Here is a minimal example demonstrating the behavior:
> > >
> > > $ make --debug -f - -o t1
> > > GNU Make 4.4.1
> > > Built for x86_64-pc-cygwin
> > > Copyright (C) 1988-2023 Free Software Foundation, Inc.
> > > License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/=
gpl.html>
> > > This is free software: you are free to change and redistribute it.
> > > There is NO WARRANTY, to the extent permitted by law.
> > > t1: t2; echo $@
> > > t2:; echo $@
> > > Reading makefiles...
> > > Updating makefiles....
> > > Updating goal targets....
> > > make: 't1' is up to date.
> > >
> > > Notice that t2 is never mentioned or evaluated in the debug output ab=
ove. Compare this to a normal run where the full relationship is explicitly=
printed:
> > >
> > > $ make --debug -f -
> > > GNU Make 4.4.1
> > > Built for x86_64-pc-cygwin
> > > Copyright (C) 1988-2023 Free Software Foundation, Inc.
> > > License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/=
gpl.html>
> > > This is free software: you are free to change and redistribute it.
> > > There is NO WARRANTY, to the extent permitted by law.
> > > t1: t2; echo $@
> > > t2:; echo $@
> > > Reading makefiles...
> > > Updating makefiles....
> > > Updating goal targets....
> > > File 't1' does not exist.
> > > File 't2' does not exist.
> > > Must remake target 't2'.
> > > echo t2
> > > t2
> > > Successfully remade target file 't2'.
> > > Must remake target 't1'.
> > > echo t1
> > > t1
> > > Successfully remade target file 't1'.
> > >
> > > Is this immediate pruning of the graph an intentional design constrai=
nt for performance, or would the maintainers consider a patch/option that f=
orces prerequisite traversal even when a target is short-circuited by -o?
> > >
> > > I would love to hear your thoughts on whether this use case is curren=
tly supported through other means, or if a feature request is appropriate h=
ere.
> > >
> > >