Question

Basically, I have a file 'blah.txt'. That files gets parsed by a 'compiler' and from it will generate N output .c files. I want a makefile that will from that .txt file generate the c files then compile all of them and archive them in a libmystuff.a

I tought of something like this :

all: dogen libmystuff.a

dogen: source.txt
    mycompiler $^

libmystuff.a: $(addsuffix .o, $(shell ls *.c))
    $(AR) rcs $@ $^

.PHONY: dogen

But obviously that doesn't work because the dependencies are evaluated at the start and at that point the *.c just doesn't yield anything yet since they don't exist.

Does anyone see how to accomplish that (without listing all the generated *.c explicitely) ?

Was it helpful?

Solution

Pavel Shved is right(*), you must rerun Make. Here is a trick I'm rather proud of. It will handle dependencies on objects that may not yet exist, and won't run unnecessarily.

SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)

all: libmystuff.a

ifeq ($(MAKELEVEL),0) 
libmystuff.a: source.txt
    mycompiler $^ 
    @$(MAKE) -s $@
else
libmystuff.a: $(OBJECTS)
    $(AR) rcs $@ $^ 
endif

(*) My old nemesis, we meet again.

EDIT:
If some other make calls this make... I hadn't thought of that. But I think this will solve it:

SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)

all: libmystuff.a

libmystuff.a: source.txt
    mycompiler $^ 
    @$(MAKE) -s phonyLib

.PHONY: phonyLib
phonyLib: $(OBJECTS)
    $(AR) rcs libmystuff.a $^ 

(Yes, I know, if you feel an urge to build a file called "phonyLib" you won't be able to do it with this makefile, but let's not be perverse.)

OTHER TIPS

Use sentry "makefile" to force make to re-read makefile and substitute correct list at *.c:

include sources-sentry

sources-sentry: source.txt
    mycompiler $^
    touch $@

libmystuff.a: $(addsuffix .o, $(shell ls *.c))
    $(AR) rcs $@ $^

include directive is used to include other makefiles (just like C's #include). It has a nice pecularity that if makefile it includes is a target itself, make program first considers it as a target and tries to update. If it is not up-to-date, make invokes the commands needed to update it and then re-reads makefile, substituting all the variables again.

Thus, if source.txt changed since the last time you processed it (the time being recorded as timestamp of sources-sentry file), the sources will be updated and make will be re-invoked, the *.c being substituted to the updates set of c-files.

If your .c files are only produced by the .txt, then you can let the libmystuff.a depend on the txt, and evaluate the $(shell ls *.c) in the rule body instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top