嵌入式Linux-根文件系统2_(利用交叉编译工具链,构建/lib目录)

2019-07-12 17:25发布

光有应用程序(命令)是不够的,因为应用程序本身需要使用C库的库函数,因此还必需制作for ARMC库,并将其放置于/lib目录。my god,要自己写C库的源代码吗?不用!还记得交叉编译工具链的3个组成部分吗?交叉编译器、for ARMC库和二进制工具。我们只需要把嵌入式的C库拷贝过来就可以了。遗憾的是:整个C库目录下的文件总大小有26M。而我们根文件系统所在分区不过区区16M而已,根本放不下。怎么办呢?$ du -s --si/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib
26M     /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib
需要C库目录下所有的文件吗?noabsolutely no! 让我们来分析一下glibc库目录下内容的组成。该目录下的子目录和文件共分8类:    1   目标文件,如crtn.o,用于gcc链接可执行文件    2 libtool库文件(.la),在链接库文件时这些文件会被用到,比如他们列出了当前库文件所依赖的其它库文件,程序运行时无需这些文件    3  gconv目录,里面是各种链接脚本,在编译应用程序时,他们用于指定程序的运行地址,各段的位置等    4  静态库文件(.a),例如libm.alibc.a     5 动态库文件.so.so.[0-9]*    6动态链接库加载器ld-2.3.6.sold-linux.so.2     7  其它目录及文件    很显然,第12347类文件和目录是不需要拷贝的。   由于动态链接的应用程序本身并不含有它所调用的C库函数的代码,因此执行时需要动态链接库加载器来为它加载相应的C库文件,所以第6类文件是需要拷贝的。   除此之外,第5类文件当然要拷贝。但第5类文件的大小也相当大。 du -c --si *.so* 7.2M    total 需要全部拷贝吗?非也,非也!其实,需要哪些库完全取决于要运行的应用程序使用了哪些库函数。如果我们只制作最简单的系统,那么我们只需要运行busybox这一个应用程序即可。通过执行$arm-linux-readelf -a bin/busybox | grep 'Shared'0x00000001(NEEDED)                    Shared library: [libcrypt.so.1]
0x00000001(NEEDED)                    Shared library: [libm.so.6]
0x00000001 (NEEDED)                    Shared library: [libc.so.6]
可知:busybox只用到了3个库:通用C库(libc)、数学库(libm)、加密库(libcrypt),因此我们只需要拷贝这3个库的库文件即可。但是每个库都有4个文件,4个文件都要拷贝吗?当然不$ls -l libcrypt[.-]*
-rwxr-xr-x 1 dennis dennis 30700 2008-01-22 05:32 libcrypt-2.3.6.so
-rw-r--r-- 1 dennis dennis 23118 2008-01-22 05:32 libcrypt.a
lrwxrwxrwx 1 dennis dennis    13 2008-12-22 15:38 libcrypt.so-> libcrypt.so.1
lrwxrwxrwx 1 dennis dennis    17 2008-12-22 15:38 libcrypt.so.1-> libcrypt-2.3.6.so
$ ls -llibm[.-]*
-rwxr-xr-x 1 dennis dennis  779096 2008-01-22 05:31 libm-2.3.6.so
-rw-r--r-- 1 dennis dennis 1134282 2008-01-22 05:32 libm.a
lrwxrwxrwx 1 dennis dennis       9 2008-12-2215:38 libm.so -> libm.so.6
lrwxrwxrwx 1 dennis dennis      13 2008-12-22 15:38libm.so.6 -> libm-2.3.6.so
$ ls -llibc[.-]*
-rwxr-xr-x 1 dennis dennis 1435660 2008-01-22 05:48 libc-2.3.6.so
-rw-r--r-- 1 dennis dennis 2768280 2008-01-22 05:31 libc.a
-rw-r--r-- 1 dennis dennis     195 2008-01-22 05:34 libc.so
lrwxrwxrwx 1 dennis dennis      13 2008-12-22 15:38libc.so.6 -> libc-2.3.6.so
4个文件中的.a文件是静态库文件,是不需要拷贝的。另外3个文件是:·     实际的共享链接库:libLIBRARY_NAME-GLIBC_VERSION.so。当然需要拷贝。·    主修订版本的符号链接,指向实际的共享链接库:libLIBRARY_NAME.so.MAJOR_REVISION_VERSION,程序一旦链接了特定的链接库,将会参用该符号链接。程序启动时,加载器在加载程序前,会检索该文件。所以需要拷贝。·   与版本无关的符号链接,指向主修订版本的符号连接(libc.so是唯一的例外,他是一个链接命令行:libLIBRARY_NAME.so,是为编译程序时提供一个通用条目)。这些文件在程序被编译时会被用到,但在程序运行时不会被用到,所以不必拷贝它。关于共享库的2个符号链接的作用的特别说明:当我们使用gcc   hello.c    -o    hello    -lm编译程序时,gcc会根据-lm的指示,加头(lib)添尾(.so)得到libm.so,从而沿着与版本无关的符号链接(libm.so -> libm.so.6)找到libm.so.6并记录在案(helloELF头中),表示hello需要使用libm.so.6这个库文件所代表的数学库中的库函数。而当hello被执行的时候,动态链接库加载器会从helloELF头中找到libm.so.6这个记录,然后沿着主修订版本的符号链接(libm.so.6 -> libm-2.3.6.so)找到实际的共享链接库libm-2.3.6.so,从而将其与hello作动态链接。可见,与版本无关的符号链接是供编译器使用的,主修订版本的符号链接是供动态链接库加载器使用的,而实际的共享链接库则是供应用程序使用的。通过以上分析,我们只需要拷贝3个库(每个库各1个主修订版本的符号链接和1个实际的共享链接库)以及动态链接库加载器(1个符号链接和1个实体文件)。步骤如下:cd  /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib:
$mkdir /work/rootfs/lib $cp  libcrypt-* /work/rootfs/lib
$ cp -llibcrypt.so.* /work/rootfs/lib
$ cp libm-* /work/rootfs/lib
$ cp -llibm.so.* /work/rootfs/lib
$ cp libc-* /work/rootfs/lib
$ cp -llibc.so.* /work/rootfs/lib $cp -l ld-* /work/rootfs/lib