Makefile 入门
来源:互联网 发布:avscanner是什么软件 编辑:程序博客网 时间:2024/04/29 15:58
原文链接:http://harttle.com/2014/01/01/makefile.html
make
是软件开发中常用的工具程序(Utility software),常被用来构建C程序。make
通过读取叫做“makefile”的文件,来自动化建构软件。
虽然
make
常被用来构建C程序,但它可用于绝大多数的文件处理过程。例如,更新一批图片的缩略图: http://harttle.github.io/2013/10/26/auto-thumb/
它是一种转化文件形式的工具,转换的目标称为“target”;
与此同时,它也检查文件的依赖关系,如果需要的话,它会调用一些外部软件来完成任务。
它的依赖关系检查系统非常简单,主要根据依赖文件的修改时间进行判断。
大多数情况下,它被用来编译源代码,生成结果代码,然后把结果代码连接起来生成可执行文件或者库文件。
它使用叫做Makefile
的文件来确定一个target文件的依赖关系,然后把生成这个target的相关命令传给shell去执行。
中文Tutorial
基本知识
编译
对于C语言,产生可执行程序包括这样的步骤:
1. 预处理源文件(.c
)
* 替换预处理命令(如 #define
)
* 展开头文件(.h
,包括静态链接库的头文件)到引用的源文件
2. 依次编译处理过的源文件,然后进行汇编,生成对应的目标文件(.o
)
3. 链接(静态链接)目标文件和静态链接库(静态链接库的源文件生成的目标文件,.a
),生成可执行的二进制文件。
gcc
不会自动链接到静态链接库(libstdio.so
除外),需要以参数的形式指定。g++
会自动解析并进行链接。动态链接库(.so
)则是运行时由操作系统解析的。
示例
target: require1 require2 shell command
make
命令会寻找当前目录下的 makefile,寻找其中的第一条规则,然后执行 shell command
来生成 target
。如果发现 requireN
同时也依赖于其他项,则会自动调用其对应的 shell command
并生成它。另外,在整个过程中,make
会比较 target
与 requireN
的时间戳,以判断是否需要重新生成。
变量
变量的定义与引用:
# 递归扩展变量,在调用时展开objects1 = a.o b.o# 简单扩展变量,在赋值时展开objects2 = $(objects) c.omain.o: $(objects) gcc -o main.o $(objects2)
如果要在makefile中真实的
$
,需要用$$
来表示。注意变量赋值时不能使用通配符。但是在规则中,通配符是可以使用的:
print: *.c some command
自动化变量
$@
表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,$@
就是匹配于目标中模式定义的集合。$%
仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是foo.a (bar.o)
,那么,$%
就是bar.o
,$@
就是foo.a
。如果目标不是函数库文件(Unix 下是.a
,Windows 下是.lib
),那么,其值为空。$<
依赖目标中的第一个目标名字。如果依赖目标是以模式(即%
)定义的,那么$<
将 是符合模式的一系列的文件集。注意,其是一个一个取出来的。$?
所有比目标新的依赖目标的集合。以空格分隔。$^
所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量 会去除重复的依赖目标,只保留一份。$+
这个变量很像”$^”,也是所有依赖目标的集合。只是它不去除重复的依赖目标。$*
这个变量表示目标模式中%
及其之前的部分。如果目标是dir/a.foo.b
,并且目标的模式是a.%.b
,那么,$*
的值就是dir/a.foo
。
隐含规则
make
会通过隐含规则自动推导依赖关系,可以帮助我们简化 makefile
。例如:
foo : foo.o bar.o cc –o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
并没有指明如何生成 .o
文件,这时 make
会生成:
foo.o : foo.c cc –c foo.c $(CFLAGS) bar.o : bar.c cc –c bar.c $(CFLAGS)
隐含规则中的编译器与上一级依赖中的相同,因此产生 foo
的规则中,cc
命令是不可省略的。
使用函数
可以使用 make
内建函数来完成某些功能。语法如下:
$(<function> <arguments>)
如:
sources := $(shell ls *.c)
make
中的函数包括:字符串处理,文件名操作,流程控制,call函数,origin函数,shell函数。
进阶技巧
伪目标
伪目标不是一个文件,而只是一个标签,使得依赖关系的书写更加灵活。.PHONY
用来声明伪目标(但不是必须的),这时可以避免 make 去检查同名的文件。例如:
.PHONY: clean clean: rm *.o temp
多目标
bigoutput littleoutput : text.g generate text.g -$(subst output,,$@) > $@# 等价于:bigoutput : text.g generate text.g -big > bigoutput littleoutput : text.g generate text.g -little > littleoutput
静态模式
静态模式可以更加容易地定义多目标的规则,语法如下:
<targets ...>: <target-pattern>: <prereq-patterns ...> <commands>
例如,下面的makefile将对所有的 .o
文件分别生成一条依赖关系。
objects = foo.o bar.o all: $(objects) $(objects): %.o: %.c $(CC) -c $(CFLAGS) $< -o $@
总控 makefile
在makefile中,可以执行子文件夹的makefile:
subsystem: $(MAKE) -C subdir
这里的$(MAKE)
是为了方便维护make的参数。总控makefile的变量可以传递到下级:
export variable = value# or use the followingvariable = value export variable
自动生成依赖
对于每个 .c
文件,我们一般会需要如下的依赖关系:
main.o : main.c defs.h
然而,有时候存在大量的 .c
文件,我们需要得到每个 .c
对应的 .h
。借助于 gcc
,可以自动探测这些依赖:
sources = main.c stack.c maze.c-include $(sources:.c=.d)%.d: %.c @set -e; rm -f $@; \ $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$
如上的makefile定义了 .c
的列表变量,然后载入对应的 .d
文件,这时会有文件不存在的警告产生,此时 make 会采用下面的模式生成 .d
:
- 设置shell,发生错误立即退出
- 得到依赖关系(如
main.o main.c defs.h
),存为.d.XXXX
(XXXX
为当前进程号) sed
替换(例如将main.o : main.c defs.h
转成main.o main.d : main.c defs.h
),使得.d
也能得到更新。- 删除临时文件
- makefile入门
- makefile入门
- makefile入门
- makefile入门
- makefile入门
- MakeFile 入门
- Makefile 入门
- Makefile 入门
- makefile入门
- makefile 入门
- makefile入门
- Makefile入门
- makefile入门
- Makefile入门
- Makefile 入门
- Makefile入门
- Makefile入门
- makefile入门
- android studio使用百度SDK开发百度地图应用中遇到的问题汇总
- hadoop入门:3.运行简单的MapReduce计算
- SFM三维重建源码(Matlab)
- 调整UILabel行高间距
- tarjan & LCA 题集
- Makefile 入门
- 一位清华师兄的SCI论文写作心得
- 命令被shell处理过程
- [web安全] 后台安全
- Linux权限与命令间的关系
- 27. Location reload() 方法
- 掌上快递之主界面篇(1)
- 14.键-值观察(KVO)
- angularjs源码阅读——angularjs工具方法