Makefile

Makefile 常用规则

wildcard

  • one use of the wildcard function is to get a list of all the C source files in a directory.
//获取当前目录下全部.c文件-test.c hello.c
$(wildcard *.c)

patsubst

  • we can change the list of c source files into a list of object files by replacing the ‘.c’ suffix with ‘.o’ in the result.
//1. 获取当前目录下全部.c文件--test.c hello.c hello.h 
objects := $(wildcard *.c)
//2. 两种方式--将.c文件替换为.o文件--test.o hello.o hello.h
//第一种方式
$(patsubst %.c,%.o,$(objects))
//第二种方式
$(objects:.c=.o)

subst

  • replace from with to in text.
text的内容-->hello world
//将text中“ll”替换为“ww”-->hewwo world
$(subst ll, ww,text)  

addprefix

input := foo.o bar.o baz.o
$(addprefix $(OBJDIR)/,$(input))
output := $(OBJDIR)/foo.o $(OBJDIR)/bar.o $(OBJDIR)/baz.o

VPATH

  • Make uses VPATH as a search list for both prerequisites and targets of rules.
//specifies a path containing two directories, src and ../headers, which make searches in that order.
VPATH = src:../headers

vpath

  • vpath pattern directories -->Specify the search path directories for file names that match pattern.
  • vpath pattern -->Clear out the search path associated with pattern.
  • vpath -->Clear all search paths previously specified with vpath directives.
//will look .c file in foo, then bar dirctory 
vpath %.c foo:bar

assignment

  • $$ : a dollar sign(if you want a dollar sign to appear in your recipe, you must double it (‘$$’))
  • = : recursively expanded variable
  • := : simple expanded variable
  • += : add more text to the value of a variable already defined
  • ?= : if the value of variable is not existed, the variable will be assigned.

PHONY target (fake target)

  • a phony target is one that is not really the name of a file; it is just a name for a recipe to be executed when you make an explicit request. (显示的请求)

substitution References(替换引用)

foo := a.o b.o c.o
//bar := a.c b.c c.c
//bar := $(patsubst %.o, %.c, $(foo))
bar := $(foo:.o=.c) ---> 和 patsubst 一样

function

  • $(foreach var,list,text)
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
//相当于下面的语句
for dir in $(dirs)
    files := $(wildcard $(dir)/*)
  • $(call expression, parm1, parm2, parm3,…)
$(0): expression
$(1): parm1
$(2): parm2
$(3): parm3   
  • $(origin variable)
  • 如果$(origin O)返回值为"undefine"时,那么变量"O"没有被定义。
  • 如果$(origin O)返回值为"command line"时,那么变量"O"是在命令行定义。需要在命令行中输入"make O=变量值"
  • 如果$(origin O)返回值为"environment"时,那么变量"O"是定义为环境变量。需要先把O定义为环境变量
  • 如果$(origin O)返回值为"file"时,这个变量是定义在Makefile中。需要在Makefile中定义O变量。
  • 如果$(origin O)返回值为"default"时,那么变量"O"是默认定义的。

include

  • ‘-I’ or ‘–include-dir’ option are searched.
  • Then the following directories (if they exist) are searched, in this order: prefix/include (normally /usr/local/include1) /usr/gnu/include, /usr/local/include, /usr/include.
  • 常用 “-include” 或者"sinclude", 来代替 “include” 来忽略文件不存在或者是无法创建的错误提示

automatic variables

  • $@ The file name of the target of the rule.
  • $< The name of the first prerequisite.
  • $^ The names of all the prerequisites, with spaces between them.
  • $? The names of all the prerequisites that are newer than the target, with spaces between them.
  • $(@F) The file-within-directory part of the file name of the target. If the value of $@is dir/foo.o then $(@F) is foo.o. $(@F)is equivalent to $(notdir $@).

$(filter pattern…,text)

  • select words in text that match one of the pattern words.
src := foo.c bar.c baz.s ugh.h
//des := foo.c bar.c baz.s
des := $(filter %.c %.s,$(src))

$(filter-out pattern…,text)

  • select words in text that do not match any of the pattern words.
src := foo.c bar.c baz.s ugh.h
//des := ugh.h
des := $(filter-out %.c %.s,$(src))

$(firstword NAMES…)

函数名称:取首单词函数—firstword。 
函数功能:取字串“NAMES…”中的第一个单词。 
返回值:字串“NAMES…”的第一个单词。 
函数说明:“NAMES”被认为是使用空格分割的多个单词(名字)的序列。函数忽
略“NAMES…”中除第一个单词以外的所有的单词。 
示例: 
$(firstword foo bar) 
返回值为“foo”。函数“firstword”实现的功能等效于“$(word 1, NAMES…)

$(word n, text)

函数名称: 取单词函数
功能: 取字符串 <text> 中的 第<n>个单词 (n从1开始)
返回: <text> 中的第<n>个单词, 如果<n><text> 中单词个数要大, 则返回空字符串.
@echo $(word 1,aa bb cc dd)
@echo $(word 5,aa bb cc dd)
@echo $(word 4,aa bb cc dd)
结果: aa,  ,dd

$(wordlist s, e, text)

函数名称: 取单词函数
功能: 用于从给定的文本 text 中提取出从位置 s 开始到位置 e 结束的单词列表
s: 从这个位置开始提取单词。
e: 在这个位置结束提取单词,但 e 位置上的单词不会被包括在内。
text: 可以是空格分隔的单词列表或任何字符串
返回:(1)如果 s 大于 e 或超出了 text 的范围,函数将返回一个空列表;
	 (2)如果 e 大于 text 中单词的数量,函数将返回从 s 到文本末尾的所有单词;
	  
words = a b c d e f g
result = $(wordlist 2, 5, $(words))

结果:result 将包含 b c d

$(words text)

函数名称: 计算给定文本text中的单词数量,text可以是空格分隔的单词列表或任何字符串
功能: 返回参数text中的单词总数

words = a b c d
word_count = $(words $(words))

结果:word_count为4

$(findstring str1, str2)

函数名称:查找字符串函数。 
函数功能:搜索字串“str2”,查找“str1”字串。 
返回值:如果在“str2”之中存在“str1” ,则返回“str1”,否则返回空。

gcc 编译选项

  • -I /home/hello/include
    表示将/home/hello/include目录作为第一个寻找头文件的目录,寻找的顺序是:/home/hello/include–>/usr/include–>/usr/local/include

  • -L /home/hello/lib
    表示将/home/hello/lib目录作为第一个寻找库文件的目录,寻找的顺序是:/home/hello/lib–>/lib–>/usr/lib–>/usr/local/lib

  • -lworld
    表示在上面的lib的路径中寻找libworld.so动态库文件(如果gcc编译选项中加入了“-static”表示寻找libworld.a静态库文件)
    1)编译目标代码时 ”-Wl,-rpath,” 指定的动态库搜索路径(当指定多个动态库搜索路径时,路径之间用冒号”:”分隔。);
    2)环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径;
    3)置文件 /etc/ld.so.conf 中指定的动态库搜索路径;
    4)默认的动态库搜索路径 /lib,如果是64位系统还包括 /lib64;
    5)默认的动态库搜索路径 /usr/lib,如果是64位系统还包括 /usr/lib64;

  • -M

`-M` 是 `gcc` 命令的一个选项,它的作用是生成 Makefile 的依赖项(dependency)。
当你使用 `-M` 选项时,`gcc` 会分析源代码文件,找出它依赖的头文件,并生成一个 Makefile 片段,这个片段包含了源文件和它依赖的头文件之间的关系。这样做的好处是,当你的源代码或头文件发生变化时,`make` 工具可以根据这些依赖关系来决定是否需要重新编译某个源文件。
例如,如果你有一个源文件 `main.c`,使用 `-M` 选项的命令可能如下:
gcc -M main.c
将输出类似下面的文本:
main.o: main.c defs.h types.h

这意味着 `main.o` 对象文件依赖于 `main.c` 源文件以及 `defs.h` 和 `types.h` 头文件。如果 `main.c` 或任何头文件被修改,`make` 将根据这些依赖关系重新编译 `main.o`。

此外,`-M` 选项还有几个变体:
- `-MD`:与 `-M` 类似,但还会生成相应的 `.d` 文件,其中包含了依赖关系。
- `-MF`:指定输出依赖关系的文件名。
- `-MP`:在生成的依赖项中,为每个依赖项添加一个前缀路径。
使用 `-M` 选项可以帮助自动化构建过程,确保在源代码或头文件更改时,只有相关的部分被重新编译,从而提高构建效率.
假设你有一个简单的 C 程序,包含两个文件:main.c(main.c foo.h) 和 foo.c(foo.c foo.h common.h),使用 gcc -M 命令:
gcc -M main.c foo.c
将输出类似于下面的依赖关系:
main.o: main.c foo.h
foo.o: foo.c foo.h common.h
如果使用 -MD 选项,gcc 还会生成一个 .d 文件,例如 main.d 和 foo.d,这些文件包含了相同的依赖信息,但格式更适合 make 使用。
gcc -MD main.c foo.c
这将生成 main.d 和 foo.d 文件,内容如下:

//main.d
main.o: main.c foo.h

//foo.d
foo.o: foo.c foo.h common.h
在 Makefile 中,你可以使用这些 .d 文件来自动更新依赖关系,例如:
/*********************************************
# 定义编译器
CC=gcc
# 定义生成目标文件的规则
%.o: %.c
    $(CC) -c $< -o $@

# 包含自动生成的依赖文件
-include main.d
-include foo.d

# 定义程序的名称
PROGRAM=program

# 定义程序的依赖
$(PROGRAM): main.o foo.o
    $(CC) $^ -o $@

# 清理编译生成的文件
clean:
    rm -f *.o $(PROGRAM)
*********************************************/
当你运行 make 命令时,它会读取 Makefile 和 .d 文件来确定哪些文件需要重新编译。如果 main.c 或 foo.h 被修改了,make 将只重新编译 main.o;如果 foo.c 或 common.h 被修改了,make 将只重新编译 foo.o。这样可以节省编译时间并提高效率
  • 静态模式

静态模式可以更加容易地定义多目标的规则,可以让我们的规则变得更加的有弹性和灵活。我们还是先来看一下语法:

<targets ...>: <target-pattern>: <prereq-patterns ...>
  <commands>
...

如果我们的<target-parrtern>定义成“%.o”,意思是我们的集合中都是以“.o”结尾的.
如果我们的<prereq-parrterns>定义成“%.c”,意思是对所形成的目标集进行二次定义,其计算方法是,取模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合。
所以,我们的“目标模式”或是“依赖模式”中都应该有“%”这个字符。

下面的例子:

objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
	$(CC) -c $(CFLAGS) $< -o $@
  • 就是从objects中寻找出满足%.o的文件,并且将%.c作为依赖,结果如下
foo.o : foo.c
	$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
	$(CC) -c $(CFLAGS) bar.c -o bar.o
  • 如果上面的objects = foo.o bar.o eric.txt
    结果如下,少了eric.txt, 因为不满足%.o目标模式<target-pattern>, 说白了,将满足的保存下来, 然后和%.c对应.
foo.o : foo.c
	$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
	$(CC) -c $(CFLAGS) bar.c -o bar.o
  • 高级写法
.c.o:
	gcc -c -o $*.o $<
  • 这句话的意思就是 %.o : %.c , 即所有的.o文件,依赖于对应的.c文件.

gcc -Map

–map 是 ld 的一个选项,用于在链接过程中生成一个包含符号表和内存映射信息的文件。

当你使用 --map 选项时,ld 会在链接完成后输出一个包含以下信息的文件:

符号表:列出了所有符号(变量、函数等)及其地址。内存映射:显示了程序的内存布局,包括代码段、数据段和其他段的位置和大小。–map 选项默认生成的文件名为 程序名.map,其中程序名是你指定的输出文件名。这个 .map 文件可以在程序运行后用来分析程序的内存使用情况和符号地址。-Map 选项用于指定输出映射文件的名称, 即使用 -Map 选项时,你可以指定一个文件名,而不是使用默认的 .map 文件名

Target-specific Variable Values

Variable values in make are usually global; that is, they are the same regardless of where they are evaluated. Exceptions to that are variables defined with the let function or the foreach function and automatic variables. Another exception are target-specific variable values. This feature allows you to define different values for the same variable, based on the target that make is currently building. As with automatic variables, these values are only available within the context of a target’s recipe (and in other target-specific assignments). Set a target-specific variable value like this:

 target ... : variable-assignment
  • Target-specific variable assignments can be prefixed with any or all of the special key words export, unexport, override, or private; these apply their normal behavior to this instance of the variable only. Multiple target values create a target-specific variable value for each member of the target list individually.
  • The variable-assignment can be any valid form of assignment; recursive (‘=’), simple (‘:=’ or ‘::=’), immediate (‘::=’), appending (‘+=’), or conditional (‘?=’). All variables that appear within the variable-assignment are evaluated within the context of the target: thus, any previously-defined target-specific variable values will be in effect. Note that this variable is actually distinct from any “global” value: the two variables do not have to have the same flavor (recursive vs. simple). Target-specific variables have the same priority as any other makefile variable. Variables provided on the command line (and in the environment if the ‘-e’ option is in force) will take precedence. Specifying the override directive will allow the target-specific variable value to be preferred.
  • There is one more special feature of target-specific variables: when you define a target specific variable that variable value is also in effect for all prerequisites of this target, and all their prerequisites, etc. (unless those prerequisites override that variable with their own target-specific variable value). So, for example, a statement like this:
 prog : CFLAGS =-g
 prog : prog.o foo.o bar.o

will set CFLAGS to ‘-g’ in the recipe for prog, but it will also set CFLAGS to ‘-g’ in the recipes that create prog.o, foo.o, and bar.o, and any recipes which create their prerequisites.

  • Be aware that a given prerequisite will only be built once per invocation of make, at most. If the same file is a prerequisite of multiple targets, and each of those targets has a different value for the same target-specific variable, then the first target to be built will Chapter 6: How to Use Variables cause that prerequisite to be built and the prerequisite will inherit the target-specific value from the first target. It will ignore the target-specific values from any other targets.

Pattern-specific Variable Values

In addition to target-specific variable values.GNU make supports pattern-specific variable values. In this form, the variable is defined for any target that matches the pattern specified. Set a pattern-specific variable value like this:

 pattern ... : variable-assignment

where pattern is a %-pattern. As with target-specific variable values, multiple pattern
values create a pattern-specific variable value for each pattern individually. The variable assignment can be any valid form of assignment. Any command line variable setting will take precedence, unless override is specified.
For example:

%.o : CFLAGS =-O

will assign CFLAGS the value of ‘-O’ for all targets matching the pattern %.o.
If a target matches more than one pattern, the matching pattern-specific variables with
longer stems are interpreted first. This results in more specific variables taking precedence over the more generic ones, for example:

 %.o: %.c
 $(CC)-c $(CFLAGS) $(CPPFLAGS) $<-o $@
 lib/%.o: CFLAGS :=-fPIC-g
 %.o: CFLAGS :=-g
 all: foo.o lib/bar.o

In this example the first definition of the CFLAGS variable will be used to update
lib/bar.o even though the second one also applies to this target. Pattern-specific
variables which result in the same stem length are considered in the order in which they were defined in the makefile.
Pattern-specific variables are searched after any target-specific variables defined explic
itly for that target, and before target-specific variables defined for the parent target

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值