I want to read a file called metafile inside a makefile.
metafile looks something like this:
file1
file2
file3
I need to read this metafile inside my makefile line by line and check if the files mentioned inside exists or not and only print names of files which exists.
I've tried a few things without success. like:
FILE=`cat metafile`
for line in $(FILE); if [ -e $${line} ]; then echo $${line} fi; done;
You can put an arbitrary piece of shell script in a target. Keeping the file's contents in a Makefile variable does not make any sense to me, unless you also need the data in other targets for other reasons. (If so, you cannot use backticks, anyway.)
target:
@while read -r file; do \
test -e "$$file" && echo "$$file"; \
done <metafile
For what it's worth, the while
loop is a safer and more idiomatic way to loop over a file's lines in a shell script than the for
loop with backticks, even though you see that a lot.
The @
prevents Make from echoing the shell script commands; take that out if for some reason you need to see them. In fact, I recommend against using this, especially while you are debugging -- use make -s
to have make
run silently once you are confident your recipe works correctly.
A more idiomatic way to do this in a Makefile is to have a target depend on these files, and use Make's own logic:
target: file1 file2 file3
@echo $(filter-out $?,$^)
This is GNU Make syntax; it might get more complex if you want to be portable to other Make flavors (to the point where maybe the shell script is preferable after all). It will echo everything on one line, but if you need separate lines, that should be a trivial fix.
I would simply build a small auxiliary Makefile snippet and include the dependencies:
target: target.d
target.d: metafile
sed 's/^/target: /' $< >$@
include target.d
This builds a small list of dependencies so you don't need to list them in the target:
dependencies explicitly; so instead of file1 file2 file3
in the recipe above, the dependencies would live in the generated target.d
which would contain
target: file1
target: file2
target: file3
You need to filter out the dependency on target.d
(or leave it undeclared; I believe GNU Make should cope).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With