Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execution of the recipe for multiple targets at once

I have a project where I need to process many files in the same way. My GNUMakefile looks like this:

$(SOURCES) = file1.a file2.a file3.a ... fileN.a
$(TARGETS) = $(SOURCES:.a=.b)

%.b: %.a
    build-tool $?

all: $(TARGETS)

This makefile executes build-tool for each target, which is slow. So I want it to execute build-tool only once with list of all updated prerequisites.
I tried to add the following rule:

$(TARGETS): $(SOURCES)

And it helped on first build like that:

$ make all
build-tool file1.a file2.a ... fileN.a

But on subsequent builds build-tool was executed as many times as many targets I have:

$ touch file1.a && make all
build-tool file1.a
build-tool file1.a
...
build-tool file1.a

In the other hand, if I change recipe to build-tool $@ it will execute build-tool once with all prerequisites in all cases, which is undesirable too.
Is there some method to execute the recipe only once for all targets, i.e. with all prerequisites on first build and only modified on subsequent builds?

like image 465
insanedeveloper Avatar asked Jan 15 '14 21:01

insanedeveloper


1 Answers

You can't use a pattern rule for this. That's why you're seeing everything build multiple times. You have to use a "sentinel" file that make can use to determine which files have changed since the last time you built.

For example, something like this will work:

$(SOURCES) = file1.a file2.a file3.a ... fileN.a
$(TARGETS) = $(SOURCES:.a=.b)

.PHONY: all
all: .ran-build-tool

.ran-build-tool: $(SOURCES)
        build-tool $?
        @touch $@

ETA: If you need another level you can do something like:

$(SOURCES) = file1.a file2.a file3.a ... fileN.a
$(TARGETS) = $(SOURCES:.a=.b)

.PHONY: all
all: .ran-build-tool2

.ran-build-tool2: $(TARGETS) | .ran-build-tool
        build-tool2 $?
        @touch $@

.ran-build-tool: $(SOURCES)
        build-tool $?
        @touch $@
like image 83
MadScientist Avatar answered Sep 19 '22 21:09

MadScientist