现在的位置: 首页 > 综合 > 正文

对一个uClinux中的Makefile文件的简单分析(ZT)

2013年09月09日 ⁄ 综合 ⁄ 共 3822字 ⁄ 字号 评论关闭
为了彻底搞清楚linuxuClinux的设备驱动,我觉得有必要找一份devices.txtcopy。那上面详细列出了0255linux主设备号的分配情况,以及各种设备的相应次设备号。对于,我自己开发非标准的linux设备非常有用。uClinux的设备和linux一样,因此这个文档同样适用于uClinux。这个文档可以从下列站点:http://www.lanana.org/docs/device-list/或者ftp://ftp.kernel.org/pub/linux/docs/device-list/获取。作为开发的常用手册,这个文档有必要打印并保存下来。

 

我自己为我的开发板上的按键写了一个驱动,我想要像其他linux标准设备那样在uClinux启动起来时,在/dev目录下有例如/dev/key这样一个设备。但是开始我一直搞不清楚为什么在menuconfigchar deviceinput core菜单中居然没有关于键盘的选项,但键盘驱动又是确实被编译进系统中了。后来,经过比较linuxuClinux后,我发现问题的关键不在于char/目录下的config.in文件,也不在于linux-2.4.x/arch/armnommu/Config.in文件,而在于drivers/char/Makefile文件。

 

简要说一下这个文件,它并不规定menuconfigchar device子菜单的构成,而是规定了drivers/char这个目录下的文件的编译规则。通过在此文件中,加入一些条件判断,并根据条件判断为一些变量赋值,从而达到将特定设备编译进uClinux的内核。

 

下面对Makefile中的一些定义进行解释。

 

编译目标定义:

 

obj-$(CONFIG_TC) += tc.o的语句是用来定义编译的目标,是子目录 Makefile 中最重要的部分。编译目标定义那些在本子目录(对于这个Makefile来说,就是针对/linux-2.4.x/drivers/char子目录)下,需要编译到 Linux 内核中的目标文件列表。为了只在用户选择了此功能后才编译,所有的目标定义都融合了对配置变量的判断。
前面说过,每个配置变量取值范围是:ynm 和空,obj-$(CONFIG_TC) 分别对应着 obj-yobj-nobj-mobj-。如果 CONFIG_TC 配置为 y,那么 tc.o 就进入了 obj-y 列表。obj-y 为包含到 Linux 内核 vmlinux 中的目标文件列表;obj-m 为编译成模块的目标文件列表;obj-n obj- 中的文件列表被忽略。配置系统就根据这些列表的属性进行编译和链接。export-objs 中的目标文件都使用了 EXPORT_SYMBOL() 定义了公共的符号,以便可装载模块使用。在 tc.c 文件的最后部分,有 "EXPORT_SYMBOL(search_tc_card);",表明 tc.o 有符号输出。其中的“obj-y +=”表示如果变量为真,那么就追加什么;而“obj-y =”表示如果变量为真,那么就等于什么。

 

这里需要指出的是,对于编译目标的定义,存在着两种格式,分别是老式定义和新式定义。老式定义就是前面 Rules.make 使用的那些变量,新式定义就是 obj-yobj-mobj-n obj-Linux内核推荐使用新式定义,不过由于 Rules.make 不理解新式定义,需要在 Makefile 中的适配段将其转换成老式定义。

 

另外,需要指出的是linuxuClinux源码树中的Makefile分为两类,一类是由autoconfautomake根据configure.in模板自动生成,另一类是由开发者自己手工写的Makefile。所以,对于前者来说,修改文件中的任何语句或判断条件,都是徒劳无功的。因为每次创建新的配置或修改以前的配置后,Makefile就会被改写或重新生成。要想要通过这种办法达到自己满意的编译配置是不可能的。但后者就不同,由于不是由内核自动生成,因此,不论配置修改多少次,这个文件都是不会改变的。所以,我们可以通过修改Makefile中的语句或判断条件,来达到构建我们自己的编译配置。这一点对添加自己的非标准设备非常有用。

 

适配段:
适配段的作用是将新式定义转换成老式定义。在下面的例子中,适配段就是将 obj-y obj-m 转换成 Rules.make 能够理解的 L_TARGETL_OBJSLX_OBJSM_OBJSMX_OBJS

 

L_OBJS := $(sort $(filter-out $(export-objs), $(obj-y))) 定义了 L_OBJS 的生成方式:在 obj-y 的列表中过滤掉 export-objstc.o),然后排序并去除重复的文件名。这里使用到了GNU Make 的一些特殊功能,具体的含义可参考Make的文档(info make)。

 

显然,由于menuconfig的图形配置菜单中根本没有关于键盘的选项,因此可以看到在obj-y中并没有keyboard.o。那么键盘驱动是怎么编译进char.o的呢?

 

可以注意到:
KEYMAP   =defkeymap.o
KEYBD    =pc_keyb.o
CONSOLE =console.o
SERIAL   =serial.o
这四个变量都被赋值。它们分别表示键盘码和扫描码的映射表、键盘驱动、控制台驱动和串口驱动。上面是四个变量的默认值。

 

在下面这一段中,先判断变量ARCH是否等于sh,如果为真,那么变量为空;紧接着下一级逻辑判断中,判断变量CONFIG_SH_HP600是否为真,如果为真,那么键盘映射表还是适用默认的映射表(defkeymap.o),但键盘驱动就改为hp600_keyb.oscan_keyb.o,控制台驱动不变。但是要注意串口在这一部分中,并没有加入判断语句中,因为串口驱动在下面用obj-$(CONFIG_68328_SERIAL) += 68328serial.o这样的形势单独列出。

 

另外,需要特别指出的是,察看linux或者uClinux各种变量配置的情况,可以看linux-2.4.x/include/linux/autoconf.huClinux-dist/config.in以及linux-2.4.x/config.in这三个文件。

 

 

还有ifeq..)表示假如等于xxx,那么xxxifneq..)便是相反意思,表示假如不等于xxx,那么xxxifdef()表示如果xxx为真,那么xxxifndef()表示如果xxx为假,那么xxx

 

ifeq ($(ARCH),sh)                                     如果ARCH=sh,那么。。。
 KEYMAP   =
 KEYBD    =
 CONSOLE =
 ifeq ($(CONFIG_SH_HP600),y)              如果CONFIG_SH_HP600=y,那么。。。
 KEYMAP   = defkeymap.o
 KEYBD    = scan_keyb.o hp600_keyb.o
 CONSOLE = console.o
 endif
endif

 

ifeq ($(ARCH),mips)
 ifneq ($(CONFIG_PC_KEYB),y)             如果CONFIG_PC_KEYB=y,那么。。。
    KEYBD    =
 endif
endif

 

ifeq ($(ARCH),m68k)
   ifdef CONFIG_AMIGA                        如果CONFIG_AMIGA为真(即变量为y),那么。。。
      KEYBD = amikeyb.o
   else
      ifndef CONFIG_MAC                     如果CONFIG_AMIGA为假,那么。。。
        KEYBD =
      endif
   endif
   SERIAL   =
endif

 

下面这一段很重要。
ifndef CONFIG_SUN_KEYBOARD             如果变量为假,那么判断变量CONFIG_VT

 

 obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD) 
else
 obj-$(CONFIG_PCI) += keyboard.o $(KEYMAP)
endif
结果就是CONFIG_SUN_KEYBOARDSUN公司PC键盘)通常为假(我们不会用到),那么CONFIG_VT是虚拟控制台,通常我们要选择,就是CONFIG_VT=y,那么追加keyboard.o$(KEYMAP)$(KEYBD)。这两个变量在最前面有定义:defkeymap.opc_keyb.o。因此,标准键盘驱动被自动编译进char.o中,进而被编译进内核中。

 

所以,我就可以根据这个道理将自己的按键驱动自动加入到内核中。下面是我加入的一段语句,完成自动将我自己的按键驱动编译进内核。

 

ifeq($(CONFIG_ARCH_S3C44B0),y)
KEYBD = key.o
KEYMAP = mykeymap.o
       CONSOLE = console.o
endif

 

这个Makefile大致就解释到这儿。其实,不过是拿给自己看的罢了。

 

抱歉!评论已关闭.