Makefile 学习笔记01

  • 博文资料:\
    https://www.cnblogs.com/baiduboy/p/6849587.html
    http://www.ruanyifeng.com/blog/2015/02/make.html

Makefile语法

Makefile 是 Make 读入的唯一配置文件
1)由 make 工具创建的目标体(target),通常是目标文件或可执行文件
2)要创建的目标体所依赖的文件(dependency_file)
3)创建每个目标体时需要运行的命令(command)
4)注意:命令行前面必须是一个” TAB 键” ,否则编译错误为:*** missing separator. \

1.Makefile 格式

target :   dependency_files
<TAB> command
例子hello.o : hello.c hello.h
gcc –c hello.c –o hello.o

2.关键字

ifeq     fieq(ARG1,ARG2)    判断参数是否相等,相等返回真,反之假。
ifndeq   fineq(ARG1,ARG2)   判断参数是否不等,不等返回真,反之假。
ifdef    ifdef  NAME        关键字“ifdef”用来判断一个变量是否已经定义
ifdef  只测试变量是否有值,不对变量进行替换展开来判断变量的值是否为空
bar = 
foo = $(bar)                     
foo = 
ifdef  foo      返回 真          
ifdef  foo      返回 假
$(if CONDITION,THEN-PART[,ELSE-PART])      同( A,B ,C)

CONDITION:  展开非空,则条件为真,执行第二个参数,反之执行第三个参数,、
返回值:      根据条件决定函数的返回值是第一个或者第二个参数表达式计算结
果。当不存在第三个参数“ELSE-PART”,并且“CONDITION”展开为空,函数返回空。
例子:        SUBDIR += $(if $(SRC_DIR) $(SRC_DIR),/home/src) 
函数的结果是: 如果“SRC_DIR”变量值不为空,则将变量“SRC_DIR”指定
的目录作为一个子目录;否则将目录“/home/src”作为一个子目录。

3. 变量定义的两种方式

  • A. 递归展开方式 VAR = var\
变量值中对其他变量的引用不会被替换展开;而是变量在引用它的地方替换展开的同时,它所引用的其它变量才会被一同替换展开。
  • B.简单方式 VAR := var
变量值中对其他量或者函数的引用在定义变量时被展开(对变量进行替换)
所以变量被定义后就是一个实际需要的文本串,其中不再包含任何变量的引用。
  • C.变量使用$(VAR)
用”$”则用”$$”来表示
 = 是最基本的赋值   
 := 是覆盖之前的值     (后边可跟多变量或列表)
 ?= 是如果没有被赋值过就赋予等号后面的值     
 += 是添加等号后面的值

用?=定义变量   FOO ?= bar
含义是,如果 FOO 没有被定义过,那么变量 FOO 的值就是“bar”,
如果 FOO 先前被定义过,那么这条语将什么也不做,其等价于
ifeq ($(origin FOO),  undefined)
FOO = bar
endif
为变量添加值
你可以通过+=为已定义的变量添加新的值
Main=hello.o hello-1.o
Main+=hello-2.o

4.自动变量

$*	不包含扩展名的目标文件名称
$+	所有的依赖文件,以空格分开,并以出现的先后为序,可能 包含重复的依赖文件
$<	第一个依赖文件的名称
$?	所有时间戳比目标文件晚的的依赖文件,并以空格分开
$@	目标文件的完整名称
$^	所有不重复的目标依赖文件,以空格分开
$%	如果目标是归档成员,则该变量表示目标的归档成员名称

5.预定义变量
ARFLAGS 库文件维护程序的选项,无默认值。
ASFLAGS 汇编程序的选项,无默认值。
CFLAGS C 编译器的选项,无默认值。
CPPFLAGS C 预编译的选项,无默认值。
CXXFLAGS C++编译器的选项,无默认值。
FFLAGS FORTRAN 编译器的选项,无默认值。

6.export
需要将一个在上层定义的变量传递给子 make,应该在上层 Makefile 中使用指示符
“export”对此变量进行声明。格式如下:
export VARIABLE …
7. ( s h e l l . . . ) B U I L D D I R : = (shell ... ) BUILD_DIR := (shell...)BUILDDIR:=(shell cd $(BUILD_DIR) && bin/pwd/ )
进入该文件内并显示其路径。

8. ( e r r o r o u t p u t d i r e c t o r y " (error output directory " (erroroutputdirectory"(saved-output)" does not exist))
显示错误信息,output directory “$(saved-output)” does not exist)

9.include $(TOPDIR)/config.mk
include”指示符告诉 make 暂停读取当前的 Makefile,而转去读取“include”
指定的一个或者多个文件,完成以后再继续当前 Makefile 的读取。Makefile 中指示符
形式如下:
include FILENAMES…
FILENAMES 是 shell 所支持的文件名(可以使用通配符

$(splobj)u-boot-spl: $(SPL_LDS) $(SPL_LIBS) $(SPL_OBJ)
cd $(SPL_LNDIR) && $(LD) $(SPL_LDFLAGS) $(PLATFORM_LIBS) $(SPL_LIBS) $(SPL_OBJ)
-Map $(splobj)u-boot-spl.map
-o $@
10.Make 使用
直接运行 make
选项
-C dir 读入指定目录下的 Makefile
-f file 读入当前目录下的 file 文件作为 Makefile
-i 忽略所有的命令执行错误
-I dir 指定被包含的 Makefile 所在目录
-n 只打印要执行的命令,但不执行这些命令
-p 显示 make 变量数据库和隐含规则
-s 在执行命令时不显示命令
-w 如果 make 在执行过程中改变目录,打印当前目录名

11.函数:

foreach :循环函数,类似for循环。

  • 语法:$(foreach VAR,LIST,TEXT)
  • 函数功能:如果需要(存在变量或者函数的引用),首先展开变量“VAR”和“LIST”的引用;而表达式“TEXT”中的变量引用不展开。执行时把“LIST”中使用空格分割的单词依次取出赋值给变量“VAR”,然后执行“TEXT”表达式。重复直到“LIST”的最后一个单词(为空时结束)。“TEXT”中的变量或者函数引用在执行时才被展开,因此如果在“TEXT”中存在对“VAR”的引用,那么“VAR”的值在每一次展开式将会到的不同的值。
  • 返回值:空格分割的多次表达式“TEXT”的计算的结果

eval 函数:根据其参数的关系、结构,对它们进行替换展开
函数功能:函数“eval”是一个比较特殊的函数。
使用它可以在Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。函数“eval”对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。展开的结果可以包含一个新变量、目标、隐含规则或者是明确规则等。也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开
返回值:函数“eval”的返回值时空,也可以说没有返回值
函数说明:“eval”函数执行时会对它的参数进行两次展开.
第一次展开过程发是由函数本身完成的,第二次是函数展开后的结果被作为Makefile内容时由make解析时展开的。

文本处理函数

$(filter-out PATTERN…,TEXT)

作用:

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

 $(filter-out $(mains),$(objects)) 
 实现了去除变量“objects”中“mains”定义的字串(文件名)功能。它的返回值
为“foo.o bar.o”。

实例:
ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)),$(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)

  1. ( f i l t e r − o u t " " , (filter-out "", (filterout"",(CONFIG_INITRAMFS_SOURCE)) 表示去除后边路径中空格
  2. $(shell echo $(CONFIG_INITRAMFS_SOURCE))
    表示打印出变量
  3. $(if , , -d) 如果第一个成立执行第二个并判断变量是否为目录。

$(strip STRINT)

  • 函数名称:去空格函数—strip。
  • 函数功能:去掉字串(若干单词,使用若干空字符分割)“STRINT”开头和结尾的
    空字符,并将其中多个连续空字符合并为一个空字符。
  • 返回值:无前导和结尾空字符、使用单一空格分割的多单词字符串。
  • 函数说明:空字符包括空格、[Tab]等不可显示字符。

例子

STR =__a__b_c 
LOSTR = $(strip $(STR)) 
结果是“a b c”

$(sort LIST)

  • 函数名称:排序函数—sort。
  • 函数功能:给字串“LIST”中的单词以首字母为准进行排序(升序),并取掉重复
    的单词。
  • 返回值:空格分割的没有重复单词的字串。
  • 函数说明:两个功能,排序和去字串中的重复单词。可以单独使用其中一个功能。
  • 示例:
$(sort foo bar lose foo)
返回值为:“bar foo lose” 。

$(wildcard PATTERN)

  • 函数名称:获取匹配模式文件名函数—wildcard
  • 函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。
  • 返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。
  • 函数说明:“PATTERN”使用shell可识别的通配符,包括“?”(单字符)、“*”(多
    字符)等。

示例:

$(wildcard *.c) 
返回值为当前目录下所有.c 源文件列表。

赋值符号

= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值

makefile中命令前@

  • make会把其要执行的命令行在命令执行前输出到屏幕上。
  1. 当我们用“@”字符在命令行前,当make执行时,会输出“正在编译XXX模块…”字串,但不会输出命令:

如:@echo 正在编译XXX模块......
输出:正在编译XXX模块......

  1. 如果没有“@”,那么,make将输出:

如:echo 正在编译XXX模块......
输出:echo 正在编译XXX模块......

  1. make参数“-n”或“--just-print” & make参数“-s”或“--slient”

如果make执行时,带入make参数“-n”或“–just-print”,那么其只是显示命令,但
不会执行命令,这个功能很有利于我们调试我们的Makefile,看看我们书写的命令是执行
起来是什么样子的或是什么顺序的。
make参数“-s”或“–slient”则是全面禁止命令的显示。

-include FILENAMES…

使用这种方式时,当所要包含的文件不存在时不会有错误提示、make也不会退出;除此之外,和第一种方式效果相同。以下是这两种方式的比较:

使用“include FILENAMES…”,make程序处理时,如果“FILENAMES”列表中的任何一个文件不能正常读取而且不存在一个创建此文件的规则时make程序将会提示错误并退出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值