Linux kernel在V2.6之后,modules的编译有些修改。不再是单独编译,而是将本module添加入:obj-m,并最终调用Linux KernelMakefile 来编译modules.
任务一:
这次Sam需要在某一平台上编译Bluetooth driver.其实也就是BlueZ的Kernel部分。但这个平台KernelSource Code做过精简,Bluetooth子系统已经被去掉了。所以Sam将Bluetoothdriver从其它平台Kernel Source Code中抽出来,以Modules的形式加入。
1. 确定copy文件:
Sam需要声成bluetooth.ko, hci_usb.ko, l2cap.ko, hidp.ko。
2. 写Modules Makefile:
ifneq ($(KERNELRELEASE),)
else
default:
endif
这个结构很简单:手动调用Makefile时,会进入else.设置了Kernel目录和当前目录,然后利用 -C进入Kernel Source顶层目录,调用的是Kernel 顶层Makefile。
又因为bluetooth.ko 和hidp.ko是多个文件编译而成的,所以又作了以下动作:
bluetooth-objs := af_bluetooth.ohci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.olib.o
hidp-objs := core.o sock.o #这两句也是从Bluetooth KernelMakefile中抄来的。
3. 将所需要的.c, .h文件从Kernel 树中 copy到本目录内。
4. #make . 4个 ko文件就顺利生产了。
注意:如果当前Kernel树中有Bluetooth目录,则这个办法有缺陷。因为很可能两部分blueZVersion不同,造成很多struct 有变化,无法编译通过。
blueZ版本号: net/bluetooth/af_bluetooth.c中:version就是。
任务二:
工作Linux Server机器上,不同平台的交叉编译工具有不少,所以Sam很不喜欢有人用exportPATH=...的方式指定交叉编译器。这样很容易造成错误和误会。
Sam的办法是:每个人在写Makefile中,都用绝对路径指定所需要的cross comple.但在编译Kernel时,就有问题了。需要去改动Kernel Makefile。这样很不方便。也觉得很硬,一直没有好的办法。
先说之前的办法:
一般是在arch/*/Makefile中去强硬的修改CROSS_COMPILE。这样的问题是,如果ToolChain换了地点或者这份SourceCode 换到另一台机器。就需要再去修改。让人很烦。
今天无意中看了一眼CROSS_COMPILE说明,才发现有非常好的办法:
#make CROSS_COMPLE="绝对路径"/mipsel-linux-
这样就很容易解决了上述问题。 当然,定义环境变量也能达到以上效果。
知识点1:
MIPS架构中的EndianessSelection.
MIPS架构中,有Little endian和Big endian.所以,在针对MIPS架构的Kernel中,有配置大头或小头的选项。 Endianessselection-->
因为MIPS架构中分大小头,所以理所当然,交叉编译器也需要分大小头。
通常,MIPS交叉编译器中会有 mipsel-linux, mips-linux这2个目录。
其中,mips-linux是指 大头(Big endian)所使用的交叉编译器。
mipsel-linux是小头(little endian)所使用的交叉编译器。
知识点2:
LinuxModules版本察看:
Sam在提供bluetooth modules (ko文件)给另家公司时,反映kernel版本与modules版本不同。
kernel版本可以使用#uname -r 来查看。但Modules版本怎么看,一下子来不及查,就直接使用emacs打开ko文件,去看了版本信息。呵呵,觉得太粗暴了。查了一下:
#modinfo xxx.ko 就可以查看。嘿嘿。
知识点3:
mipsel-linux-gcc找不到库位置的处理:
#mipsel-linux-gcc -Wl,-rpath-link-Wl,/home/sam/work/current/BCM/BCM7403/ToolChain/crosstools_sf-linux-2.6.12.0_gcc-3.4.6-21_uclibc-0.9.28-20050817-20070607/mipsel-linux/lib
知识点4:
-rpath, -rpath-link 与 -L的区别。
当Link阶段,找不到库时,编译器会自动找几个地点(具体地点在libtool学习中有)
但
Sam猜想是这样的,如果显式的使用 -lxxx.
如果是c基本库,则只能使用-rpath, -rpath-link。
另外,-rpath, -rpath-link都是给link的,所以需要用 -W1,的形式传递给ld.