在我的 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