1
\$\begingroup\$

For the record, I'm writing according to the NEXT - Version 5 of Single Unix Specification, which is Issue 8 if you count the days when it was named XPG. In this new standard, a few new already-common-place features are being added, such as delayed and immediate expansion macros, and re-making of include files. Parts of the proposed changes are available here.

My end-goal is to include something generated by more complex scripts, and this is just me practicing. For example, I want to create a "make" prerequisite listing of C/C++ include files; Or I want to extract a list of contributors to my project, and put this list in the "make" target for documentations.

What I'm trying to achieve, is to include a file in the main Makefile, and this file is always generated on-demand whenever the build targets are requested to make (thus excluding auxiliary targets such as clean, install, etc.)

Here's my Makefile

.PHONY: all clean timestamping

all: main.c
    ${CC} -o main -D LIB_RET=1${lib_ret} main.c

clean:
    rm -f main include.mk time.stamp

all: timestamping

timestamping:
    date -u '+%Y-%m-%d T %H:%M:%S %Z' > time.stamp

time.stamp:; :

include.mk: time.stamp
    printf 'lib_ret='`date +%S` > include.mk

include include.mk

Here's "main.c":

#include <stdio.h>
int main(void){ return LIB_RET; }

I'm quite satisfied with the current form of it, but I'm sure suggests for improvements will be plenty. I'm mostly concerned about the portability of this Makefile on FOSS makes, such as GNU make and pmake.

One part I'm not satisified is that the commands for timestamping and time.stamp gets executed twice on the make supplied by the Xcode toolchains (which uses GNU Make version 3.81 as of Xcode Version 14.2 (14C18) 2022-12-27).

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

It seems strange to be writing a non-text file here (i.e. lacking a final newline):

    printf 'lib_ret='`date +%S` > include.mk

I would have written it with a newline, using

     date +lib_ret=%S >$@

It's also strange that it depends on time.stamp but doesn't use that dependency. It's like you intended

    date -d $(cat $<) +lib_ret=%S >$@

Or perhaps not have the timestamping and time.stamp targets at all (and have .PHONY: include.mk instead).

Instead of all: main.c, we could let the default rules build main from main.c:

CFLAGS += -DLIB_RET=1${lib_ret}
all: main

If we can assume GNU Make is available (and that's a good assumption these days), then we could simplify the entire Makefile to

.PHONY: main clean

main: CFLAGS += -DLIB_RET=$(shell date +1%S)

clean::
    $(RM) main

Even without GNU Make, we could use $$(date +1%S) in CFLAGS.

And I'd recommend including at least -Wall -Wextra when compiling C sources.

Be aware that the whole concept of including timestamps in your builds is something the free software community has made great efforts to eliminate in recent years in the pursuit of reproducible builds, so I strongly urge you to reconsider whether this is something you really should be doing at all.

\$\endgroup\$
5
  • \$\begingroup\$ The timestamping and the time.stamp target are intentional, timestamping is used to ensure the commands for include.mk are always executed, time.stamp (with the null command) is there to prevent Make from reporting non-existent prerequisite. My end-goal is to include something generated by more complex scripts, so although I thank you for the simplified Makefile, I'll have to stick with the premise in the question. \$\endgroup\$
    – DannyNiu
    Dec 27, 2022 at 11:42
  • \$\begingroup\$ Also, GNU make seem to reject include files that're phony targets, so I did away with it. \$\endgroup\$
    – DannyNiu
    Dec 27, 2022 at 11:46
  • \$\begingroup\$ You don't need timestamping to ensure that include.mk's commands are always executed - that's what .PHONY is for. \$\endgroup\$ Jan 4 at 9:35
  • \$\begingroup\$ Yeah, but when I last tried, GNU make seem to reject include files that're phony targets as I said in my last comment. Of course, if you can provide a fragment of Makefile that behaves differently from what I've been observing, you're answer will be more than valuable. \$\endgroup\$
    – DannyNiu
    Jan 4 at 11:36
  • \$\begingroup\$ That's probably a sign that the rule needs a comment explaining why it's done like that. Without the comment, any future maintainer is likely to make the same assumptions I did. \$\endgroup\$ Jan 4 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.