6.2 LibrariesIn Chapter 4 we discussed how to build, install, and use the GNU C library and its alternatives for application development. Here, we will discuss how to install those same libraries on the target's root filesystem so that they can be used at runtime by the applications we develop. We will not discuss diet libc, because it is mainly used as a static library. 6.2.1 glibcAs I said earlier, the glibc package contains a number of libraries. You can see the entire list of libraries installed during the package's build process by looking at your ${TARGET_PREFIX}/lib directory. This directory contains mainly four types of files:
You will also find some other types of files in ${TARGET_PREFIX}/lib, such as crti.o and crt1.o, but you will not need to copy these to your target's root filesystem. Out of the four types of files described above, we will need only two for each library: the actual shared libraries and the major revision version symbolic links. The two other file types are needed only when linking executables and are not required for the runtime operation of our applications. In addition to the library files, we will need to copy the dynamic linker and its symbolic link. The dynamic linker itself follows the naming convention of the various glibc libraries, and is usually called ld-GLIBC_VERSION.so. In what is probably one of the most bizarre aspects of the GNU toolchain, however, the name of the symbolic link to the dynamic linker depends on the architecture for which the toolchain has been built. If the toolchain is built for the i386, the ARM, the SuperH, or the m68k, the symbolic link to the dynamic linker is usually called ld-linux.so.MAJOR_REVISION_VERSION. If the toolchain is built for the MIPS or the PowerPC, the symbolic link to the dynamic linker is usually called ld.so.MAJOR_REVISION_VERSION. Before we actually copy any glibc component to the target's root filesystem, however, we need to select the glibc components required for our applications. Table 6-2 provides the description of all the components in glibc[1] and provides inclusion guidelines for each component. In addition to my guidelines, you will need to evaluate which components your programs need, depending on their linking.
Apart from keeping track of which libraries you link your applications with, you can usually use the ldd command to find out the list of dynamic libraries that an application depends on. In a cross-platform development environment, however, your host's ldd command will fail when provided with target binaries. You could still use the cross-platform readelf command we installed in Chapter 4 to identify the dynamic libraries that your application depends on. Here is an example showing how the BusyBox utility's dependencies can be retrieved using readelf: $ powerpc-linux-readelf -a ${PRJROOT}/rootfs/bin/busybox | \ > grep "Shared library" 0x00000001 (NEEDED) Shared library: [libc.so.0] Ideally, however, if you installed uClibc, you should use the cross-platform capable ldd-like command installed by uClibc. For our control module target, which is based on a PowerPC board, the command's name is powerpc-uclibc-ldd. This way, you can build the list of libraries your target binaries depend on. Here are the dependencies of the BusyBox utility, for example (one line has been wrapped to fit the page): $ powerpc-uclibc-ldd ${PRJROOT}/rootfs/bin/busybox libc.so.0 => /home/karim/control-project/control-module/tools/uclibc/lib/ libc.so.0 /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 Having determined the library components we need, we can copy them and the relevant symbolic links to the /lib directory of the target's root filesystem. Here is a set of commands that copy the essential glibc components: $ cd ${TARGET_PREFIX}/lib $ for file in libc libcrypt libdl libm \ > libpthread libresolv libutil > do > cp $file-*.so ${PRJROOT}/rootfs/lib > cp -d $file.so.[*0-9] ${PRJROOT}/rootfs/lib > done $ cp -d ld*.so* ${PRJROOT}/rootfs/lib The first cp command copies the actual shared libraries, the second one copies the major revision version symbolic links, and the third one copies the dynamic linker and its symbolic link. All three commands are based on the rules outlined earlier in this section regarding the naming conventions of the different files in ${TARGET_PREFIX}/lib. The -d option is used with the second and third cp commands to preserve the symbolic links as-is. Otherwise, the files pointed to by the symbolic links are copied in their entirety. Of course, you can remove the libraries that are not used by your applications from the list in the set of commands above. If you would rather have the complete set of libraries included in glibc on your root filesystem, use the following commands: $ cd ${TARGET_PREFIX}/lib $ cp *-*.so ${PRJROOT}/rootfs/lib $ cp -d *.so.[*0-9] ${PRJROOT}/rootfs/lib $ cp libSegFault.so libmemusage.so libpcprocfile.so \ > ${PRJROOT}/rootfs/lib If you have applications that use the glibc NSS, don't forget to copy the libnss_SERVICE libraries you need to your target's root filesystem. libnss_files and libnss_dns are the ones most often used. You will also need to copy the sample nsswitch.conf provided with glibc to your target's /etc directory and customize it to your setup:[4]
$ cp ${PRJROOT}/build-tools/glibc-2.2.1/nss/nsswitch.conf \ > ${PRJROOT}/rootfs/etc Whether you copy all or part of the glibc libraries, you will notice that some of these libraries are large. To reduce the size of the libraries installed, we can use the cross-platform strip utility we built earlier. Be careful not to strip the original libraries, since you would have to install them all over again. Strip the libraries only after you copy them to the root filesystem: $ powerpc-linux-strip ${PRJROOT}/rootfs/lib/*.so On my control module, the ${PRJROOT}/rootfs/lib directory with all the glibc libraries weighs around 10 MB before stripping. By stripping all the libraries, the directory is reduced to 2.5 MB. The glibc components have now been installed on the target's root filesystem and are ready to be used at runtime by our applications. 6.2.2 uClibcAs with glibc, uClibc contains a number of libraries. You can see the entire list by looking at your ${PREFIX}/uclibc/lib directory. This directory contains the same four different types of files as the glibc directory. Because uClibc is meant to be a glibc replacement, the names of the uClibc components and their use is identical to the glibc components. Hence, you can use Table 6-2 for uClibc components. Note, however, that not all glibc components are implemented by uClibc. uClibc implements only ld, libc, libcrypt, libdl, libm, libpthread, libresolv, and libutil. Use the same method as described for glibc to identify the uClibc components you will need on your target. Having determined the list of components we need, we can now copy them and their relevant symbolic links to the /lib directory of our target's root filesystem. The following set of commands copies the essential uClibc components: $ cd ${PREFIX}/uclibc/lib $ for file in libuClibc ld-uClibc libc libdl \ > libcrypt libm libresolv libutil > do > cp $file-*.so ${PRJROOT}/rootfs/lib > cp -d $file.so.[*0-9] ${PRJROOT}/rootfs/lib > done The commands are likely to report that two files haven't been found: cp: libuClibc.so.[*0-9]: No such file or directory cp: libc-*.so: No such file or directory This is not a problem, since these files don't exist. The set of commands above is meant to be easy to type in, but you could add conditional statements around the cp commands if you prefer not to see any errors. As with glibc, you can modify the list of libraries you copy according to your requirements. Note that, in contrast to glibc, you will not save much space by copying only a select few uClibc components. For my control module, for instance, the root filesystem's /lib directory weighs around 300 KB when all the uClibc components are copied. The following commands copy all uClibc's components to your target's root filesystem: $ cd ${PREFIX}/uclibc/lib $ cp *-*.so ${PRJROOT}/rootfs/lib $ cp -d *.so.[*0-9] ${PRJROOT}/rootfs/lib There is no need to strip uClibc components, since they were already stripped by uClibc's own build scripts. You can verify this using the file command. |