makefile学习部分语法和实例

4 篇文章 0 订阅
2 篇文章 0 订阅
终于写完了,出自于好早我存的一个makefile学习.txt,具体作者已经不清楚了,之后我会找一些makefile或者shell的东西写写
例子1:
edit : main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
    cc -c display.c
insert.o : insert.c defs.h buffer.h
    cc -c insert.c
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c
clean :
    rm edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

makefile中使用变量

objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

edit : $(objects)
    cc -o edit $(objects)
main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
    cc -c display.c
insert.o : insert.c defs.h buffer.h
    cc -c insert.c
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c
clean :
    rm edit $(objects)

让make自己主动推导 省略了  .o文件中需要同名的.c文件

objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

.PHONY : clean
clean :
    rm edit $(objects)

“.PHONY”表示,clean是个伪目标文件。

另类风格的makefile

objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

edit : $(objects)
    cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h

.PHONY : clean
clean :
    rm edit $(objects)

清空目标文件的规则

clean:
    rm edit $(objects)

更为稳健的做法是:

.PHONY : clean
clean :
    -rm edit $(objects)

在rm命令前面加了一个小减号的意思就是,或许某些文件出现故障,但不要管,继续做后面的事。

引用其他makefile

-include <filename>

makefile规则  同行分号或者下一行Tab

targets : prerequisites
command
...

或是这样:

targets : prerequisites ; command
    command

通配符

objects = *.o   #object就是 *.o

objects := $(wildcard *.o)    #objects的值是全部[.o]的文件名称的集合  ##wildcard 是关键字

文件搜寻

VPATH = src:../headers
上面的的定义指定两个文件夹,“src”和“../headers”,make会依照这个顺序进行搜索。文件夹由“冒号”分隔。(当然,当前文件夹永远是最高优先搜索的地方)
1、vpath <pattern> <directories>
为符合模式<pattern>的文件指定搜索文件夹<directories>。

2、vpath <pattern>
清除符合模式<pattern>的文件的搜索文件夹。

3、vpath
清除全部已被设置好了的文件搜索文件夹。
vpath %.c foo
vpath % blish
vpath %.c bar

其表示“.c”结尾的文件,先在“foo”文件夹,然后是“blish”,最后是“bar”文件夹。
静态模式
<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”)。
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
filter滤波器,过滤相应的
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 $<
sources = foo.c bar.c
include $(sources:.c=.d)

上述语句中的“$(sources:.c=.d)”中的“.c=.d”的意思是做一个替换,把变量$(sources)全部[.c]的字串都替换成[.d],
注意次序,由于include是按次来加载文件,最先加载的[.d]文件里的目标会成为默认目标。
书写命令
显示命令

@echo 正在编译XXX模块......
##会输出“正在编译XXX模块......”
沒有“@”,那么,make将输出:
##echo 正在编译XXX模块......
##正在编译XXX模块......

假设make运行时,带入make參数“-n”或“--just-print”,那么其仅仅是显示命令,但不会运行命令,便于调试使用。

而make參数“-s”或“--slient”则是全面禁止命令的显示。
命令运行

演示例子一:
exec:
cd /home/hchen
pwd

演示例子二:
exec:
cd /home/hchen; pwd

当我们运行“make exec”时,第一个样例中的cd沒有作用,pwd会打印出当前的Makefile文件夹,而第二个样例中,cd就起作用了,pwd会打印出“/home/hchen”。
子文件夹叫subdir,这个文件夹下有个Makefile文件
subsystem:
cd subdir && $(MAKE)

其等效于:

subsystem:
$(MAKE) -C subdir


假设你要传递变量到下级Makefile中,那么你能够使用这样的声明:
export <variable ...>
假设你不想让某些变量传递到下级Makefile中,那么你能够这样声明:
unexport <variable ...>
如:

演示例子一:
export variable = value
其等效于:
variable = value
export variable
其等效于:
export variable := value
其等效于:
variable := value
export variable

演示例子二:
export variable += value
其等效于:
variable += value
export variable

假设你要传递全部的变量,那么,仅仅要一个export就可以了。后面什么也不用跟,表示传递全部的变量。

一个是SHELL,一个是MAKEFLAGS,这两个变量无论你是否export,其总是要传递到下层Makefile中,特别是MAKEFILES变量,当中包括了make的參数信息,
可是make命令中的有几个參数并不往下传递,它们是“-C”,“-f”,“-h”“-o”和“-W”

不往下层传递參数
subsystem:
cd subdir && $(MAKE) MAKEFLAGS=

 

objects = program.o foo.o utils.o
program : $(objects)
cc -o program $(objects)

$(objects) : defs.h



foo = c
prog.o : prog.$(foo)
$(foo)$(foo) -$(foo) prog.$(foo)
展开后得到:
prog.o : prog.c
cc -c prog.c
一个“替代”的原理,加括号更安全




x := foo
y := $(x) bar
x := later
其等效于:
y := foo bar
x := later

y := $(x) bar
x := foo
那么,y的值是“bar”,而不是“foo bar”。



ifeq (0,${MAKELEVEL})####make有一个嵌套运行的动作   MAKELEVEL记录嵌套层数
cur-dir := $(shell pwd)
whoami := $(shell whoami)
host-type := $(shell arch)
MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}
endif



FOO ?= bar

其含义是,假设FOO沒有被定义过,那么变量FOO的值就是“bar”
假设FOO先前被定义过,那么这条语将什么也不做
其等效于:

ifeq ($(origin FOO), undefined)
FOO = bar
endif
x = variable1
variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))    #########$(a)的值就是$(variable2)的值——“Hello”


first_second = Hello
a = first
b = second
all = $($a_$b)#####$(all)的值就是“Hello”。


objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o###$(objects)值变成:“main.o foo.o bar.o utils.o another.o”
使用函数
字符串处理函数

$(subst <from>,<to>,<text> )
名称:字符串替换函数——subst。
功能:把字串<text>中的<from>字符串替换成<to>。
返回:函数返回被替换过后的字符串。

演示例子:
$(subst ee,EE,feet on the street),
把“feet on the street”中的“ee”替换成“EE”,返回结果是“fEEt on the strEEt”。


$(patsubst <pattern>,<replacement>,<text> )
名称:模式字符串替换函数——patsubst。
功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,假设匹配的话,则以<replacement>替换。
<pattern>能够包括通配符“%”,表示随意长度的字串。假设<replacement>中也包括“%”,那么,<replacement>中的这个“%”将是<pattern>中的那个“%
”所代表的字串。(能够用“/”来转义,以“/%”来表示真实含义的“%”字符)
返回:函数返回被替换过后的字符串。

演示例子:
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”

备注:
相似。如:
“$(var:<pattern>=<replacement> )”
相当于
“$(patsubst <pattern>,<replacement>,$(var))”,

而“$(var: <suffix>=<replacement> )”
则相当于
“$(patsubst %<suffix>,%<replacement>,$(var))”。

比如有:objects = foo.o bar.o baz.o,
那么,“$(objects:.o=.c)”和“$(patsubst %.o,%.c,$(objects))”是一样的。

$(strip <string> )
名称:去空格函数——strip。
功能:去掉<string>字串中开头和结尾的空字符。
返回:返回被去掉空格的字符串值。
演示例子:

$(strip a b c )

把字串“a b c ”去到开头和结尾的空格,结果是“a b c”。

$(findstring <find>,<in> )

名称:查找字符串函数——findstring。
功能:在字串<in>中查找<find>字串。
返回:假设找到,那么返回<find>,否则返回空字符串。
演示例子:

$(findstring a,a b c)
$(findstring a,b c)

第一个函数返回“a”字符串,第二个返回“”字符串(空字符串)

$(filter <pattern...>,<text> )

名称:过滤函数——filter。
功能:以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。能够有多个模式。
返回:返回符合模式<pattern>的字串。
演示例子:

sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
cc $(filter %.c %.s,$(sources)) -o foo

$(filter %.c %.s,$(sources))返回的值是“foo.c bar.c baz.s”。

$(filter-out <pattern...>,<text> )

名称:反过滤函数——filter-out。
功能:以<pattern>模式过滤<text>字符串中的单词,去除符合模式<pattern>的单词。能够有多个模式。
返回:返回不符合模式<pattern>的字串。
演示例子:

objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o

$(filter-out $(mains),$(objects)) 返回值是“foo.o bar.o”。

$(sort <list> )

名称:排序函数——sort。
功能:给字符串<list>中的单词排序(升序)。
返回:返回排序后的字符串。
演示例子:$(sort foo bar lose)返回“bar foo lose” 。
备注:sort函数会去掉<list>中相同的单词。

$(word <n>,<text> )

名称:取单词函数——word。
功能:取字符串<text>中第<n>个单词。(从一开始)
返回:返回字符串<text>中第<n>个单词。假设<n>比<text>中的单词数要大,那么返回空字符串。
演示例子:$(word 2, foo bar baz)返回值是“bar”。

$(wordlist <s>,<e>,<text> )

名称:取单词串函数——wordlist。
功能:从字符串<text>中取从<s>开始到<e>的单词串。<s>和<e>是一个数字。
返回:返回字符串<text>中从<s>到<e>的单词字串。假设<s>比<text>中的单词数要大,那么返回空字符串。假设<e>大于<text>的单词数,那么返回从<s>开始

,到<text>结束的单词串。
演示例子: $(wordlist 2, 3, foo bar baz)返回值是“bar baz”。

$(words <text> )

名称:单词个数统计函数——words。
功能:统计<text>中字符串中的单词个数。
返回:返回<text>中的单词数。
演示例子:$(words, foo bar baz)返回值是“3”。
备注:假设我们要取<text>中最后的一个单词,我们能够这样:$(word $(words <text> ),<text> )。

$(firstword <text> )

名称:首单词函数——firstword。
功能:取字符串<text>中的第一个单词。
返回:返回字符串<text>的第一个单词。
演示例子:$(firstword foo bar)返回值是“foo”。
备注:这个函数能够用word函数来实现:$(word 1,<text> )。

以上,是全部的字符串操作函数,假设搭配混合使用,能够完成比較复杂的功能。这里,举一个现实中应用的样例。我们知道,make使用“VPATH”变量来指定

“依赖文件”的搜索路径。于是,我们能够利用这个搜索路径来指定编译器对头文件的搜索路径參数CFLAGS,如:

override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))

假设我们的“$(VPATH)”值是“src:../headers”,那么“$(patsubst %,-I%,$(subst :, ,$(VPATH)))”将返回“-Isrc -I../headers”,这正是cc或gcc

搜索头文件路径的參数。
文件名称操作函数
$(dir <names...> )
名称:取文件夹函数——dir。功能:从文件名称序列<names>中取出文件夹部分。文件夹部分是指最后一个反斜杠(“/”)之前的部分。假设沒有反斜杠,那么返回“./”。返回:返回文件名称序列<names>的文件夹部分。演示例子: $(dir src/foo.c hacks)返回值是“src/ ./”。$(notdir <names...> )名称:取文件函数——notdir。功能:从文件名称序列<names>中取出非文件夹部分。非文件夹部分是指最后一个反斜杠(“/”)之后的部分。返回:返回文件名称序列<names>的非文件夹部分。演示例子: $(notdir src/foo.c hacks)返回值是“foo.c hacks”。$(suffix <names...> )名称:取后缀函数——suffix。功能:从文件名称序列<names>中取出各个文件名称的后缀。返回:返回文件名称序列<names>的后缀序列,假设文件沒有后缀,则返回空字串。演示例子:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c .c”。$(basename <names...> )名称:取前缀函数——basename。功能:从文件名称序列<names>中取出各个文件名称的前缀部分。返回:返回文件名称序列<names>的前缀序列,假设文件沒有前缀,则返回空字串。演示例子:$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo src-1.0/bar hacks”。$(addsuffix <suffix>,<names...> )名称:加后缀函数——addsuffix。功能:把后缀<suffix>加到<names>中的每一个单词后面。返回:返回加过后缀的文件名称序列。演示例子:$(addsuffix .c,foo bar)返回值是“foo.c bar.c”。$(addprefix <prefix>,<names...> )名称:加前缀函数——addprefix。功能:把前缀<prefix>加到<names>中的每一个单词后面。返回:返回加过前缀的文件名称序列。演示例子:$(addprefix src/,foo bar)返回值是“src/foo src/bar”。<list1>的单词后面。假设<list1>的单词个数要比<list2>的多,那么,<list1>中的多出来的单词将保持原样。假设<list2>的单词个数要比<list1>多,那么,<list2>多出来的单词将被拷贝到<list2>中。返回:返回连接过后的字符串。演示例子:$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”。 foreach 函数循环用的$(foreach <var>,<list>,<text> )这个函数的意思是,把參数<list>中的单词逐一取出放到參数<var>所指定的变量中,然后再运行<text>所包括的表达式。每一次<text>会返回一个字符串,循环过程中,<text>的所返回的每一个字符串会以空格分隔,最后当整个循环结束时,<text>所返回的每一个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。所以,<var>最好是一个变量名,<list>能够是一个表达式,而<text>中通常会使用<var>这个參数来依次枚举<list>中的单词。举个样例:names := a b c dfiles := $(foreach n,$(names),$(n).o)上面的样例中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次依据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。注意,foreach中的<var>參数是一个暂时的局部变量,foreach函数运行完后,參数<var>的变量将不在作用,其作用域仅仅在foreach函数当中。 if 函数 $(if <condition>,<then-part> )或是$(if <condition>,<then-part>,<else-part> )
call函数

call函数是唯一一个能够用来创建新的參数化的函数。你能够写一个非常复杂的表达式,这个表达式中,你能够定义很多參数,然后你能够用call函数来向这个
表达式传递參数。其语法是:
$(call <expression>,<parm1>,<parm2>,<parm3>...)

reverse = $(1) $(2)
foo = $(call reverse,a,b)###foo的值就是“a b”。

reverse = $(2) $(1)
foo = $(call reverse,a,b)###此时的foo的值就是“b a”。
 

origin函数
origin函数不像其他的函数,他并不操作变量的值,他仅仅是告诉你你的这个变量是哪里来的?其语法是:

$(origin <variable> )
注意,<variable>是变量的名字,不应该是引用。所以你最好不要在<variable>中使用“$”字符。Origin函数会以其返回值来告诉你这个变量的“出生情况”
,以下,是origin函数的返回值:

“undefined”
假设<variable>从来未定义过,origin函数返回这个值“undefined”。

“default”
假设<variable>是一个默认的定义,比方“CC”这个变量,这样的变量我们将在后面讲述。

“environment”
假设<variable>是一个环境变量,而且当Makefile被运行时,“-e”參数沒有被打开。

“file”
假设<variable>这个变量被定义在Makefile中。

“command line”
假设<variable>这个变量是被命令行定义的。

“override”
假设<variable>是被override指示符又一次定义的。

“automatic”
假设<variable>是一个命令运行中的自己主动化变量。

 

这些信息对于我们编写Makefile是非常实用的,比如,假设我们有一个Makefile其包了一个定义文件Make.def,在Make.def中定义了一个变量“bletch”,而
我们的环境中也有一个环境变量“bletch”,此时,我们想推断一下,假设变量来源于环境,那么我们就把之重定义了,假设来源于Make.def或是命令行等非环
境的,那么我们就不又一次定义它。于是,在我们的Makefile中,我们能够这样写:

ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
shell函数

contents := $(shell cat foo)
files := $(shell echo *.c)
注意,这个函数会新生成一个Shell程序来运行命令
注意其运行性能,假设你的Makefile中有一些比較复杂的规则,
并大量使用了这个函数,那么对于你的系统性能是有害的。
特别是Makefile的隐晦的规则可能会让你的shell函数运行的次数比你想像的多得多。



控制make的函数

检测一些运行Makefile时的运行时信息
$(error <text ...> )

演示例子一:
ifdef ERROR_001
$(error error is $(ERROR_001))
endif 

演示例子二:
ERR = $(error found an error!)
.PHONY: err
err: ; $(ERR)

演示例子一会在变量ERROR_001定义了后运行时产生error调用,而演示例子二则在文件夹err被运行时才发生error调用。



$(warning <text ...> )
这个函数非常像error函数,仅仅是它并不会让make退出,仅仅是输出一段警告信息,而make继续运行。
shell函数

contents := $(shell cat foo)

make的运行
make的退出码

make命令运行后有三个退出码:
0 —— 表示成功运行。
1 —— 假设make运行时出现不论什么错误,其返回1。
2 —— 假设你使用了make的“-q”选项,而且make使得一些目标不须要更新,那么返回2。


指定目标

“all”
这个伪目标是全部目标的目标,其功能通常是编译全部的目标。
“clean”
这个伪目标功能是删除全部被make创建的文件。
“install”
这个伪目标功能是安装已编译好的程序,事实上就是把目标运行文件拷贝到指定的目标中去。
“print”
这个伪目标的功能是例出改变过的源文件。
“tar”
这个伪目标功能是把源程序打包备份。也就是一个tar文件。
“dist”
这个伪目标功能是创建一个压缩文件,通常是把tar文件压成Z文件。或是gz文件。
“TAGS”
这个伪目标功能是更新全部的目标,以备完整地重编译使用。
“check”和“test”
这两个伪目标一般用来测试makefile的流程。


检查规则

“-n”
“--just-print”
“--dry-run”
“--recon”
不运行參数,这些參数仅仅是打印命令,把规则和连带规则下的命令打印出来,但不运行,这些參数对于我们调试makefile非常实用处。

“-t”
“--touch”
把目标文件的时间更新,但不更改目标文件。
make假装编译目标,但不是真正的编译目标,仅仅是把目标变成已编译过的状态。

“-q”
“--question”
找目标
假设目标存在,那么其什么也不会输出,当然也不会运行编译
假设目标不存在,其会打印出一条出错信息

“-W <file>”
“--what-if=<file>”
“--assume-new=<file>”
“--new-file=<file>”
这个參数须要指定一个文件。通常是是源文件(或依赖文件),Make会依据规则推导来运行依赖于这个文件的命令,一般来说,能够和“-n”參数一同使用,来

查看这个依赖文件所发生的规则命令。
make的參数

“-b”
“-m”
这两个參数的作用是忽略和其他版本号make的兼容性。

“-B”
“--always-make”
觉得全部的目标都须要更新(重编译)。

“-C <dir>”
“--directory=<dir>”
指定读取makefile的文件夹。假设有多个“-C”參数,make的解释是后面的路径曾经面的作为相对路径,并以最后的文件夹作为被指定文件夹。如:“make –C 

~hchen/test –C prog”等效于“make –C ~hchen/test/prog”。

“—debug[=<options>]”
输出make的调试信息。它有几种不同的级别可供选择,假设沒有參数,那就是输出最简单的调试信息。以下是<options>的取值:
a —— 也就是all,输出全部的调试信息。(会非常的多)
b —— 也就是basic,仅仅输出简单的调试信息。即输出不须要重编译的目标。
v —— 也就是verbose,在b选项的级别之上。输出的信息包括哪个makefile被解析,不须要被重编译的依赖文件(或是依赖目标)等。
i —— 也就是implicit,输出所以的隐含规则。
j —— 也就是jobs,输出运行规则中命令的具体信息,如命令的PID、返回码等。
m —— 也就是makefile,输出make读取makefile,更新makefile,运行makefile的信息。

“-d”
相当于“--debug=a”。

“-e”
“--environment-overrides”
指明环境变量的值覆盖makefile中定义的变量的值。

“-f=<file>”
“--file=<file>”
“--makefile=<file>”
指定须要运行的makefile。

“-h”
“--help”
显示帮助信息。

“-i”
“--ignore-errors”
在运行时忽略全部的错误。

“-I <dir>”
“--include-dir=<dir>”
指定一个被包括makefile的搜索目标。能够使用多个“-I”參数来指定多个文件夹。

“-j [<jobsnum>]”
“--jobs[=<jobsnum>]”
指同一时候运行命令的个数。假设沒有这个參数,make运行命令时能运行多少就运行多少。
假设有一个以上的“-j”參数,那么仅最后一个“-j”才是有效的。(注意这个參数在MS-DOS中是没用的)

“-k”
“--keep-going”
出错也不停止运行。假设生成一个目标失败了,那么依赖于其上的目标就不会被运行了。

“-l <load>”
“--load-average[=<load]”
“—max-load[=<load>]”
指定make运行命令的负载。

“-n”
“--just-print”
“--dry-run”
“--recon”
仅输出运行过程中的命令序列,但并不运行。

“-o <file>”
“--old-file=<file>”
“--assume-old=<file>”
不又一次生成的指定的<file>,即使这个目标的依赖文件新于它。

“-p”
“--print-data-base”
输出makefile中的全部数据,包括全部的规则和变量。这个參数会让一个简单的makefile都会输出一堆信息。假设你仅仅是想输出信息而不想运行makefile,你

能够使用“make -qp”命令。假设你想查看运行makefile前的预设变量和规则,你能够使用“make –p –f /dev/null”。这个參数输出的信息会包括着你的

makefile文件的文件名称和行号,所以,用这个參数来调试你的makefile会是非常实用的,特别是当你的环境变量非常复杂的时候。

“-q”
“--question”
不运行命令,也不输出。仅仅是检查所指定的目标是否须要更新。假设是0则说明要更新,假设是2则说明有发生错误。

“-r”
“--no-builtin-rules”
禁止make使用不论什么隐含规则。

“-R”
“--no-builtin-variabes”
禁止make使用不论什么作用于变量上的隐含规则。

“-s”
“--silent”
“--quiet”
在命令运行时不输出命令的输出。

“-S”
“--no-keep-going”
“--stop”
取消“-k”选项的作用。由于有些时候,make的选项是从环境变量“MAKEFLAGS”中继承下来的。所以你能够在命令行中使用这个參数来让环境变量中的“-k”

选项失效。

“-t”
“--touch”
相当于UNIX的touch命令,仅仅是把目标的改动日期变成最新的,也就是阻止生成目标的命令运行。

“-v”
“--version”
输出make程序的版本号、版权等关于make的信息。

“-w”
“--print-directory”
输出运行makefile之前和之后的信息。这个參数对于跟踪嵌套式调用make时非常实用。

“--no-print-directory”
禁止“-w”选项。

“-W <file>”
“--what-if=<file>”
“--new-file=<file>”
“--assume-file=<file>”
假定目标<file>须要更新,假设和“-n”选项使用,那么这个參数会输出该目标更新时的运行动作。假设沒有“-n”那么就像运行UNIX的“touch”命令一样,

使得<file>的改动时间为当前时间。

“--warn-undefined-variables”
仅仅要make发现有未定义的变量,那么就输出警告信息。
自己主动化变量

完成从不同的依赖文件生成对应的目标
自己主动化变量及其说明:

$@
表示规则中的目标文件集。在模式规则中,假设有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。

$%
仅当目标是函数库文件里,表示规则中的目标成员名。
比如,假设一个目标是"foo.a(bar.o)",那么,"$%"就是"bar.o","$@"就是"foo.a"。
假设目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。

$<
依赖目标中的第一个目标名字。
假设依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。

$?
全部比目标新的依赖目标的集合。以空格分隔。

$^
全部的依赖目标的集合。以空格分隔。假设在依赖目标中有多个反复的,那个这个变量会去除反复的依赖目标,仅仅保留一份。

$+
这个变量非常像"$^",也是全部依赖目标的集合。仅仅是它不去除反复的依赖目标。

$* 
这个变量表示目标模式中"%"及其之前的部分。假设目标是"dir/a.foo.b",而且目标的模式是"a.%.b",那么,"$*"的值就是"dir/a.foo"。
假设目标中沒有模式的定义,那么"$*"也就不能被推导出
假设目标文件的后缀是make所识别的,那么"$*"就是除了后缀的那一部分。
比如:假设目标是"foo.c",由于".c"是make所能识别的后缀名,所以,"$*"的值就是"foo"。
这个特性是GNU make的,非常有可能不兼容于其他版本号的make

当你希望仅仅对更新过的依赖文件进行操作时,"$?"在显式规则中非常实用
比如,假设有一个函数库文件叫"lib",其由其他几个object文件更新。那么把object文件打包的比較有效率的Makefile规则是:
lib : foo.o bar.o lose.o win.o
ar r lib $?

在上述所列出来的自己主动量变量中。四个变量($@、$<、$%、$*)在扩展时仅仅会有一个文件,而另三个的值是一个文件列表。
使用函数"dir"或"notdir"区分文件和文件夹


















  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CMake是一个跨平台的构建工具,用于构建C ++代码的工具,同时支持多个平台和编译器。相比于传统的Makefile,CMake提供了更加简洁、易于维护、易于理解的构建方式,而且相对于Makefile的生成方式,Cmake的生成方式更加容易自动化,很适合在大型项目中使用。对于想要深入学习CMake的用户,可以参考一些著名的CMake书籍,如《CMake Cookbook》,该书针对不同的用例提供了详细的使用指南;《Mastering CMake》讨论了如何使用CMake来构建C ++和C软件;《Professional Cmake: A Practical Guide》则强调了CMake的最佳实践和如何解决常见问题。 而Makefile则是UNIX及其衍生系统常见的程序构建工具,主要用于通过执行一个包含编译规则的脚本自动化构建过程。如果想要深入了解Makefile的使用,可以先了解一下GNU make的语法规则,很多的Makefile编写风格比较接近于GNU make的语法。相关的书籍也很丰富,如《Managing Projects with GNU Make, Third Edition》,该书对GNU make的使用做了全面的介绍,从基础概念到高级特性等方面都有所讲解;《跟我一起写Makefile》则是一本为Makefile初学者准备的教程,通过实例讲解了什么是Makefile以及如何使用Makefile来构建项目。 总之,CMake和Makefile都是重要的构建工具,在程序员的工作中扮演着不可替代的角色。随着工具的不断发展,它们的使用也越来越普及,相应地,相关的书籍越来越多,选择一本适合自己的书籍,深入学习这两种工具,相信可以让自己的构建工作更加高效、便捷。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值