Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile variable expansion/evaluation

Tags:

makefile

Currently I am facing an issue with my Makefile caused by evaluation of a make variable. I have reduced the complexity, only the essential elements remain that produce the issue.

  • $(LIST) is evaluated as a list of files when the Makefile is read.
  • During step1 one of those files is deleted.
  • When using the variable in step2 it is not evaluated again and thus not valid any more which leads to an error during the copy command.
  • It would be nice if the variable was evaluated at the time it is used, here during step2.

Any ideas how to solve or work around this issue?


Makefile:

LIST=$(wildcard src/*.txt)

all: step1 step2

step1:
    @echo "---------- step1 ----------"
    @echo $(LIST)
    rm src/q1.txt
    ls src

step2:
    @echo "---------- step2 ----------"
    @echo $(LIST)
    cp $(LIST) ./dst

Execution logging:

$ make
---------- step1 ----------
src/q1.txt src/q2.txt
rm src/q1.txt
ls src
q2.txt
---------- step2 ----------
src/q1.txt src/q2.txt
cp src/q1.txt src/q2.txt ./dst
cp: cannot stat `src/q1.txt': No such file or directory
make: *** [step2] Error 1
like image 376
Helmholtz42 Avatar asked Jan 27 '12 07:01

Helmholtz42


People also ask

What is $@ in makefile?

The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run.

What does eval do in makefile?

8.9 The eval Function The eval function is very special: it allows you to define new makefile constructs that are not constant; which are the result of evaluating other variables and functions. The argument to the eval function is expanded, then the results of that expansion are parsed as makefile syntax.

How do you check if a variable is defined in makefile?

Check if variable is defined in a Makefilecheck_defined = \ $(strip $(foreach 1,$1, \ $(call __check_defined,$1,$(strip $(value 2))))) __check_defined = \ $(if $(value $1),, \ $(error Undefined $1$(if $2, ($2)))) install: $(call check_defined, var1) $(call check_defined, var2) # do stuff here..


1 Answers

Don't use the wildcard function.

LIST = src/*.txt

all: step1 step2

step1:
    @echo "---------- step1 ----------"
    @echo $(LIST)
    rm src/q1.txt
    ls src

step2:
    @echo "---------- step2 ----------"
    @echo $(LIST)
    cp $(LIST) ./dst
like image 170
Jonathan Leffler Avatar answered Sep 18 '22 01:09

Jonathan Leffler