编译内核前,配置内核用Initramfs挂载根文件系统,配置选项如下:
Genera setup-------------------------------->
[ * ] Initial RAM filesystem and RAM disk (initramfs/initrd)support
( /home/myrootfs )Initramfs source file(s)
配置完毕,第一次编译OK。但是编译第二次时就出问题了,编译过程终止在了/user/Makefil里面,错误原因是多个目标匹配。详细信息如下:
-
root@localhost kernels]# make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm uImage
-
CHK include/linux/version.h
-
CHK include/generated/utsrelease.h
-
make[1]: “include/generated/mach-types.h”是最新的。
-
CALL scripts/checksyscalls.sh
-
CHK include/generated/compile.h
-
/home/ASM335/kernel/kernels/usr/Makefile:58: *** 多个目标匹配。 停止。
-
make: *** [usr] 错误 2
我试着make clean和make disiclean,都不行,任然停在上面那个地方,同样的问题。我又试着把Initial RAM filesystem and RAM disk (initramfs/initrd)support取消,还是同样的错误。根据提示,问题出现在了/usr/Makefile的第58行,我打开/usr/目录下的Makefile,定位到58行,发现时一个变量:$(deps_initramfs)
其实后面网上看了很多博客,不少人也碰到了多目标匹配报错的问题,他们问题的原因大都由于作为目标的变量中(这些变量有时会是文件名或路径名)包含冒号( :)。大家都知道Makefile规则的格式是:
目标:依赖
相关指令
若代表目标的变量中包含冒号,则会别识别成多个目标。于是,我打算把$(deps_initramfs)的值打印出来,看看里面是否含冒号。我在$(deps_initramfs)前面加上$(warning $(deps_initramfs)),打印出了一大堆路径,占据了我的整个显示终端,仔细阅读这些路径,发现全是我根文件系统里的文件。猜测 $(deps_initramfs)的值是Initramfs source file(s)
里所有文件的绝对路径。
如何确定这些路径是否有冒号?从显示终端打印出的路径里用眼睛找?显然不可能!而且根文件系统文件比较多,路径也比较长,我的显示终端只能看到部分文件路径,好多跑前面去了,无法看到。我知道我的路径肯定不可能有冒号的,那么文件名呢?我试着在文件系统里新建一个文件,命名的时候加个冒号,结果报错,显然文件名也不能有冒号啊!何解?到这里我无从下手了。接着网上找资料!
直到后来。找到一篇博客,也是和我一样的问题,它介绍了一个解决方法。我照着它的方法来,发现还真管用。
它是用make -d命令打印出详细的编译信息,然后根据打印出的调试信息,找到与你问题相关部分(应该是最后几行吧,因为编译过程会停在有问题的地方)。我使用make -d命令,与/usr/Makefile相关的如下:
-
正在读入 makefile “/home/ASM335/kernel/kernels/usr/Makefile” (搜索路径) (no ~ expansion)...
-
正在读入 makefile “usr/.initramfs_data.cpio.d” (搜索路径) (no ~ expansion)...
-
/home/ASM335/kernel/kernels/usr/Makefile:58: *** 多个目标匹配。 停止。
-
正在中止失败的子进程 0x08acc7e8 PID 16580
-
make: *** [usr] 错误 2
-
Removing child 0x08acc7e8 PID 16580 from chain.
-
学着那篇博客,我把/usr/.initramfs_data.cpio.d删除,然后重新编译,OK。问题解决。至于为什么会出现这个问题,一下子没弄明白。
参考博客:
http://blog.csdn.net/zjujoe/article/details/3185382
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
补充:
造成上述原因的确实是冒号的问题。我打开了/usr/.initramfs_data.cpio.d文件:
-
deps_initramfs := /home/asm335/kernel/kernels/scripts/gen_initramfs_list.sh
-
/home/asm335/rootfs
-
/home/asm335/rootfs/sys
-
/home/asm335/rootfs/var
-
/home/asm335/rootfs/var/spool
-
/home/asm335/rootfs/var/spool/mail
-
/home/asm335/rootfs/var/lib
-
/home/asm335/rootfs/var/lib/misc
-
/home/asm335/rootfs/var/lib/opkg
-
/home/asm335/rootfs/var/lib/opkg/lists
-
/home/asm335/rootfs/var/lib/opkg/info
-
/home/asm335/rootfs/var/lib/opkg/info/libasound2.list
-
.....................................
文件里面其实就是deps_initramfs变量的赋值!在打开的.initramfs_data.cpio.d文件查找冒号,不找不知道,一找吓一跳啊,一大堆冒号:
再看看/usr/Makefile里deps_initramfs的位置
$(deps_initramfs)是一个目标啊,而deps_initramfs所代表的路径里又含有冒号,难怪会识别成多目标匹配!
另外,包含冒号的文件都在/etc/usb_modeswitch.d目录下(这些都是产品设备号?)
纠正一点:前面说文件名不能有冒号,这句话其实是错的。在Windows中文件名不能有冒号,但是在linux中是可以有冒号的!可以touch一个带名字冒号的文件试试看。
回过头来看:make是之所以会说多目标匹配,想必一定发现了多个目标。而网上好多文章都说Makefile里的目标包含冒号的话会导致这个问题。那么,解决问题的思路应该是:定位到出问题的Makefile里面的那个目标,然后想办法把相关变量的值导出来看看里面有没有冒号。在本次问题中,/usr/.initramfs_data.cpio.d文件中恰好就是deps_initramfs变量的值,直接搜索冒号即可。
一些疑惑:既然deps_initramfs所代表的路径包含冒号,那为什么第一次编译时OK的呢?而后面的编译就出问题? .initramfs_data.cpio.d 到底是什么文件,在使用initramfs挂载根文件系统时扮演什么角 {MOD}。这些就得学习initramfs的知识了。这里推荐一篇博客:
http://blog.chinaunix.net/uid-26009923-id-4072464.html
原文链接:
http://blog.csdn.net/andoubi/article/details/52052186