Makefile目录功能未按预期在for循环中展开

时间:2019-07-14 14:16:23

标签: makefile

我要遍历文件列表,在执行命令之前在其各自的目录中执行cd

所以我想使用$(dir $(FILES))函数来获取目录,但是似乎在for循环中不能正常工作。

FILES=../dir1/file1 ../dir2/file2

.PHONY: all

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

输出

../dir1/file1 in ./
../dir2/file2 in ./

$(dir $${f})扩展为./,而不是../dirN

注意:

  • 按预期,仅在echo $(dir $(FILES))循环输出for之外写入../dir1/ ../dir2/
  • 使用$(abspath ...)也不起作用。

我想念什么?

1 个答案:

答案 0 :(得分:1)

您正在混合make构造(dir)和shell构造。不幸的是,没有同时评估它们。 Make会在将配方传递给外壳之前 一次评估其构造,而不是在外壳执行配方期间进行评估。扩展配方时(在将其传递给外壳之前),它将转换为:

for f in ../dir1/file1 ../dir2/file2; do echo $f in ./; done

因为当make展开$(dir $${f})时,它首先会扩展参数:

$(dir ${f})

,然后,由于字符串/中没有${f},因此dir函数的扩展将其替换为./。从GNU make手册:

$(dir names…)
     

提取名称中每个文件名的目录部分。文件名的目录部分是所有内容(和   包括)中的最后一个斜杠。如果文件名不包含斜杠,   目录部分是字符串./。例如,

$(dir src/foo.c hacks)
     

产生结果src/ ./

无论如何,混合make和shell结构通常不是您想要做的(有例外)。您只能使用shell构造:

all:
    $(FILES); do \
        echo $$f in $$(dirname $$f) ; \
    done

或者您可以使用static pattern rule完全摆脱shell循环,并使其遍历类似目标的列表:

FILES = ../dir1/file1 ../dir2/file2
FOOS  = $(addsuffix .foo,$(FILES))

.PHONY: all $(FOOS)

all: $(FOOS)

$(FOOS): %.foo:
    @echo $* in $(dir $*)