1、make工程管理器
工程管理器,就是管理较多的文件
make工程管理器:也就是“自动编译管理器”。
作用:
1)读取makefile文件编译内容来执行具体编译工作
2)根据文件时间戳自动发现更新过的文件
3)只编译改动的代码文件,而不用完全编译
更多资料见:
https://www.gnu.org/software/make/
2、Makefile语法
Makefile是make读取的唯一配置文件
target: dependency_files
<TAB> command
target: 编译的目标,目标文件或者可执行文件
dependency_files 依赖的文件
command 编译的命令
举个例子:
hello.o: hello.c hello.h
gcc -c hello.c -o hello.o
命令行前面必须是一个“TAB键”,否则编译会报错。
就只对于上面的仅一个test.c文件,按照上面的语法规则我们需要下面的Makefile内容:
test:test.o
gcc test.o -o test
test.o: test.c
gcc -c -Wall test.c -o test.o
Makefile变量
Makef在Makefile中创建和使用变量。变量是在Makefile中定义的一些名字,用来替代一个文本字符串,该文本字符串称为该变量的值。
用户自定义变量
预定义变量
自动变量
环境变量
1)自定义变量:其值由用户自行设定
变量的值可以用来代替目标体、依赖文件、命令以及Makefile文件中的其他部分
2)自动变量:用来代表编译语句中出现的目标文件和依赖文件,具有本地含义。
常见自动变量:
$< 第一个依赖文件的名称
$@ 目标文件的完整名称
$^ 所有不重复的目标依赖文件,以空格分开
$? 所有时间戳比目标文件晚的依赖文件,并以空格分开
3)预定义变量:预先定义好的常见编译器、汇编器的名称及编译选项
CC C编译器的名称,默认值为cc。
RM 文件删除程序的名称,默认值为rm -f
CFLAGS C编译器的选项,无默认值
AR 库文件维护程序的名称,默认为ar
CPP C预编译器的名称,默认值为$(CC) -E
CPPFLAGS C预编译的选项,无默认值
用户可以在一个Makefile中定义一些和编译无关的命令,比如程序的打包、备份和删除等。
注意:.PHONY 说明伪目标
例如:Makefile中添加如下
.PHONY: clean
clean:
-rm f1.o f2.o main.o test
使用方法:make clean
补充规则:
1)隐含规则1:编译C程序的隐含规则
<n>.o 目标的依赖目标会自动推导为<n>.c
2)隐含规则2:链接object文件的隐含规则
<n> 目标的依赖目标会自动推导为<n>.o
@echo $(SUBDIRS)
让echo显示提示
@(RM)
预定义变量, rm -f
Make -C $@
读入指定目录下的Makefile
export CC OBJS BIN OBJS_DIR BIN_DIR
让子makefile可以找到使用这些变量
通过这些Makefile的语法规则,我们就可以变成下面的Makefile:
gcc -Wall 启动所有的gcc警报
gcc -c 生成.o文件
OBJS= test.o
CFLAGS= -c -O -g -Wall
test:$(OBJS)
.PHONY:clean
clean:
-rm $(OBJS)
执行make clean就可以删除掉test.o,执行流程如下:
3、make工具的使用参数
make使用方法:
1)直接运行make
2)make带选项
-C //dir读取指定目录下的Makefile
-f //file读取当前目录下的fiLe作为Makefile
-i //忽略所有的命令执行错误
-l //dir指定被包含的Makefile所在目录
-n //只打印要执行的命令,但不执行这些命令
-p //显示make变量数据库和隐含规则
-s //在执行命令时不显示命令
-w //如果make执行时改变目录,打印当前目录名
4、生成驱动的Makefile
编写一个内核hello.c
#include <linux/module.h> //所有模块都需要的头文件
#include <linux/init.h> // init&exit相关宏
static int __init hello_init(void){
printk(KERN_ERR "hello world");
return 0;
}
static void __exit hello_exit(void){
printk(KERN_EMERG "hello exit!");
}
module_init(hello_init);
module_exit(hello_exit);
ifneq ($(KERNELRELEASE),)
obj-m :=hello.o // 来指定模块名,注意模块名加.o而不是加.ko
else
KERNELDIR ?=/lib/modules/$(shell uname -r)/build // 目标板linux内核源码顶层目录的绝对路径
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
endif
obj-y := hello.o 表示将hello.o编译进内核,工程中按照规范来不要这样写。
Make -C表示存放到内核的目录执行其Makefile
“M=”的作用是:当模块需要以内核为基础编译一个外部模块时,需要在make modules命令中加入"M=dir",程序就会到dir目录下来找你的源文件进行编译,make clean也是类似的,到你当前目录下进行清除工作(删除所有编译生成的文件)。
通过make之后可以生成hello.ko文件,将该文件进行insmod(insert module)操作,就可以将hello.ko文件载入内核,通过dmesg就可以查看载入时的相关信息了。