目录
1.makefile总结
以下内容参考《跟我一起写makefile》,仅作个人学习总结。
make 命令执行时,需要一个 Makefile 文件,以告诉 make 命令需要怎么样的去编译和链接程序。
1.1makefile基本规则
target...:prerequisites...
command
target: 目标文件,Objectfile,执行文件,或者标签
prerequisites:生成target所需文件或目标
command:make执行的命令(任意shell命令)
1.1.1makefile变量
Makefile 中的变量其实就是 C/C++中的宏。
objects = main.0 kbd.o display.o insert.o #all .o file
edit: $(objects)
cc -o edit $(objects)
1.1.2make自动推导
GNU 的 make 很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必 要去在每一个[.o]文件后都写上类似的命令,因为,我们的 make 会自动识别,并自己推导 命令。 只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make 找到whatever.o,那么 whatever.c,就会是 whatever.o 的依赖文件,并且 cc -c whatever.c 也会被推导出来。
1.1.3清空目标文件
所有生成的文件,都应当可以被清空,这有利于重编译和保持文件清洁。
.PHONY:clean
clean:
rm edit $(objects)
1.2makefile综述
makefile主要包含五个东西:显式规则,隐式规则,变量定义,文件指示和注释
1.2.1引用其他makefile
makefile使用include关键字可以把别的makefile包含进来
include <filename>
filename 可以是当前操作系统 Shell 的文件模式(可以保含路径和通配符) 在 include 前面可以有一些空字符,但是绝不能是[Tab]键开始。make 命令开始时,会把找寻 include 所指出的其它 Makefile,并把其内容安置在当前的位置。
如果文件都没有指定绝对路径或是相对路径的话, make 会在当前目录下首先寻找,如果当前目录下没有找到,那么,make 还会在下面的几个目录下找:
1."-I"或"--include-dir"所指定目录
2.<prefix>/include中
1.2.2makefile工作方式
GNU 的 make 工作时的执行步骤入下:
1、读入所有的 Makefile。
2、读入被 include 的其它 Makefile。
3、初始化文件中的变量。
4、推导隐晦规则,并分析所有规则。
5、为所有的目标文件创建依赖关系链。
6、根据依赖关系,决定哪些目标要重新生成。
7、执行生成命令。
1.3makefile规则书写
targets : prerequisites
command
或是这样:
targets : prerequisites ; command
command
1.3.1通配符的使用
~/:当前用户$HOME目录
*.c:表示所有后缀为c的文件
clean:
rm -f *.o
1.3.2文件搜寻
在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在不同的目录中。所以,当 make 需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是定义一个路径,让 make 在自动去找。
VPATH
VPATH = src:../headers
make 会优先在当前的目录中去找寻依赖文件和目标文件,找不到时会去VPATH中寻找,如上所示会按照"src"和"../headers"顺序去搜索。目录由“冒号”分隔。
关键字vpath
1、vpath 为符合模式的文件指定搜索目录。
vpath <pattern> <directories>
2、vpath 清除符合模式的文件的搜索目录。
vpath <pattern>
3、vpath 清除所有已被设置好了的文件搜索目录。
vpath
vapth 使用方法中的需要包含“%”字符。“%”的意思是匹配零或若干字符, 例如,“%.h”表示所有以“.h”结尾的文件。
vpath %.h ../headers
该语句表示,要求 make 在“../headers”目录下搜索所有以“.h”结尾的文件。(如果 某文件在当前目录没有找到的话)
1.3.3伪目标
“伪目标”并不是一个文件,只是一个标签, 由于“伪目标”不是文件,所以 make 无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。
伪目标最好不要和文件名重名,但可以用特殊标记".PHONY"显式指明伪目标,不管是否有该文件,该目标都是伪目标。
.PHONY: clean
clean:
rm *.o temp
伪目标可以指定依赖,如下所示可以实现“一键三连”
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
伪目标也可以成为依赖,如下所示可以实现“一键清空”
PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj :
rm *.o
cleandiff :
rm *.diff
1.3.4多目标静态模式
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
targets 定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern 是指明了 targets 的模式,也就是的目标集模式。
prereq-parrterns 是目标的依赖模式,它对 target-parrtern 形成的模式再进行一次依赖目标的定义。
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
命令中的“$<”和“$@”是自动化变量,“$<”表示所有的依赖目标集(也就是“foo.c bar.c”),“$@”表示目标集(也就是“foo.o bar.o”)
当文件众多时,利用简单的“静态模式规则”可以高效的完成规则编写。
files = foo.elc bar.o lose.o
$(filter %.o,$(files)): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
$(filter %.elc,$(files)): %.elc: %.el
emacs -f batch-byte-compile $<
$(filter %.o,$(files))表示调用 Makefile 的 filter 函数,过滤“$filter”集,只要其 中模式为“%.o”的内容。
1.4命令书写
每条命令的开头必须以[Tab]键开头,在命令行之间中的空格或是空行会被忽略。
make 的 命 令 默 认 是 被 “/bin/sh”——UNIX 的标准 Shell 解释执行的。
“#”是注释符,其后的本行字符都被注释。
1.4.1显示命令
通常,make 会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在 命令行前,那么,这个命令将不被 make 显示出来。
echo git checkout ysyx-tracer
@echo git checkout ysyx-tracer
make执行时,加入参数"-n"或"--just-print",那么将只显示命令,不执行命令,可以利用这个功能调试Makefile。
而 make 参数“-s”或“--slient”则是全面禁止命令的显示。
1.4.2 命令执行
当依赖目标新于目标时,也就是当规则的目标需要被更新时,make 会一条一条的执行 其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使 用分号分隔这两条命令。
exec: cd /home/hchen; pwd
1.4.3命令出错
忽略命令的出错,我们可以在 Makefile 的命令行前加一个减号“-” (在 Tab 键之后),标记为不管命令出不出错都认为是成功的。
clean:
-rm -f *.o
给make 加上“-i”或是“--ignore-errors”参数,那么,Makefile 中所有命令都会忽略错误。
如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。
参数“-k”或是“--keep-going”的作用是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。
1.4.4定义命令包
如果 Makefile 中出现一些相同命令序列,那么我们可以为这些相同的命令序列定义一 个变量。定义这种命令序列的语法以“define”开始,以“endef”结束。
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef
foo.c : foo.y
$(run-yacc)
1.5使用变量
在 Makefile 中的定义的变量,就像是 C/C++语言中的宏一样,他代表了一个文本字串,在 Makefile 中执行的时候其会自动原模原样地展开在所使用的地方。其与 C/