• 重编译Linux命令源代码


    转: http://blog.csdn.net/endoresu/article/details/6967435

    以su命令为例。

    查看su命令的路径:
    # which su
    /bin/su

    查看su是由哪个包安装的:
    # rpm -qf /bin/su
    coreutils-5.97-12.1.el5

    去网上搜索“coreutils-5.97-12.1.el5.src.rpm”包,注意,后面还多了个“.src”,表示源代码的安装包。

    将下载到的源代码的包直接安装是行不通的,需要先安装下列.rpm包:
    elfutils-libs-0.125-3.el5.i386.rpm
    elfutils-0.125-3.el5.i386.rpm
    rpm-build-4.4.2-47.el5.i386.rpm

    安装完上面的包,就可以安装任意源代码的包了。注意,使用命令
    # rpm -ivh coreutils-5.97-12.1.el5.src.rpm
    安装时会报错,但这没影响。安装包依然会在/usr/src/redhat/SOURCES/目录下生成我们想要的。

    进入/usr/src/redhat/SOURCES/目录,解压缩coreutils-5.97.tar.bz2:
    # bzip2 -d coreutils-5.97.tar.bz2
    #tar -xvf coreutils-5.97.tar

    进入解压出来的coreutils-5.97目录,各命令的源代码就放在src目录中,需要的头文件放在lib目录中。直接用
    # gcc -I/usr/src/redhat/SOURCES/coreutils-5.97/lib/ -E -o su.i /usr/src/redhat/SOURCES/coreutils-5.97/src/su.c
    是无法生成预处理文件的,因为源代码需要的某些头文件是由coreutils-5.97目录下的configure脚本产生的,有些头文件是由make命令产生的。

    运行configure配置脚本:
    # ./configure --prefix=/tmp/coreutils/prefix
    其中--prefix参数的作用是指定安装路径为等号后面的“/tmp/coreutils/prefix”,这是一个我自建的目录。configure脚本将生成Makefile文件,这是一个提供给make命令用于编译的配置文件,其中包含当前安装环境的信息。

    运行make命令,这里我们需要重定向命令的输出,以便从中查找有用的信息:
    # make>/tmp/coreutils/make.log
    步骤到此,其实所有命令的可执行程序已经被编译出来了,在src目录下,只是还没移动到我们指定的安装路径去,文件的属性也还没修改。只要再执行
    # make install
    这个命令才算完全安装完成。这里我们不需要这步。

    到这一步,如果你修改了su命令的源代码,想重新编译的话需要把整个所有命令都编译一遍,非常浪费时间。下面介绍下怎么把su.c单独拿出来编译。

    我们把su命令的源代码复制到自己的目录下,我这边是/tmp/coreutils/
    然后就能预编译了:
    # gcc -E -I/usr/src/redhat/SOURCES/coreutils-5.97/lib/ -I/usr/src/redhat/SOURCES/coreutils-5.97/ -I/usr/src/redhat/SOURCES/coreutils-5.97/src/ -o su.i su.c
    -E参数告诉gcc只要进行预编译,-o参数告诉gcc将预编译输出到文件su.i,-I/usr/src/redhat/SOURCES /coreutils-5.97/lib/告诉gcc在/usr/src/redhat/SOURCES/coreutils-5.97/lib/目录下 寻找头文件。

    将预编译文件su.i编译成.o文件:
    # gcc -c -o su.o su.i
    -c参数告诉gcc将源代码编译成.o文件。

    链接静态库libcoreutils.a、动态库libcrypt.so,生成可执行文件su:
    # gcc -L/usr/src/redhat/SOURCES/coreutils-5.97/lib/ -L/usr/lib/ -o su su.o -lcoreutils -lcrypt
    注意两个-L参数写在一起,两个-l参数写在一起。-L参数告诉gcc库文件的位置,-l参数指明了库文件的文件名。如-lcoreutils,其文件名 为libcoreutils,在前面加个lib就行了。至于后缀,没有什么讲究,因为一般名字都不一样,就不深究了。.a库是静态库,链接完可以独立库运 行;.so库是动态库,链接完缺少库就不能单独运行。
    简单地用
    # gcc -o su su.o
    会报错,错误信息都是找不到需要的函数。因为.o文件的源代码中调用了本身没有具体实现的函数(可能声明过),这些函数也编译在了包含它的.o文件或者.a、.so文件。在编译成可执行文件时,需要将这些可执行文件一并链接起来。
    libcoreutils.a文件包含了编译所有命令可能需要调用的函数。

    如何知道一个.o/.a/.so文件中包含哪些函数?使用nm命令:
    #nm /usr/lib/libcrypt.so

    OK。到此你修改su命令的源代码,可以单独编译它了。不用为了编译su命令的源代码,把整个命令都编译一遍。可以把需要的头文件、库复制下来。其 中config.h这个头文件configure脚本产生的,它在/usr/src/redhat/SOURCES/coreutils-5.97/目录 下面;localedir.h在/usr/src/redhat/SOURCES/coreutils-5.97/src/目录下面,由make命令产生 的。其实localedir.h的内容非常简单
    #define LOCALEDIR "/tmp/coreutils/prefix//share/locale"
    就是把执行configure脚本时prefix参数的内容后面接上“/share/locale”。完全可以自己写一个。但是make命令还是要执行的,静态库libcoreutils.a是由make命令产生的。
    直接把所有头文件复制到一个目录下,-I参数就省了很多。

    两个需要的库路径为:
    /usr/src/redhat/SOURCES/coreutils-5.97/lib/libcoreutils.a
    /usr/lib/libcrypt.so

    config.h头文件路径为:
    /usr/src/redhat/SOURCES/coreutils-5.97/config.h

    其他头文件的路径为:
    /usr/src/redhat/SOURCES/coreutils-5.97/lib/*.h
    /usr/src/redhat/SOURCES/coreutils-5.97/src/*.h

    删除之前安装的命令,很简单,之前configure的脚本指定prefix参数的值为/tmp/coreutils/prefix,参数这个目录就行了。然后还要清除由configure、make产生的文件:
    # make clean
    # make distclean

  • 相关阅读:
    WF4.0 基础 InvokeMethod 调用方法
    MySQL数据库表名、列名、别名区分大小写的问题
    客户端调用Web服务
    something about Socket
    C#参数传递
    学习内容
    About HttpContext
    Best Sequence [POJ1699] TSPDP
    优先队列
    Watermelon Full of Water [ZOJ 4778]
  • 原文地址:https://www.cnblogs.com/xiaoyaodao/p/3438584.html
Copyright © 2020-2023  润新知