在这里,我自己写一个自己的Makefile的例子,说明一下Makefile是怎么写的。
准备工作:为了使我们的代码更加接近真实的大型程序,我们可以从网络上下载一些写好的源代码。我所使用的是 “Unix Network Programming” 这本书中的源代码。代码下载地址为:www.unpbook.com,下载的文件为unpv13e.tar.gz。使用命令 tar –zxvf unpv13e.tar.gz 直接解压就可以。解压之后按照README文件先编译一下(也可以不用做这一步,直接看下面的内容,如果在unpv13之下没有libunp.a这个文件再做这一步)。
进入目录,我们来建立一个自己的Makefile文件,自己编译自己的程序。
在unpv13e/ 这个目录内建立自己的一个目录。 拷贝unpv13e/tcpcliserv/ 目录下的 tcpserv01.c 和 str_echo08.c 到自己建立的目录下,给他们命名为tcpserv.c 和 str_echo.c。 并在这个目录下建立自己的Makefile文件。
首先,在目录 ~/unp/unpv13e/test/tcpserv 这个文件夹下写自己的程序,有两个文件,tcpserv.c 和 str_echo.c,还有自己写的Makefile 文件:
test@Ubuntu:~/unp/unpv13e/test/tcpserv$ ls Makefile str_echo.c tcpserv.c
tcpserv.c 和 str_echo.c这两个文件都是用 unp.h 这个头文件,而这个文件的位置在 ~/unp/unpv13e/lib/ 这个目录中。它们不再调用其他头文件。
tcpserv.c 的开头为:
#include "unp.h"
str_echo.c 的开头为:
#include "unp.h"
在unp.h中,它自己又使用其它的头文件:
#include "../config.h" /* configuration options for current OS */ #include <sys/wait.h> /* soem other headers …… */ # include "../lib/addrinfo.h"
我的Makefile 文件是这样写的:
CC = gcc CFLAGS = -I../../lib -Wall tcpserv: tcpserv.o str_echo.o $(CC) $(CFLAGS) -o $@ $^ ../../libunp.a .PHONY: clean clean: -rm *.o tcpserv
其中 –I../../lib 标记表示gcc 编译的时候,以Makefile文件所在的目录为基准,在目录 ../../lib 中查找头文件,也就是在~/unp/unpv13e/lib/ 这个文件中查找。../../lib是一个相对路径,你也可以把它换成绝对路径,比如 –I/home/test/unp/unpv13e/lib
-Wall 选项进行更好的判断。
$@ 表示target,这里即tcpserv
$^ 表示所有 依赖关系,这里即tcpserv.o 和 str_echo.o
../../libunp.a 是一个库文件(在Unix中叫做Archive File),里面放有很多自己定义的函数,我在tcpserv.c 和 str_echo.c 中都使用到了这些函数。.a 文件是把好多 .o 文件合在一起构成的一个文件,它并不依赖于.c源文件的存在。
.PHONY: clean 是指定clean为伪目标,即clean是一个假的target,make命令不会生成这个文件。
rm命令之前有一个小小的减号,表明忽略错误,继续执行。
如果rm之间没有减号,那么一旦出错,就会停止执行。看下面的代码:
clean: rm *.o rm tcpserv
在终端中运行 make clean 命令,如果当前目录下只有tcpserv.c str_echo.c Makefile 这三个文件,那么就会出现下面的情况:
rm *.o
rm: 无法删除 “*.o”: 没有那个文件或目录
make: *** [clean] 错误 1
编好自己的Makefile 之后,可以在终端中运行 make –n 命令查看自己所写的Makefile 文件会执行哪些命令,这可以用来判断我们的Makefile是否正确。
使用make 命令进行编译。