感谢支持
我们一直在努力

Makefile,Linux程序员你伤不起

1. 概述


Makefile,what??很多Windows程序可能都没听说过
简单的说,Makefile是Unix/Linux环境下描述了整个工程的编译、连接等规则的文件,其主要包括三点:
1) 工程中的哪些源文件需要编译以及如何编译
2) 依赖库以及库所在的位置
3) 想得到什么:可执行文件?静态库?动态库?
项目中,我们会有很多源文件、头文件、依赖库文件、配置文件等等,通过Makefile定义规则来制定编译顺序,编译规则,编译依赖,甚至更复杂的功能,将极大的方便我们的开发,其最大的好处就是”自动化编译“,通过‘make’就可以方便的进行整个项目的编译工作。


2. 编译链接


从源码到可执行文件,具体步骤:
源码—>预处理—>编译—>汇编—>链接
我们常常把预处理、编译和汇编三个阶段统称为编译阶段,在这个阶段,编译器会检查程序语法、函数与变量是否声明等。
经过编译之后,unix/linux下,将得到.o文件(一般来说,每个源文件都能生成一个对应的.o文件),即object file(windows下即.obj文件),.o不能直接运行,我们需要将其合成可执行文件,这个过程就叫链接。在链接过程,链接器会在所有的.o文件中找寻函数的实现,如果找不到,则会报链接错误。


3.Makefile规则


Makefile只有一个规则:


target: prerequisites
command

target:即目标,它可以是可执行文件、可以是.o文件,也可以是一个标签,简单的说,它就是你要做的事情。
prerequisites:生成target所需要的条件,它可以是一个文件,也可以是另外一个target
command:具体执行的命令


解释如下:target这个目标依赖于prerequisites中的文件,其生成规则定义在command中。
更简单一点表达:如果prerequisites中任何一个文件的时间要比target文件更新的话,command所定义的命令就会执行。


eg:
=====makefile=====
#第一个规则
test: main.o hello.o
gcc main.o hello.o –o test


#第二个规则
main.o: main.c
gcc –c main.c

#第三个规则
hello.o: hello.c hello.h
gcc –c hello.c

#第四个规则
clean :
rm –rf *.o
rm –rf test
=====makefile=====

第一个规则:
test就是target, main.o和hello.o是prerequisites,’gcc main.o hello.o –o test’是command。
即:要生成test,就需要有main.o和hello.o,如果main.o或者hello.o文件的时间比test新(或者test文件不存在),则会执行命令’gcc main.o hello.o –o test’,


第二个规则:
target是main.o,main.c是prerequisites,’gcc –c main.c’是command
即:要生成test,就需要main.c,如果main.c文件的时间比main.o新,则会执行’gcc –c main.c’


第三个规则和第二个规则类似


第四个规则:
这里,target是clean,此处,clean并不是一个文件,而是一个动作的名字,它的执行,需要显示的在make命令后制定,例如,此处执行‘make clean’,将调用其后的command,即‘rm –rf *.o rm –rf test’,另外,此处没有prerequisites,即任何时候都执行command


我们来看下如果执行’make’会做什么:


1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。
3、如果test文件不存在,或是test所依赖的后面的[.o]文件的文件修改时间要比test这个文件新,那么,他就会执行后面所定义的命令来生成test这个文件。
4、如果test所依赖的.o文件存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。
5、依次类推,直到生成的所有的target都是最新的。


用户如果执行’make clean’,由于其后面没有依赖,则执行command所定义的命令。


如果我们修改了代码main.c,然后执行‘make’,由于main.c时间比main.o新,那么main.o会重新编译生成,由于main.o文件的时间比test新,那么test也会重新生成。

4. 一个好用的Makefile模板


  1. ######################################################################  

  2. #   makefile 模版  

  3. #  

  4. ######################################################################  

  5.   

  6. ###################项目路径和程序名称#################################  

  7. DIR=$(shell pwd)  

  8. BIN_DIR=$(DIR)/bin  

  9. LIB_DIR=$(DIR)/lib  

  10. SRC_DIR=$(DIR)/src  

  11. INCLUDE_DIR=$(DIR)/include   

  12. OBJ_DIR=$(DIR)/obj  

  13. DEPS_DIR=$(DIR)/deps  

  14. #PROGRAM=$(BIN_DIR)/test  

  15. PROGRAM=$(BIN_DIR)/test  

  16.   

  17. ###################OBJ文件及路径############################################  

  18. EXTENSION=cpp  

  19. OBJS=$(patsubst $(SRC_DIR)/%.$(EXTENSION), $(OBJ_DIR)/%.o,$(wildcard $(SRC_DIR)/*.$(EXTENSION)))  

  20. DEPS=$(patsubst $(OBJ_DIR)/%.o, $(DEPS_DIR)/%.d, $(OBJS))  

  21.   

  22. ###################include头文件路径##################################  

  23. INCLUDE=\  

  24.         -I$(INCLUDE_DIR)  

  25.           

  26. ###################lib文件及路径######################################  

  27.   

  28. ###################编译选项及编译器###################################  

  29. CC=g++  

  30. CFLAGS=-Wall -W -g   

  31. LDFLAGS=  

  32.   

  33. ###################编译目标###########################################  

  34. .PHONY: all clean rebuild  

  35.   

  36. all:$(OBJS)   

  37.     @echo $(DEPS_DIR)  

  38.     $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)   

  39.   

  40.   

  41. $(DEPS_DIR)/%.d: $(SRC_DIR)/%.$(EXTENSION)  

  42.     $(CC) -MM $(INCLUDE) $(CFLAGS) {1}lt; | sed -e 1’s,^,$(OBJ_DIR)/,’ > $@  

  43.   

  44. sinclude $(DEPS)  

  45.   

  46. $(OBJ_DIR)/%.o:$(SRC_DIR)/%.$(EXTENSION)   

  47.     $(CC) {1}lt; -o $@ -c $(CFLAGS) $(INCLUDE)   

  48.   

  49. rebuild: clean all  

  50.   

  51. clean:  

  52.     rm -rf $(OBJS)  $(PROGRAM)  
工作目录结构:
bin  deps  include  lib  Makefile  obj  src



5. 结语


以上只是Makefile的冰山一角,有兴趣的同学可以看下make的info pages。


Makefile可以很方便的维护中小型项目,但是,在项目大到一定程度,存在众多依赖之后,人力维护Makefile也是一件极为困难的事情。目前有一些自动化的工具,例如Automake,就是一个极好的工具。

赞(0) 打赏
转载请注明出处:服务器评测 » Makefile,Linux程序员你伤不起
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏