Re: [PATCH] make: add valid-for and valid-max target TTL support
Britton Kerin <[email protected]> Tue, 17 Feb 2026 08:17:10 -0800
| Newsgroups | gmane.comp.gnu.make.bugs |
|---|---|
| Message-ID | <CAC4O8c_ww=Mn2jwEtKzQvPjrWSTchbT=A_R7WC_d4-PqDRW2jw@mail.gmail.com> |
--0000000000000d845f064b0768fd Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, Feb 16, 2026, 1:46=E2=80=AFPM Yair Lenga <[email protected]> wro= te: > Hello, > > This patch introduces two optional target-specific variables, > 'valid-for' and 'valid-max', that allow controlling the freshness > and expiration of existing targets based on their modification time. > > Motivation > ---------- > > GNU make treats an existing target with no prerequisites as > permanently up to date. In practice, many build workflows generate > cache or artifact files that should be reused while fresh but > periodically regenerated even without explicit dependencies. Today > this: requires introducing artificial phony prerequisites or external > timestamp logic. > > The new variables provide a declarative mechanism for this: > > valid-for =3D DURATION > If the target exists and its age is less than or equal to the > specified duration, make treats it as up to date and skips > dependency checking. > > valid-max =3D DURATION > If the target exists and its age exceeds the specified duration, > make forces a rebuild even if the target has no prerequisites. > > Durations are specified as either an integer number of seconds or a > sequence of <number><unit> segments without spaces, where unit is one > of 's', 'm', 'h', 'd', or 'w' (e.g. "300", "5m", "1d5h"). > > When both variables are present, 'valid-for' takes precedence for > fresh targets, while 'valid-max' forces rebuild of expired targets. > I'm not sure I entirely understand this and think it could probably be better expressed for documentation at least. By fresh I assume you mean otherwise up-to-date? > Implementation > -------------- > > The logic is implemented in update_file_1() via a small helper that > parses and evaluates the TTL variables. Invalid values are ignored > and reported under --debug=3Dv. Successful use of the TTL is reported > under --debug=3Db. > > This approach preserves existing make semantics while enabling > expiration of leaf targets and optional dependency skipping for > recent artifacts. > Is it usable only for leaves? I guess these variables are not inherited by dependent targets (as other target-local variables are) since that would presumably add a bunch of undesired edges to the DAG? > ------- > Example 1: Periodic reloading of remote resources that change very > frequently. > > cache.json: private valid-max=3D1d > cache.json: > curl -o $@ https://example/api > > The file will be regenerated once per day even without prerequisites.This > can be useful when a test job is running every few minutes, but loading o= f > remote resources is time consuming. > > Other use cases include periodically refreshing generated version > stamps, expiring downloaded resources in reproducible builds, and > limiting reuse of expensive intermediate artifacts in CI or code > generation workflows. > > --- > > Patch attached. Comments welcome. > > Best regards, > Yair Lenga > --0000000000000d845f064b0768fd Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"auto"><div><br><br><div class=3D"gmail_quote gmail_quote_contai= ner"><div dir=3D"ltr" class=3D"gmail_attr">On Mon, Feb 16, 2026, 1:46=E2=80= =AFPM Yair Lenga <<a href=3D"mailto:[email protected]">yair.lenga@gma= il.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"m= argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l= tr">Hello,<br><br>This patch introduces two optional target-specific variab= les,<br>'valid-for' and 'valid-max', that allow controlling= the freshness<br>and expiration of existing targets based on their modific= ation time.<br><br>Motivation<br>----------<br><br>GNU make treats an exist= ing target with no prerequisites as<br>permanently up to date.=C2=A0 In pra= ctice, many build workflows generate<br>cache or artifact files that should= be reused while fresh but<br>periodically regenerated even without explici= t dependencies.=C2=A0 Today<br>this:=C2=A0 requires introducing artificial = phony prerequisites or external<br>timestamp logic.<br><br>The new variable= s provide a declarative mechanism for this:<br><br>=C2=A0 valid-for =3D DUR= ATION<br>=C2=A0 =C2=A0 =C2=A0 If the target exists and its age is less than= or equal to the<br>=C2=A0 =C2=A0 =C2=A0 specified duration, make treats it= as up to date and skips<br>=C2=A0 =C2=A0 =C2=A0 dependency checking.<br><b= r>=C2=A0 valid-max =3D DURATION<br>=C2=A0 =C2=A0 =C2=A0 If the target exist= s and its age exceeds the specified duration,<br>=C2=A0 =C2=A0 =C2=A0 make = forces a rebuild even if the target has no prerequisites.<br><br>Durations = are specified as either an integer number of seconds or a<br>sequence of &l= t;number><unit> segments without spaces, where unit is one<br>of &= #39;s', 'm', 'h', 'd', or 'w' (e.g. &qu= ot;300", "5m", "1d5h").<br><br>When both variables= are present, 'valid-for' takes precedence for<br>fresh targets, wh= ile 'valid-max' forces rebuild of expired targets.<br></div></block= quote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">I'm not= sure I entirely understand this and think it could probably be better expr= essed for documentation at least.=C2=A0 By fresh I assume you mean otherwis= e up-to-date?</div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class= =3D"gmail_quote gmail_quote_container"><blockquote class=3D"gmail_quote" st= yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div = dir=3D"ltr"><br>Implementation<br>--------------<br><br>The logic is implem= ented in update_file_1() via a small helper that<br>parses and evaluates th= e TTL variables.=C2=A0 Invalid values are ignored<br>and reported under --d= ebug=3Dv.=C2=A0 Successful use of the TTL is reported<br>under --debug=3Db.= <br><br>This approach preserves existing make semantics while enabling<br>e= xpiration of leaf targets and optional dependency skipping for<br>recent ar= tifacts.<br></div></blockquote></div></div><div dir=3D"auto"><br></div><div= dir=3D"auto">Is it usable only for leaves?=C2=A0 I guess these variables a= re not inherited by dependent targets (as other target-local variables are)= since that would presumably add a bunch of undesired edges to the DAG?</di= v><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote g= mail_quote_container"><blockquote class=3D"gmail_quote" style=3D"margin:0 0= 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br>-= ------<br>Example 1: Periodic reloading of remote resources that change ver= y frequently.<br><br>=C2=A0 cache.json: private valid-max=3D1d<br>=C2=A0 ca= che.json:<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 curl -o $@ <a href=3D"https= ://example/api" target=3D"_blank" rel=3D"noreferrer">https://example/api</a= ><br><br>The file will be regenerated once per day even without prerequisit= es.This can be useful when a test job is running every few minutes, but loa= ding of remote resources is time consuming.<div><br></div><div>Other use ca= ses include periodically refreshing generated version<br>stamps, expiring d= ownloaded resources in reproducible builds, and<br>limiting reuse of expens= ive intermediate artifacts in CI or code<br>generation workflows.</div><div= ><br></div><div>---</div><div><br></div><div>Patch attached. Comments welco= me.</div><div><br></div><div>Best regards,</div><div>Yair Lenga</div></div> </blockquote></div></div></div> --0000000000000d845f064b0768fd--