最近正在搞交叉编译,参考很多博客,学习了一下Makefile的编写,记录一下Makefile内代码是什么意思。

代码如下:(简单的hello.ko的makefile)

ifneq ($(KERNELRELEASE),)
obj-m += hello.o 
else
PWD := $(shell pwd)
KDIR := /home/xuejunjie/raspberry_src/linux-rpi-5.4.y

all:
	make  -C  $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 
clean:
	rm -rf *.o *.mod.c *.ko *.symvers *.order *.makers
endif

ifneq ($(KERNELRELEASE),)
KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读取执行else之后的内容
如果make的目标是clean,直接执行clean操作,然后结束。
当make的目标为all时,-C (KDIR)指明跳转到内核源码目录下读取那里的Makefile;
M=(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。
当从内核源码目录返回时,KERNELRELEASE已被定义,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及要生成的目标模块名。

obj-m := hello.o表示编译连接后将生成param.o模块。
P.S.
obj-m = *.o
obj-y = *.o
上面两者的区别在于,前者才会生成ko文件,后者只是代码编译进内核,并不生成ko文件。
参考:https://blog.csdn.net/xiaocaichonga/article/details/7788778
http://blog.chinaunix.net/uid-31426707-id-5757993.html

PWD := $(shell pwd)
makefile中,要调用shell脚本。需要特殊的语法。比如要调用xxx命令。相应的语法是(shell xxx)
pwd命令是获取当前文件夹所在路径。

modules
编译成模块

make -C (KDIR) M=(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
-C (KDIR):指明跳转到内核源码目录下读取那里的Makefile;
M=(PWD) :表明然后返回到当前目录继续读入、执行当前的Makefile。
ARCH=arm:make ARCH=arm就是编译arch/arm下的代码。
P.S.
ARCH即architecture,就是选择编译哪一种cpu architecture,也就是编译arch/目录下的哪一个子目录。如指定make ARCH=arm就是编译arch/arm下的代码。如果不指定,make将使用本机(用什么机器编译就是什么)的cpu作为缺省ARCH.注意:arch/arm下不但有arm体系架构特有的代码,还有arm特有的kconfig,也就是配置选项,所以在make menuconfig,make xxxx_defconfig的时候也必须指定ARCH=arm。

CROSS_COMPILE=arm-linux-gnueabihf-:make CROSS_COMPILE=arm-linux-gnueabihf-就是使用arm-linux-gnueabihf-gcc工具将代码编译成arm的可执行指令。
P.S.
CROSS_COMPILE即交叉编译器的前缀(prefix),也就是选择将代码编译成目标cpu的指令的工具,如果不指定CROSS_COMPILE参数,make时将认为prefix为空,即使用gcc来编译。这里cross_compile的设置,是假定所用的交叉工具链的gcc程序名称为arm-linux-gcc。如果实际使用的gcc名称是some-thing-else-gcc,则这里照葫芦画瓢填some-thing-else-即可。总之,要省去名称中最后的gcc那3个字母。
在配置或编译内核之前,首先要确定目标CPU架构,以及编译时采用什么工具链。这是最最基础的信息,首先要确定的。
参考:https://blog.csdn.net/zydlyq/article/details/50997582

编译过程:先进入Linux内核所在的目录,并编译出hello.o文件,运行MODPOST会生成临时的hello.mod.c文件,而后根据此文件编译出hello.mod.o,之后连接hello.o和hello.mod.o文件得到模块目标文件hello.ko,最后离开Linux内核所在的目录。
参考:https://blog.csdn.net/njuitjf/article/details/40348491

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐