读书人

Makefile的编纂

发布时间: 2012-08-15 16:57:17 作者: rapoo

Makefile的编写

Makefile的编写
?
开始使用Linux编程时,一个很讨厌的问题就是如何写Makefile文件,由于在Linux下不像在Windows下那么熟悉,有那么多好的软件(也许是对Linux孤陋寡闻了)。虽然象Kylix和Anjuta这样的集成编译环境,但是Kylix太大太慢,用它编写console程序不亚于高射炮打蚊子——大材小用,而Anjuta又太不稳定,况且字体有那么难看。不说了,还是言归正传,看看Makefile该如何编写。
?
1. 简单的GCC语法:
如果你只有一个文件(或者只有几个文件),那么就可以不写Makefile文件(当然有Makefile更加方便),用gcc直接编译就行了。在这里我们只介绍几个我经常用的几个参数,第一是 “-o”,它后面的参数表示要输出的目标文件,再一个是 “-c”,表示仅编译(Compile),不连接(Make),如果没有”-c”参数,那么就表示连接,如下面的几个命令:
gcc c test.c,表示只编译test.c文件,成功时输出目标文件test.o
gcc c test.c o test.o ,与上一条命令完全相同
gcc o test test.o,将test.o连接成可执行的二进制文件test
gcc o test test.c,将test.c编译并连接成可执行的二进制文件test
gcc test.c o test,与上一条命令相同
gcc c test1.c,只编译test1.c,成功时输出目标文件test1.o
gcc c test2.c,只编译test2.c,成功时输出目标文件test2.o
gcc o test test1.o test2.o,将test1.o和test2.o连接为可执行的二进制文件test
gcc c test test1.c test2.c,将test1.o和test2.o编译并连接为可执行的二进制文件test
注:如果你想编译cpp文件,那么请用g++,否则会有类似如下莫名其妙的错误:
cc3r3i2U.o(.eh_frame+0x12): undefined reference to `__gxx_personality_v0’......
还有一个参数是”-l”参数,与之紧紧相连的是表示连接时所要的链接库,比如多线程,如果你使用了pthread_create函数,那么你就应该在编译语句的最后加上”-lpthread”,”-l”表示连接,”pthread”表示要连接的库,注意他们在这里要连在一起写,还有比如你使用了光标库curses,那么呢就应该在后面加上”-lcurses”,比如下面的写法:
gcc o test test1.o test2.o lpthread lcurses
当然gcc的参数我感觉有几百个,不过我们平时在x86机器上用的就这么些,况且这里也不是GCC教程,所以,就此打住。
?
2. Makefile基本语法
我这里没有Makefile的详细设计书,只是凭着看别人的Makefile文件和一些网上的参考资料,作一些简单的介绍(我自己理解的,不对的地方还请各位老大们指出,鄙人将不甚感激)
2.1 目标:
大家在看别人使用Makefile文件时肯定经常见到有的人常用make all, make install, make clean等命令,同样只有一个Makefile文件,那么all、install、clean参数是如何控制Makefile文件的运行呢(这句话有问题,但我不知道该怎么说,大家能看懂我的意思,就放我一马吧)?在这里,如果向上面的命令如果能够正确运行的话,那么在Makefile文件里一定有这样的几行,他们的开始一定是
all: ×××××××
?????? ×××××××××××
install: ××××××
?????? ×××××××××××
clean: ×××××××××
??????? ×××××××××××
当然也不尽然,因为all,install,clean我们可以用其他的变量来代替,但是着了我们就简单起见,就下定论了,各位别怪。
在上面提到的all,install,clean等就是我们所说的目标。make all命令,就告诉make我们将执行all所指定的目标。为了便于理解Make程序的流程,我们给大家看一个与gcc毫无关系的Makefile文件:
# #表示Makefile文件中的注释,下面是Makefile文件的具体内容
all:
??????? @echo you have typed command “make all”
clean:
??????? @echo you have typed command “make clean”
install:
??????? @echo you have typed command “make $@”
#Makefile文件结束
注意在这里,all:、clean:、install:行要顶格些,而所有的@echo前要加tab键来跳格缩进。下面是运行结果:
[root@xxx test]#cat Makefile
# #表示Makefile文件中的注释,下面是Makefile文件的具体内容
all:
??????? @echo you have typed command “make all”
clean:
??????? @echo you have typed command “make clean”
install:
??????? @echo you have typed command “make $@”
[root@xxx test]#make all
you have typed command “make all”
[root@xxx test]#make clean
you have typed command “make clean”
[root@xxx test]#make install
you have typed command “make install”
[root@xxx test]#
不知大家注意到没有,我们在Makefile文件里有一个符号$@,其中$表示变量名,其后的要当作变量来解释,$@是Makefile预先定义的一个变量,表示目标命令,比如在上面的文件里属于install目标,那么$@就表示install,同样,如果你将clean目标下面的加引号的”make clean”换为:”make $@”,那么命令make clean的输出与原来是一摸一样的。大家可以下来试试。
2.2 依赖
我们现在提出这样一个问题:我如何用一个make命令将替代所有的make all, make install,make clean命令呢?当然我们可以象刚才那样写一个Makefile文件:
[root@xxx test]#cat Makefile
# #表示Makefile文件中的注释,下面是Makefile文件的具体内容
all:
??????? @echo you have typed command “make all”
clean:
??????? @echo you have typed command “make clean”
install:
??????? @echo you have typed command “make $@”
doall:
??????? @echo you have typed command “make $@l”
??????? @echo you have typed command “make all”
??????? @echo you have typed command “make clean”
??????? @echo you have typed command “make install”
[root@xxx test]#make doall
you have typed command “make doall”
you have typed command “make all”
you have typed command “make clean”
you have typed command “make install”
[root@xxx test]#
在这里,doall:目标有4调语句,他们都是连在一起并都是由tab键开始的。当然,这样能够完成任务,但是太笨了,我们这样来写:
[root@xxx test]#cat Makefile
# #表示Makefile文件中的注释,下面是Makefile文件的具体内容
all:
??????? @echo you have typed command “make all”
clean:
??????? @echo you have typed command “make clean”
install:
??????? @echo you have typed command “make $@”
doall: all clean install
??????? @echo you have typed command “make $@l”
[root@xxx test]#make doall
you have typed command “make all”
you have typed command “make clean”
you have typed command “make install”
you have typed command “make doall”
[root@xxx test]#
相信大家已经看清了doall:的运行方式,它先运行all目标,然后运行clean目标,然后是install,最后是自己本身的目标,并且每个$@还是保持着各自的目标名称。
在这里,我们称all, clean, install为目标doall所依赖的目标,简称为doall的依赖。也就是你要执行doall,请先执行他们(all, clean, install),最后在执行我的代码。
注意依赖一定是Makefile里面的目标,否则你非要运行,结局是注定的:
[root@xxx test]#cat Makefile
all:
??????? @echo you have typed command “make all”
xxx: all WAHAHA:
[root@xxx test]make xxx
you have typed command “make all”
make: *** No rule to make target ‘WAHAHA’, needed by `xxx’, Stop.
【轻松一下】我们能否利于“相互依赖”来作弄一下make?
[root@xxx test]#cat Makefile
tar1: tar2
tar2: tar1
??????? @echo this line cann’t be shown on you screen!
[root@xxx test]make tar1
make: Circular tar2 <- tar1 dependency dropped.
呵呵,骗不了的
?
3.实战:
有了上面的说明,我们就可以开始写一些弱智一些地Makefile文件了。比如我们有如下的文件:
tmp/
?? +---- include/
?? |????? +---- f1.h
?? |????? +----f2.h
?? +----f1.c
?? +----f2.c
?? +---main.c
其中f1.c中#include “include/f1.h”,f2.c中#include”include/f2.h”,main.c中又#include”include/f1.h”, #include”include/f2.h”,主函数在main.c中,要将他们联合起来编译为目标为testmf的文件,我们就可以按下面的方式写(当然是弱智的):
[root@xxx test]#cat Makefile
main: main.o f1.o f2.o
??????? gcc o testmf main.o f1.o f2.o
f1.o: f1.c
??????? gcc c o file1.o file1.c
f2.o: f2.c
??????? gcc c o file2.o file2.c
main.o
??????? gcc c o main.o main.c
clean:
??????? rm rf f1.o f2.o main.o testmf
[root@xxx test]make
gcc c o main.o main.c
gcc c o file1.o file1.c
gcc c o file2.o file2.c
gcc o testmf main.o f1.o f2.o
[root@xxx test]ls
f1.c f1.o f2.c f2.o main.c main.o include/ testmf
如果你的程序没有问题的话,就应该可以执行了./testmf
大家可能发现问题了:对目标文件f1.o f2.o和main.o,他们的写法是如此的类似,我们能够将他们一块写?有的,不过今天没时间了,以后再写吧。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Mr_HongYe/archive/2007/09/02/1768833.aspx

读书人网 >操作系统

热点推荐