2023-01-23

Tools: redo (part 5) version.h, autogenerated

#software

Content

Part 0: Intro

Part 1: Hello, world!

Part 2: Automatic Recording of Dependencies on Header Files

Part 3: CFLAGS and friends, config.sh, compile.do

Part 4: CFLAGS and friends, env/VAR, default.run.do

Part 5: Auto-update BUILDDATE in version.h

Part 6: The yacc/bison problem: one call produces two artifacts

Part 7: Test: Generator for N source files

My code featured in this series can be found at

https://git.sr.ht/~ew/ew.redo/

Part 5: Auto-update BUILDDATE in version.h

How about updating something like BUILDDATE or GITVERSION automatically in some generated version.h file? Wouldn't that be nice? Or in more technical terms:

How hard can it be?

Turns out, it was harder than I expected, because I stomped on a bug lurking in goredo. Good news: After reporting the error, Sergey Matveev has fixed it in version 1.29.0.

The example below was basically recycled fron the documentation of Avery Pennaruns redo:

https://redo.readthedocs.io/en/latest/cookbook/defaults/

https://github.com/apenwarr/redo/

Generate "version" with version.do

The snippet is quite simple, the important lines are the last two.

This way any generated content can be checked for changes.

Generate "date" with date.do

Same sort of script. It should be clear that including the seconds in the timestamp will make this target change pretty much always.

Changes?

So we want to see that the content of file version does not change on redo, whereas the content of file date does change:

Works as advertised.

Generate include/version.h from a template

From these two files, we create a new file include/version.h. So we have a template include/version.h.in and a script include/version.h.do to expand the template and produce the desired result.

The corresponding redo snippet "include/version.h.do" edits the template and produces the desired file "include/version.h"

Again file include/version.h is always generated, but is considered unchanged, if its content is unchanged. This can be tested by removing the line, which edits %%DATE%%, or by removing the time part of the output in date.do. In that case nothing is rebuild on subsequent calls to redo.

So we instrument hello.c to use version.h accordingly:

With both variables being considered, include/version.h changes and hello.o and thus hello is being rebuild:

Unfortunately there is a chicken-and-egg problem in here. Building include/version.h explicitly will make the remaining build succeed. However, starting from scratch fails:

This problem is not so hard to understand: The generated file include/version.h is referenced in hello.c. So include/version.h is a prerequisite for hello.o. Moreover, it is automatically detected and added via compile.run. However, compile.run or more precisely "gcc -MMD" will fail if include/version.h is not yet available. So there is a chicken-or-egg problem. That means we have to add this dependency explicitly. It should not come as a surprise, that adding this to default.o.do is questionable, because now all .c files whereever they reside in this build tree will depend on include/version.h. The solution is to add an extra snippet for hello.o:

With that in place, and goredo of version 1.29.0 or later, things will start to work:

PostScriptum

The bug mentioned above had to do with a target (version.h) being triggered twice in one redo run. The second invocation would always fail with

Thanks to Sergey for fixing this immediately.

Cheers,

~ew

Home

Proxied content from gemini://ew.srht.site/en/2023/20230123-redo-5.gmi (external content)

Gemini request details:

Original URL
gemini://ew.srht.site/en/2023/20230123-redo-5.gmi
Status code
Success
Meta
text/gemini
Proxied by
kineto

Be advised that no attempt was made to verify the remote SSL certificate.