C 在我的makefile中意外执行“all”目标

C 在我的makefile中意外执行“all”目标,c,shell,makefile,target,automatic-variable,C,Shell,Makefile,Target,Automatic Variable,我有一个makefile,它假设对目录中的每个file.csv重复执行一次c代码BootstrapCL.c。对于每次执行,它都应该以argv 2字符串的形式向c代码提供输入:当前执行中使用的输入csv文件的名称(带扩展名和不带扩展名)。 这是makefile内容: SRCS := $(wildcard *.csv) BINS := $(SRCS:%.csv=%) all: ${BINS} %: BootstrapCL.c gcc -Wall BootstrapCL.c -lm -o

我有一个makefile,它假设对目录中的每个file.csv重复执行一次c代码BootstrapCL.c。对于每次执行,它都应该以argv 2字符串的形式向c代码提供输入:当前执行中使用的输入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文件;我想我使用$@的方式不对,但我不明白为什么以及如何解决这个问题,知道吗?

问题是你没有所有的配方,也没有一个与任何东西匹配的%规则。当Make完成了先决条件${BINS}时,它会尝试构建全部,寻找适合的配方,并找到%

至少有两种方法可以解决这个问题。快速而肮脏的方法是为所有以下内容添加一个空配方:

在我看来,另一个更好的方法是收紧第二条规则:

BINS := $(SRCS:%.csv=%.phony)

all: ${BINS}

%.phony: BootstrapCL.c
    gcc -Wall BootstrapCL.c  -lm -o BootstrapCL
    ./BootstrapCL $*.csv $*
为了保持整洁,我建议您也添加以下行:

.PHONY: $(BINS)
让他们知道.phony目标不是要构建的真实文件


其他一些小的改进是可能的。我会考虑BootstrapCL,以及它是否生成了一个可以用作真正目标的文件。

问题是,您没有所有的配方,也没有一个匹配任何内容的%规则。当Make完成了先决条件${BINS}时,它会尝试构建全部,寻找适合的配方,并找到%

至少有两种方法可以解决这个问题。快速而肮脏的方法是为所有以下内容添加一个空配方:

在我看来,另一个更好的方法是收紧第二条规则:

BINS := $(SRCS:%.csv=%.phony)

all: ${BINS}

%.phony: BootstrapCL.c
    gcc -Wall BootstrapCL.c  -lm -o BootstrapCL
    ./BootstrapCL $*.csv $*
为了保持整洁,我建议您也添加以下行:

.PHONY: $(BINS)
让他们知道.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的BINS目标,但首先需要BootstrapCL-这将为每个.csv文件运行一次。 您有一个生成BootstrapCL可执行文件的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的BINS目标,但首先需要BootstrapCL-这将为每个.csv文件运行一次。 您有一个生成BootstrapCL可执行文件的BootstrapCL目标,它将只运行一次。 %规则太笼统,捕获所有内容,甚至尝试重新生成生成文件本身。此外,它每次都编译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发生更改时重新生成它们:

%规则太笼统,捕获所有内容,甚至尝试重新生成生成文件本身。此外,它每次都编译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发生更改时重新生成它们:


谢谢你的回答;它帮助我更好地理解正在发生的事情;现在我只有一个疑问。当Make完成了先决条件${BINS}时,它将尝试构建所有。但是所有的都没有一个配方,那么为什么要将分配给另一个目标${BINS}的所有配方呢;它帮助我更好地理解正在发生的事情;现在我只有一个疑问。当Make完成了先决条件${BINS}时,它将尝试构建所有。但是all没有一个菜谱,那么为什么要将assign分配给另一个目标${BINS}的所有菜谱呢?为什么BootstrapCL目标将以这种方式仅运行一次?因为创建BootstrapCL的规则已定义-因此,一旦文件BootstrapCL存在,make将看到它存在,并且如果时间戳比源文件新,则不会再次尝试创建它。这是makefile的一个关键特性
s、 感谢您的澄清为什么BootstrapCL目标将以这种方式仅运行一次?因为创建BootstrapCL的规则已定义-因此,一旦文件BootstrapCL存在,make将看到它存在,并且如果时间戳比源文件新,则不会再次尝试创建它。这是makefiles的一个关键特性。感谢您的澄清