2
votes

Right now I am learning how to use makefiles and am having trouble with variables inside rules. My goal is to parse a file containing names of other files, save that in a variable, and use the variable as a "target pattern" to run a rule on each file. Here is a simple example of my problem (I'm writing the file names in to make it simpler).

When I run this:

variable = file1.txt file2.txt file3.txt

run : $(variable)

$(variable): %.txt:
    echo File is $@

I get the following, which is what I want:

$ make run
echo File is file1.txt
File is file1.txt
echo File is file2.txt
File is file2.txt
echo File is file3.txt
File is file3.txt

The problem is I want to define variable by parsing a file, and I want that file to be a dependency because, if it does not exist, I will make it using another rule in the makefile. So when I define the variable in a rule like this (which I know is there from my echo):

target1 :
    $(eval variable = file1.txt file2.txt file3.txt)
    echo $(variable)

run : $(variable)

$(variable): %.txt:
    echo File is $@

I get the following:

$ make target1
echo file1.txt file2.txt file3.txt
file1.txt file2.txt file3.txt

And this:

$ make run
make: Nothing to be done for `run'.

So my question is how to define the variable in a rule and and use it in something line this:

$(variable): %.txt:
    echo File is $@

I've tried reading through the manual and Googling but I just can't figure this out. I also imagine there is some simple answer I am missing. Thanks so much for your help! :)

1
It doesn't work because of the way make works: FIRST make parses the ENTIRE makefile, expanding variables, etc. as necessary. THEN make starts to run recipes for rules that are outdated. So, by the time make runs the recipe for target1 which contains the eval, the rest of the makefile has already been parsed and variable has already been expanded (to the empty string).MadScientist

1 Answers

2
votes

If you can control the content of the target1 created file this is easy: just make the format of that file be a make variable assignment, then use the include command, like this:

run:

include target1

run: $(variable)

$(variable): %.txt:
        echo File is $@

target1:
        echo 'variable = file1.txt file2.txt file3.txt' > $@

Through the magic of automatically generated makefiles make will recreate that target file then re-invoke itself automatically.