CFLAGS=-std=c99 -Wall
CC=gcc
hangman: hangman.o hangman.c
$(CC) $(CFLAGS) hangman.o hangman.c -o hangman
hangman.o: hangman.c
$(CC) $(CFLAGS) -c hangman.c
clean:
rm -f hangman *.o
好吧,hangman
(程序二进制文件)只依赖于hangman.o
,而不是hangman.c
,它已经被编译成hangman.o
(在编译阶段)。
在Makefile
中,您只声明直接依赖关系,而make(1)
完成其余的工作。
我用于在变量中为程序指定所有对象,因为它们将被多次使用。 这样:
# Makefile -- make file for hangman.
targets = hangman
hangman_objs = hangman.o
hangman: $(hangman_objs)
$(CC) $(LDFLAGS) -o hangman $(hangman_objs)
没有别的,因为make(1)
有一个自动规则,那就是
.c.o:
$(CC) $(CFLAGS) -o $@ -c $<
这相当于这个规则:
hangman.o: hangman.c
$(CC) $(CFLAGS) -o hangman.o -c hangman.c
(对于您可以拥有的每个.c
和.o
文件也是如此。
顺便说一下,您收到的错误是make找到了对hangman.c
的依赖关系,但没有找到任何名为hangman.c
的文件,因此需要构建它,但您不提供此文件。 您可能已经删除了hangman.c
文件(如果您在Makefile
中拼错了文件,有时会发生这种情况,以消除对您重要的文件) 在这种情况下,它尝试构建handman
这取决于handman.o
取决于handman.c
,所以没有找到handman.c
make(1)
说, 我对handman.c
有依赖关系,但没有找到这样的文件(而且我没有依赖关系可以让我构建它)
如果您的项目是单个源项目,则可以避免生成hangman.o
并创建如下所示的Makefile
:
hangman: hangman.c
$(CC) $(CFLAGS) $(LDFLAGS) -o hangman hangman.c
它声明了从二进制到源代码的显式直接引用。 在这种情况下,您不会使用编译器的-c
标志进行编译,也不要链接,并使用一个命令直接生成可执行文件。 这在大型项目中不使用,因为通常您只想编译已更改的源代码。 如本例所示:
hangman_objs = hang.o man.o foo.o bar.o a.o b.o c.o
hangman: $(hangman_objs)
$(CC) $(LDFLAGS) -o hangman $(hangman_objs)
如果展开变量,将得到以下规则:
hangman: hang.o man.o foo.o bar.o a.o b.o c.o
cc -o hangman hang.o man.o foo.o bar.o a.o b.o c.o
#all this are automatic dependencies generated from
# .c.o:
# $(CC) $(CFLAGS) -c $< -o $@
# for the files hang.o man.o foo.o bar.o a.o b.o c.o
hang.o: hang.c
cc -O2 -pipe -c hang.c -o hang.o
man.o: man.c
cc -O2 -pipe -c man.c -o man.o
foo.o: foo.c
cc -O2 -pipe -c foo.c -o foo.o
bar.o: bar.c
cc -O2 -pipe -c bar.c -o bar.o
a.o: a.c
cc -O2 -pipe -c a.c -o a.o
b.o: b.c
cc -O2 -pipe -c b.c -o b.o
c.c: c.c
cc -O2 -pipe -c c.c -o c.o
但是,在程序的链接阶段,不得同时使用目标代码和源代码。 编译器将链接您hangman.o
提供的文件,并对其进行编译(这会生成新的hangman.o
),并将尝试链接两者(同一代码的两个版本),这可能会产生新的错误。
我对你的程序的方法是:
# main targets to build (programs)
targets = hangman
# toclean maintains everything must be erased on clean.
toclean = $(targets)
# object files of hangman target
hangman_objs = hangman.o foo.o
# add all those objects to the toclean variable.
toclean += $(hangman_objs)
# libraries
hangman_ldflags = -L path/to/libbar
hangman_libs = -lbar
# main target all
all: $(targets)
# ... and clean
clean:
rm -f $(toclean)
# just the link phase, the compiling is automatically done.
hangman: $(hangman_objs)
$(CC) $(LDFLAGS) $($@_ldflags) -o $@ $($@_objs) $($@_libs)