gpt4 book ai didi

c - Makefile 只执行一次命令

转载 作者:太空宇宙 更新时间:2023-11-04 01:47:08 26 4
gpt4 key购买 nike

我正在使用 MinGW(Windows 8.1,GCC 7.3.0)的 Makefile 构建一个中型项目,自动检测文件夹 src 下的所有源文件并将所有目标文件编译到 obj 文件夹,但不幸的是它只对第一个检测到的文件执行命令并在那里停止。

这是我第一次为一个源文件之外的任何东西编写 Makefile 脚本,也许我弄错了一些规则。提前致谢!

CC   := gcc

SRC := src
OBJ := obj

MAIN := main
PACK := libbundle

SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(patsubst $(SRC)/%.c,$(OBJ)/%.o, $(SOURCES))
CFLAGS := -I$(SRC)

$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $< -o $@

# build:
# ar rcs $(PACK).a $(OBJECTS)
# $(CC) -shared -o $(PACK).so $(OBJECTS)
# $(CC) -o $(MAIN).c $(PACK).so

输出:

gcc -Isrc -c src/firstsource.c -o obj/firstsource.o

...到此为止!

最佳答案

问题 - 具有多个目标的规则

你的规则

$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $< -o $@

多个目标。我认为这在这里不合适。参见讨论 here具有多个目标的规则在哪里有用。

此外,此规则指定了多个先决条件 - 但 $< 仅代表第一个先决条件。您可以使用 $+捕获所有 先决条件 - 但随后您将失去使用 -o 的能力选项。如果您想使用多个先决条件,请参阅下文。

什么$(OBJECTS): $(SOURCES)详细的意思

例如,假设您的 src/目录包含 firstsource.csecondsource.c .那么你的变量就变成了

$(SOURCES) -> src/firstsource.c src/secondsource.c
$(OBJECTS) -> obj/firstsource.o obj/secondsource.o

(实际上 - 并且有些不直观 - firstsource 将被放置在 secondsource 之后,但为了简单起见,让我们忽略它。)

所以规则

$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $< -o $@

相当于

obj/firstsource.o obj/secondsource.o: src/firstsource.c src/secondsource.c
$(CC) $(CFLAGS) -c $< -o $@

反过来,这条规则等同于两条规则(因为它有多个目标)——每个都有相同的先决条件:

obj/firstsource.o: src/firstsource.c src/secondsource.c
$(CC) $(CFLAGS) -c $< -o $@

obj/secondsource.o: src/firstsource.c src/secondsource.c
$(CC) $(CFLAGS) -c $< -o $@

你能看出这里的问题吗?

$<表示仅第一个先决条件,第一个规则的配方变为

    gcc -Isrc -c src/firstsource.c -o obj/firstsource.o

对于第一条规则没问题,但对于第二条规则就不行了

    gcc -Isrc -c src/firstsource.c -o obj/secondsource.o

因为您使用了错误的输入文件。

顺便说一下......你提到过

unfortunately it [i.e. make] is only executing the command over the first detected file and stops there.

这是因为 - 当您调用 make没有任何参数 - 它调用文件中的第一条规则,仅此而已。

选项 1:使用多个规则

这里更合适的是多条规则——每条规则只有一个单一目标。因此,请尝试将上面的内容替换为以下内容。

$(OBJ)/%.o: $(SRC)/%.c
$(CC) $(CFLAGS) -c $< -o $@

compile-only: $(OBJECTS)

您可以调用 make在这个修改后的 Makefile 上作为

make -B compile-only

选项 2:具有多个先决条件的单一目标

如果您的目标中有多个先决条件,您可以使用特殊变量 $+ 在您的配方中引用它们.但是,您不能使用 -o在这种情况下的选项 - 所以将无法指定目标文件的输出目录。 (要解决此问题,您可以在编译前将 cd 转到 obj 目录 - 但随后您需要调整 SOURCES 变量。)

CC := gcc
CFLAGS := -Isrc
SRC := src

SOURCES := $(wildcard $(SRC)/*.c)

myobjs: $(SOURCES)
$(CC) $(CFLAGS) -c $+

这会将所有目标文件放在顶级目录中。如前所述,您可以调整 SOURCEScd obj如果必须将目标文件放在单独的目录中,则目录。

旁白 - 模式规则的预定义配方

我理解像您所做的那样将构建输出放在单独目录中的基本原理,但是 - 如果您愿意将构建输出放在与源文件相同的目录中 - 您可以使用 make 简化您的 Makefile的 predefined pattern rules .

SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(SOURCES:.c=.o)

compile: $(OBJECTS)

关于c - Makefile 只执行一次命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51578108/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com