Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile sequential execution

Tags:

makefile

gnu

I have the following Makefile:

all: generate print # <-- doesn't work

date: 
    date > date.txt

ls:
    ls -la > ls.txt

generate: ls date

print: *.txt
    cat $^

clean:
    rm *.txt

The targets date and ls generate a file each, the target print, prints them out.

How do I write the target all, so that it first generates the files and then prints it?

like image 396
scrrr Avatar asked Mar 25 '14 09:03

scrrr


2 Answers

Just add the pipe symbol:

all: | generate print

From the make manual:

Order-only prerequisites can be specified by placing a pipe symbol (|) in the prerequisites list: any prerequisites to the left of the pipe symbol are normal; any prerequisites to the right are order-only:

targets : normal-prerequisites | order-only-prerequisites
like image 163
akond Avatar answered Oct 19 '22 21:10

akond


The dependancy hierarchy of the rules you want is all -> print -> generate. 'print' should be dependant on 'generate'.

The Makefile you have is interesting. On first pass it generates the .txt files using { all -> generate -> ls, date } hierarchy but the print fails. On second pass if you don't do clean it works.

The 'print' rule you have is a valid rule. But doesn't allow make to know that you need to do the 'generate' actions before doing the 'print'.

You could EXplicitly make a print rule which says it is dependant on generating date.txt and ls.txt. Try change your 'all' and 'print' rules like this . . .

EDIT: SORRY! First Answer I gave doesn't work. Tested it. This works.

all: print # <- just print target here as you don't want generate to happen after print
.
print: generate ls.txt date.txt
    cat $^

Make could decide to do print action first and the generate action afterwards if print is not made dependant on the files explicitly or generate.

This works but we get an error as the cat of non existant file generate doesn't work.

Taking this a bit further . . . Get rid of the generate rule. And I think the date and ls rule would be better if they explicitly detailed what file they generated, i.e.

all: print

date.txt:
    date > date.txt

ls.txt:
    ls -la > ls.txt

print: ls.txt date.txt
    cat $^

*.txt. If you want to operate on multiple files with same extension then you can do different things e.g. put the list of files in a make variable. You can have a make rule to calculate this list of files (using shell cmd in make). But that make rule cannot be dependant on the files already existing if it is the thing that is generating them.

The make manual gives a rule very close to your original print rule - using wildcard in rule prerequisites. http://www.gnu.org/software/make/manual/make.html#Wildcard-Examples

Make has quite a simple hierarchy of dependancies. Make will follow dependancies in order. Getting your head around the sequence a makefile will follow can be tricky but it is actually quite simple enough so well worth while working on understanding it.

It is a common problem for makefiles for some part of make system to be missing a dependancy on another. Often build systems will get away with this but sometimes it can cause weirdness (e.g. object files being compiled after being linked in).

The make manual has a good introduction. http://www.gnu.org/software/make/manual/make.html#Introduction

like image 44
gaoithe Avatar answered Oct 19 '22 21:10

gaoithe