Makefile dir函数不使用';在for循环中不能按预期进行扩展

Makefile dir函数不使用';在for循环中不能按预期进行扩展,makefile,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 ./

我想遍历文件列表,在执行命令之前,在它们各自的目录中执行
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

注:

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

我缺少什么?

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

for f in ../dir1/file1 ../dir2/file2; do echo $f in ./; done
因为当make展开
$(dir$${f})
时,它首先展开参数:

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

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

$(dir src/foo.c hacks)
生成结果
src/

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

all:
    @for f in $(FILES); do \
        echo $$f in $$(dirname $$f) ; \
    done
或者,您也可以使用来完全摆脱shell循环,并让make遍历类似目标的列表:

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

.PHONY: all $(FOOS)

all: $(FOOS)

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

对,我很困惑,因为我认为在执行
$(dir$$f)
之前,
$$f
会被扩展到
./dirN/fileN
,并且它会包含
/
。显然不是。谢谢
FILES = ../dir1/file1 ../dir2/file2
FOOS  = $(addsuffix .foo,$(FILES))

.PHONY: all $(FOOS)

all: $(FOOS)

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