问题描述
我有一个 makefile,它假设为目录中的每个 file.csv 重复执行一次 c 代码(BootstrapCL.c)。对于每次执行,它应该将输入提供给 c 代码(作为 argv)2 字符串:当前执行中使用的输入 csv 文件的名称(带和不带扩展名)。 这是生成文件的内容:
SRCS := $(wildcard *.csv)
BINS := $(SRCS:%.csv=%)
all: ${BINS}
%: BootstrapCL.c
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL [email protected] $@
问题是,在执行完所有 csv 文件组(我只想执行 ${BINS} 列表中的目标)之后,它还使用“所有”目标运行最后一次执行。当然,我的文件夹中没有任何 all.csv 文件;我认为我以错误的方式使用 $@,但我不明白为什么以及如何解决这个问题,知道吗?
解决方法
问题是您没有all
的食谱,而%
的规则可以匹配任何内容。当Make完成时先决条件 (${BINS}
),它尝试构建 all
,寻找适合的配方,并找到 %
。
(至少)有两种方法可以解决问题。快速而肮脏的方法是为 all
添加一个(空)配方:
all: ${BINS}
@:
在我看来更好的另一种方法是收紧第二条规则:
BINS := $(SRCS:%.csv=%.phony)
all: ${BINS}
%.phony: BootstrapCL.c
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL $*.csv $*
为了整洁,我建议你也添加一行:
.PHONY: $(BINS)
让 Make 知道 .phony
目标不是要构建的真实文件。
其他一些小的改进也是可能的。我会考虑 BootstrapCL
以及它是否会生成一个可以用作真正目标的文件。
我对解决方案的看法与 Beta 略有不同:
SRCS := $(wildcard *.csv)
BINS := $(SRCS:%.csv=%)
# All rule - requires binaries to be generated. This does not generate anything,therefore it is PHONY
.PHONY: all
all: ${BINS}
# Generates the binaries - requires BootstrapCL exe to be generated first
${BINS}: BootstrapCL
./BootstrapCL [email protected] $@
# Generates BootstrapCL
BootstrapCL:
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
据我所知 - 您需要编译 BootstrapCL.c 一次以生成 BootstrapCL 可执行文件。然后使用它生成多个二进制文件 - 一个用于 eacn .csv 文件。
反过来:
- 您有一个需要 BINS 的
all
目标。 - 您有一个生成 BIN 的
BINS
目标,但首先需要 BootstrapCL - 这将对每个 .csv 文件运行一次。 - 您有一个生成 BootstrapCL 可执行文件的
BootstrapCL
目标 - 这将只运行一次。
%
规则过于笼统,可以捕获所有内容,甚至尝试重建 Makefile 本身。此外,它每次都编译 BootstrapCL
,这似乎没有必要:
$ make
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL Makefile.csv Makefile
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL foo.csv foo
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL bar.csv bar
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL all.csv all
我会使用模式规则来生成二进制文件,因为如果 .csv 文件发生更改,这也将重建二进制文件。我还会将 BootstrapCL
生成分离到不同的规则,以便仅编译一次,但将其保留在依赖项列表中,以便目标在 BootstrapCL
更改时重新生成它们:
$ cat Makefile
SRCS := $(wildcard *.csv)
BINS := $(SRCS:%.csv=%)
all: ${BINS}
BootstrapCL: BootstrapCL.c
gcc -Wall $< -lm -o $@
%: %.csv BootstrapCL
./BootstrapCL $< $@
输出:
$ make
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL foo.csv foo
./BootstrapCL bar.csv bar