首页 > 解决方案 > 没有规则可以使“out”需要目标“main.o”。停止

问题描述

我不断收到此错误,我无法弄清楚我做错了什么。我正在使用一个模板,所以我可以在 dir bin 中获取可执行文件。目录包括头文件。创建的目标文件的 dir obj 和 .c 文件的 src。

我的生成文件

OBJ_dir = obj
INC_DIR = include
OBJECTS = main.o client.o private.o memory.o process.o proxy.o server.o
main.o = main.h memory-private.h stdio.h stdlib.h string.h syscall.h unistd.h wait.h sysexits.h memory.h 
client.o = client.h
private.o = private.h
memory.o = memory.h memory_private.h
process.o = process.h
proxy.o = proxy.h
server.o = server.h
CC = gcc
CFLAGS = -Wall –I $(INC_DIR)
LIBS = -lm

out: $(OBJECTS)
    $(CC) $(addprefix $(OBJ_dir)/,$(OBJECTS)) -o bin/out $(LIBS)

%.o: src/%.c $($@)
    $(CC) $(CFLAGS) -o $(OBJ_dir)/$@ -c $<

clean:
    rm –f *.o out
    rm –f out

标签: cmakefile

解决方案


这里有很多问题。至少阅读GNU make 手册的前几章以了解 make 和 makefile 的工作方式可能是一个好主意。

采取这条规则:

out: $(OBJECTS)
        $(CC) $(addprefix $(OBJ_dir)/,$(OBJECTS)) -o bin/out $(LIBS)

首先,列出与您实际构建的文件不同的目标是不正确的。在这里,您告诉 make 您将构建一个名为 的目标out,但您的配方实际上构建了一个名为bin/out. 那是错误的。

其次,但类似地,让您的目标依赖于一组先决条件(由 定义的文件$(OBJECTS))但随后让您的规则配方使用一组完全不同的先决条件(通过$(OBJ_dir)/为所有文件添加前缀)是不正确的。

这告诉 make “请构建文件main.o,client.o等,但我的命令实际使用的是文件obj/main.o,obj/client.o等”。告诉 make 构建您不会实际使用的目标是没有意义的。

这应该是:

bin/out: $(addprefix $(OBJ_dir)/,$(OBJECTS))
        $(CC) $^ -o $@ $(LIBS)

一般来说,如果您发现自己编写了一个配方,其中您正在修改自动变量,$@或者$^没有按原样使用它们,那么您几乎肯定做错了什么。

接下来,您的模式规则还有其他问题:

%.o: src/%.c $($@)
        $(CC) $(CFLAGS) -o $(OBJ_dir)/$@ -c $<

首先,您不能像$@在先决条件列表中那样使用自动变量。这些值仅在扩展规则的配方时设置。在评估先决条件列表时,它们没有设置(空)。所以$($@)在这里扩展为空字符串并且什么都不做。

其次,您遇到与上述相同的问题,您不是在创建$@而是在创建$(OBJ_dir)/$@,这是错误的。你应该这样写你的规则:

$(OBJ_dir)/%.o: src/%.c
        $(CC) $(CFLAGS) -o $@ -c $<

以便目标列出您要构建的文件,并且配方$@无需修改即可使用。

至于您的先决条件,您应该直接创建它们,而不是尝试使用花哨的变量(这是行不通的)。正如上面的评论所暗示的,只需更改:

proxy.o = proxy.h

至:

proxy.o : proxy.h

(以及所有其他),它会工作。bin/out但是请注意,make 总是构建它默认看到的第一个显式目标,因此如果您想成为默认目标,您可能需要稍微重新安排您的 makefile 。


推荐阅读