我正在尝试使makefile将目标文件编译到obj
目录中,然后链接已编译的代码,然后将其转换为可执行文件。
CC=gcc
CFLAGS=-Iinclude.
OBJ = obj/main.o obj/print.o
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
prog: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
,错误是“ prog”需要目标“ obj / main.o”没有规则。停止。 这是我在makefile教程中完成的纯复制粘贴,目的是确保它也无法正常工作。
那为什么这行不起作用
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
答案 0 :(得分:1)
这种规则...
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
非常好(对于GNU make,在其他make
实现中就没有那么多了)。它从相应的.o
文件构建一个.c
文件,其中“相应”表示具有通过将结尾的.o
更改为.c
而形成的名称。不过,实际上并不需要这样做,因为make
具有一个内置的规则,可以执行基本上相同的操作。
消息
'prog'不需要创建目标'obj / main.o'的规则。停止。
将obj/main.o
标识为目标prog
所需的先决条件,该目标不存在且没有[适用]规则。如果存在对应的来源(按照上述意义),则上面的模式规则将适用,但显然没有。
要绝对清楚:将.o
中的obj/main.o
替换为.c
形成的相应源是obj/main.c
。除非存在这样的文件,否则您提供的模式规则不适用于构建obj/main.o
。 make
程序本身并不真正了解或关心目录。它执行的命令可以执行,但是对于make
本身,目标和先决条件标识符只是字符的平面序列。
我对这类事情的第一个建议是不要试图变得可爱。在与目标文件源相同的目录中构建目标文件是最简单,最常见的。假设您的C源代码位于相对于makefile的src/
子目录中,则该makefile就足够了(依赖于内置的.c.o规则):
CC=gcc
CFLAGS=-Iinclude.
prog: src/main.o src/print.o
$(CC) -o $@ $^ $(CFLAGS)
但是,如果您坚持将对象编译到单独的目录中,则您的模式规则需要反映出这一点:
CC=gcc
CFLAGS=-Iinclude.
OBJ = obj/main.o obj/print.o
obj/%.o: src/%.c
$(CC) -c -o $@ $< $(CFLAGS)
prog: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)