Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Make get the list of all files in a directory that were generated by previous rule

Tags:

makefile

I am looking for Makefile macro to get list of all files in a directory that were generated as rule1 processing and using this list for rule2 processing.

Here's what I am trying to achieve :

  • Rule 1: Generate source .c files (using xml files) and place them in $(MYDIR) directory.
  • Rule 2: Get the list of all files in $(MYDIR) and create object files and place them in $(OBJDIR).

Problem is, I want to update list of files in Rule2 after Rule 1 has been processed, else list of files in $(MYDIR) will be empty.

all : rule_1 rule_2

rule1 : $(MYDIR)/generated_source1.c $(MYDIR)/generated_source2.c

$(MYDIR)/generated_source1.c:
    xsltproc generator1.xml style_generator.xsl -o $(MYDIR)/generated_source_1.c

$(MYDIR)/generated_source2.c:
    xsltproc generator2.xml style_generator.xsl -o $(MYDIR)generated_source_2.c

#Get list of all $(MYDIR).*c , create corresponding $(OBJDIR)/*.o list.
SOURCES := $(wildcard $(MYDIR)/*.c)
OBJECTS := $(notdir ${SOURCES})
GENERATED_OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(OBJECTS))

#This rule is compiling of all .c generated in rule1.
rule2 : $(GENERATED_OBJS)
    ld -r -o $(OBJDIR)/generated_lib.o $(GENERATED_OBJS)

$(OBJDIR)/%.o: $(MYDIR)/%.c
        gcc $(CFLAGS) -c -o $@ $<

$(SOURCES) is shown empty, but actually it should contain generated_source1.c and generated_source2.c I am not sure how .SECONDEXPANSION rule will work for my case.

like image 271
NeilBlue Avatar asked Feb 12 '23 04:02

NeilBlue


1 Answers

You can't really (and don't really want to) play around with getting make to re-evaluate file existence during the running of the make process.

What you want to do is track the files from start to finish in make and then you have all your lists.

You can start at either direction but starting with the initial source tends to be easier.

So start with

MYDIR:=dir
OBJDIR:=obj

XML_SOURCES := $(wildcard $(MYDIR)/*.xml)

then translate from there to the generated source files

SOURCES := $(subst generator,generated_source,$(XML_SOURCES:.xml=.c))

and from there to the generated object files

GENERATED_OBJS := $(patsubst $(MYDIR)/%.c,$(OBJDIR)/%.o,$(SOURCES))

At which point you can define the default target

all: $(OBJDIR)/generated_lib.o

and then define the rules for each step

$(MYDIR)/%.c:
        cat $^ > $@

$(OBJDIR)/%.o: $(MYDIR)/%.c
        cat $^ > $@

$(OBJDIR)/generated_lib.o: $(GENERATED_OBJS)
        ld -r -o $@ $^

The $(MYDIR)/%.c rule needs a bit of extra magic to actually work correctly. You need to define the specific input/output pairs so that they are used correctly by that rule.

$(foreach xml,$(XML_SOURCES),$(eval $(subst generator,generated_source,$(xml:.xml=.c)): $(xml)))

This .xml to .c step would be easier if the input and output files shared a basename as you could then just use this and be done.

%.c: %.xml
        cat $^ > $@
like image 80
Etan Reisner Avatar answered Feb 23 '23 00:02

Etan Reisner