Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you call functions in the body of a for loop in a Makefile

Tags:

makefile

I have defined a list of files in a Makefile.

I need to copy those files, with their directory structure, to a new location.

I can't use cp --parent because the source files live in ../ (so .. will be a part of the dest path).

I've decided, then, to do one for loop that creates the dirs, then a second for loop that copies the files. The problem, however, is that I can't seem to call $(dir $$file) in the body of the for loop. I always get "./" as the result, rather than the actual dir name. If I do something like echo $(dir foo/bar), that works fine, but echo $(dir $$file) (when $$file is 'foo/bar') always returns './'.

I've tried other options like $(shell basename $$file), but that also doesn't work.

I've tried defining a function and calling it in the body of the for, but that, too, doesn't work.

Here's a quick example Makefile:

FILES := foo/faz \
         bar/baz \
         gah/gaz

all:
    @for f in $(FILES); do \
      echo $(dir $$f); \
    done

I expect the output of this to be:

foo
bar
gah

but instead, I'm getting:

./
./
./

I'm open to other solutions if my method is not the best. At the end of the day, I need to be able to copy all the $(FILES) that exist in ../ (so ../foo/bar, for example) to a new dir called $(NEWDIR) (so newdir/foo/bar, for example).

This only needs to work under Linux.

like image 453
Brian K Avatar asked Oct 18 '25 19:10

Brian K


1 Answers

f is a shell variable here. The make function dir is called on the string $f (which the shell then interprets as a variable expansion).

If you use a shell loop, you need to use the shell's constructs to extract the directory part:

@set -e; for f in $(FILES); do \
      echo $$(dirname $$f); \
    done

Don't forget set -e, so that if there's an error during the copy, the make rule will fail.

You can also use a foreach function in make to generate a bunch of cp commands. It makes the makefile harder to debug though.

like image 197
Gilles 'SO- stop being evil' Avatar answered Oct 21 '25 03:10

Gilles 'SO- stop being evil'