我的工作目录是这样的:
- c
- Makefile
- my_memmove.h
- my_memmove.c
- c-timer-lib
- timer.c
- timer.h
我的makefile是这样的:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib
TARGET := output
output: main.o my_memmove.o timer.o
$(CC) $(CFLAGS) main.o my_memmove.o timer.o -o $(TARGET)
main.o: main.c
gcc -c main.c
my_memmove.o: my_memmove.c my_memmove.h
gcc -c my_memmove.c
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $@
clean:
rm *.o $(TARGET)
我不明白为什么我总是得到"Makefile: No rule to make target 'timer.c',而'timer.o'需要。停止!"错误。我认为这是因为找不到timer.c和timer.h文件。
这里太混乱了!:)
首先,这肯定是错误的:
$(CC) $(CFLAGS) -I main.o ...
-I main.o
告诉编译器它应该使用main.o
作为目录名来搜索包含文件。这显然行不通。你应该去掉这里的-I
。
关于你的问题:你必须意识到这里有两个完全不同的程序在起作用:make
计算如何运行命令,以及正在运行的命令,在这种情况下是编译器gcc
。
-I
选项是编译器的一个选项,以便编译器知道在哪里查找包含在源代码中的#include
头文件。
这个选项没有任何意义;它不理解这个选项。它只是传递给编译器的一些文本。Make正在寻找源文件timer.c
,它找不到它,因为你没有告诉Make它在哪里。
你必须把你的规则写在正确的位置,像这样:
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $@
(您应该始终使用-o $@
,以便您的编译行将输出文件放在make期望找到它的地方,在计算配方之前,make将输出文件放入$@
变量中。)
埃塔
另外,你确定-DUNITS="ms"
是正确的吗?如果没有看到UNITS
在源代码中是如何使用的,我们无法判断,但我怀疑您可能需要在这里添加额外的引号,如-DUNITS='"ms"'
真的,你在这个makefile中做了太多的事情。Make已经知道如何正确地从源文件构建目标文件。如果您不通过编写自己的规则来强制解决这个问题,那么make的内置规则将为您完成这项工作。你的makefile可以这样写:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib -DUNITS='"ms"'
TARGET := output
$(TARGET): main.o my_memmove.o c-timer-lib/timer.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
my_memmove.o: my_memmove.h
c-timer-lib/timer.o: c-timer-lib/timer.h
clean:
rm *.o $(TARGET)
make不知道你的源代码需要哪些头文件,所以你必须手动添加先决条件,尽管你可以添加额外的规则,让它自己计算出来。