在我的 makefile 中意外执行 "all" 目标
Unexpected execution of "all" target in my makefile
我有一个 makefile,假设为目录中的每个 file.csv 重复执行一次 c 代码 (BootstrapCL.c)。对于每次执行,它应该将输入提供给 c 代码(作为 argv) 2 字符串:当前执行中使用的输入 csv 文件的名称,包括和不包括扩展名。
这是 makefile 内容:
SRCS := $(wildcard *.csv)
BINS := $(SRCS:%.csv=%)
all: ${BINS}
%: BootstrapCL.c
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL $@.csv $@
问题是,在执行所有 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 $@.csv $@
# 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
我有一个 makefile,假设为目录中的每个 file.csv 重复执行一次 c 代码 (BootstrapCL.c)。对于每次执行,它应该将输入提供给 c 代码(作为 argv) 2 字符串:当前执行中使用的输入 csv 文件的名称,包括和不包括扩展名。 这是 makefile 内容:
SRCS := $(wildcard *.csv)
BINS := $(SRCS:%.csv=%)
all: ${BINS}
%: BootstrapCL.c
gcc -Wall BootstrapCL.c -lm -o BootstrapCL
./BootstrapCL $@.csv $@
问题是,在执行所有 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 $@.csv $@
# 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