Makefile语法

Makefile语法

C语言编译过程

预处理:将.h和.c文件处理为.i文件
编译:将.i文件编译为.s文件(汇编文件)
汇编:将.s文件编译为.o文件(二进制文件)
链接:将.o文件链接为.out文件(可执行文件)

GCC编译器参数

gcc -E hello.c > a.txt 只激活预处理,把程序重定向到a.txt文件。
gcc -S hello.c 只激活预处理和编译,把程序编译成汇编文件。
gcc -c hello.c 只激活预处理,编译和汇编,把程序编译成obj文件。 
gcc -o hello.exe hello.c 指定输出文件名称,默认为a.out。
gcc -O0 -O1 -O2 -O3 编译器4个优化等级,-O0表示不优化;-O1表示默认值,-O3优化等级最高。

GNU 的 make 工作时的执行步骤

1、读入所有的 Makefile。 
2、读入被 include 的其它 Makefile。 
3、初始化文件中的变量。 
4、推导隐晦规则,并分析所有规则。 
5、为所有的目标文件创建依赖关系链。 
6、根据依赖关系,决定哪些目标要重新生成。 
7、执行生成命令。

make参数

-C <dir> 读取指定makefile目录,当使用-C参数时,-w会自动被打开。
-I <dir> 指定一个包含makefile的目录
--include-dir=<dir> 指定一个包含makefile的目录
-j <jobsnum> 指同时运行命令的个数
-r 禁止make使用任何隐含规则
-R 禁止make使用任何作用于变量上的隐含规则
-w/--print-directory 进入和退出目录时,会输出Entering directory和Leaving directory。
-s/--slient/--quiet 进入和退出目录时,不会输出Entering directory和Leaving directory,-w总是失效的。
--no-print-directory 进入和退出目录时,不会输出Entering directory和Leaving directory,-w总是失效的。

Makefile文件包含

include 如果找不到包含文件,make就停止。
sinclude 如果找不到包含文件,忽略该错误,继续执行。

Makefile文件注释

#这是一行注释 

Makefile格式

目标文件 : 依赖文件
	(Tab)命令
核心:依赖文件中有一个文件比目标文件新,或者目标文件不存在,就要执行命令。

通配符

* 
? 
[] 
"%" 的意思是表示一个或多个任意字符。

make变量

SHELL
MAKEFLAGS (该变量定义了make参数) 
注意:除非使用unexport声明,否则这两个变量都将传递给下级Makefile。

传递变量

export 变量名 (传递变量到下级Makefile)
export (传递所有变量到下级Makefile)
unexport 变量名 (不传递变量到下级Makefile)

环境变量

KBUILD_EXTMOD //编译外部模块,设置源码路径

内置变量

CURDIR := /home/zht  # 记录当前路径
SHELL = /bin/sh
MAKEFILE_LIST :=  Makefile
.DEFAULT_GOAL := all
MAKEFLAGS = p
HOSTARCH := x86_64
CC = cc 		# C语言编译器的名称
CPP = $(CC) -E  # C语言预处理器的名称 $(CC) -E
CXX = g++       # C++语言的编译器名称
RM = rm -f		# 删除文件程序的名称
CFLAGS			# C语言编译器的编译选项,无默认值
CPPFLAGS  		# C语言预处理器的编译选项,无默认值
CXXFLAGS		# C++语言编译器的编译选项,无默认值
......

自动化变量

$@:目标文件集合
规则中的目标集合,在模式规则中,如果有多个目标的话,“$@”表示匹配模式中定义的目标集合。
$%
当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,那么其值为空。
$<:第一个依赖文件
依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<”就是符合模式的一系列的文件集合。
$? 
所有比目标新的依赖目标集合,以空格分开。
$^:依赖文件集合
所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件,“$^”会去除重复的依赖文件,值保留一份。$+ 和“$^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件。
$*
这个变量表示目标模式中"%"及其之前的部分,如果目标是 test/a.test.c,目标模式为 a.%.c,那么“$*”就是 test/a.test。

变量赋值

定义变量 objects = main.o kbd.o command.o display.o
$() 引用变量 $(objects)
= 变量的值是整个makefile文件中最后被指定的值,最后展开变量。
:= 定义的变量不能使用后面定义的变量,只能使用前面定义好的变量。
?= 变量是否被定义过,未定义则赋值,定义过则什么也不做。
+= 追加变量值

文件搜索

VPATH变量
VPATH变量=src:../headers
设置VPATH变量目录为src和../headers,其中目录名用:隔开。
make默认会在当前目录寻找依赖和目标文件,如果找不到,才会到指定的目录中去寻找文件。

vpath关键字

显示命令 @

echo:在shell中显示echo这条命令和这条命令的输出结果。
@echo:不会在shell中显示echo这条命令,但是会显示命令的输出结果。

执行命令 连续执行

如果你要让上一条命令的结果应用在下一条命令时,应该使用分号分隔这两条命令。
exec: 
cd /home/hchen; pwd

命令出错 在命令行前加-

clean:
	rm -f *.o     //如果出错,不再执行。
	-rm -f *.o     //不管是否出错,都执行。

伪目标 .PHONY

all clean install print tar dist TAGS check test

清理工程

make clean //清除编译的可执行文件和配置文件。
make distclean //清除所有生成的文件。

条件编译

ifeq(a,b) else endif	//判断a和b是否相等
ifneq(a,b) else endif	//判断a和b是否不等
ifdef(a) else endif		//判断a是否被定义
ifndef(a) else endif	//判断a是否未被定义

shell函数

格式:name := $(shell 命令)
shell函数把执行操作系统命令后的输出作为函数返回。我们可以用操作系统命令以及字符串处理命令awk,sed等命令来生成一个变量。
contents := $(shell cat foo) 
files := $(shell echo *.c) 

函数调用

函数调用格式:
	$(<function> <arguments>)
	
字符串处理函数 
	$(subst <from>,<to>,<text>)
	$(patsubst <pattern>,<replacement>,<text>)
	$(strip <string>)
	$(findstring <find>,<in>)
	$(filter <pattern...>,<text>)
	$(filter-out <pattern...>,<text>)
	$(sort <list>)
	$(word <n>,<text>)
	$(wordlist <s>,<e>,<text>)
	$(words <text>)
	$(firstword <text>)
	
文件名操作函数
	$(dir <names...>)
	$(notdir <names...>)
	$(suffix <names...>)
	$(basename <names...>)
	$(addsuffix <suffix>,<names...>)
	$(addprefix <prefix>,<names...>)
	$(join <list1>,<list2>)
	$(foreach <var>,<list>,<text>)
	$(if <condition>,<then-part>)
	$(call <expression>,<parm1>,<parm2>,<parm3>...)
	$(origin <variable>) //查看变量的来源
		函数返回值:
		undefined 		//variable变量未定义,返回undefined。
		default 		//variable是一个环境变量,并且当Makefile被执行时,-e参数没有被打开。
		file 			//variable变量被定义在Makefile中,返回file。
		command line	//variable变量被命令行定义。
		override 		//被override指示符重新定义。
		automatic 		//是一个命令运行中的自动化变量。

C程序的隐含规则

“<n>.o”的目标的依赖目标会自动推导为“<n>.c”,并且其生成命令是“$(CC) –c $(CPPFLAGS) $(CFLAGS)”

Makefile代码分析

make (不带参数) 当make后不带参数时,默认执行第一个伪目标的操作。
make clean 清楚操作
make copy 复制操作
make install 安装操作
KERNELDIR := /home/chen/Linux/linux_kernel/linux_kernel
/* 将路径赋值给KERNELDIR变量 */
CURRENT_PATH := $(shell pwd)
/* 将路径赋值给CURRENT_PATH变量 */
obj-m := helloworld.o
	obj-y +=xxx.o 该模块编译进内核文件。
	obj-m +=xxx.o 该模块不会编译成可加载模块。
/* build kernel_modules clean copy 都是makefile中的伪目标 */
build: kernel_modules
/* build依赖于kernel_modules,其实还是执行的$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules这一条命令。 */
kernel_modules:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
/*	$(MAKE)就相当于make
	-C 选项的作用是指将当前工作目录转移到你所指定的位置。
	“M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成KO文件。
	modules作为参数还可以有以下选择:modules_install clean help */
install:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules_install
clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
copy:
	sudo cp *.ko /home/chen/Linux/nfs/buildroot-rootfs/lib/modules/4.1.15 -f
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Paper_Love

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值