改变动态库搜索路径

Snake游戏中用了ncurses库开发,使用时只需要包含头文件<ncurses.h>即可。虽然整个程序运行通过,但是移植的时候别的机器不能直接运行,因为别人的机器上不一定就安装了ncurses,所以就需要机器下载ncurses。想想吧,现在的程序都讲究人性化,玩家下载了游戏后就直接可以玩,如果还让用户下载另一个依赖的库,可以预见会有大部分玩家会放弃这款游戏,虽然我这只是一个普普通通的shell端游戏,但是这点策略还是应该有的。

首先想到的就是找到ncurses.h所包含的头文件及头文件所涉及其他头文件,这里只需要ncurses.h和ncurses_dll.h,把这两个文件移到工程中,并新建include文件,将这两个头文件放于此,这时就需要将程序中<ncurses.h>更改为"include /ncurses.h"。有了头文件后编译就能通过了,但是链接时需要ncurses.h中相关函数的实现文件,这时就需要ncurses的动态库帮忙了,whereis libncurses.so,找到动态库存放的路径,你会发现有好几个版本的动态库,到底需要哪个呢?

确定到底动态加载了哪个版本的库,就需要ldd帮忙了,ldd会列出可执行文件依赖的动态库,执行ldd testSnake:

    linux-gate.so.1 =>  (0xb77d4000)
    libX11.so.6 => /lib/libX11.so.6 (0x4574b000)
    libncurses.so.5 => /usr/lib/libncurses.so.5 (0x4702a000)
    ./lib/libIrrKlang.so (0xb7742000)
    libtinfo.so.5 => /usr/lib/libtinfo.so.5 (0x47006000)
    libstdc++.so.6 => /lib/libstdc++.so.6 (0x45925000)
    libm.so.6 => /lib/libm.so.6 (0x4556c000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x455d8000)
    libpthread.so.0 => /lib/libpthread.so.0 (0x45599000)
    libc.so.6 => /lib/libc.so.6 (0x453b1000)
    libxcb.so.1 => /lib/libxcb.so.1 (0x45727000)
    libdl.so.2 => /lib/libdl.so.2 (0x45565000)
    /lib/ld-linux.so.2 (0x4538e000)
    libXau.so.6 => /lib/libXau.so.6 (0x45721000)

可以看到程序依赖/usr/lib/libncurses.so.5和/ust/lib/libtinfo.so.5,这样将这两个动态库拷贝到工程中lib/目录中。这样是否就可以了呢?

此时你运行程序,然后执行ldd后会发现程序依然依赖的是之前的动态库,这时我们就要告诉链接器到lib/中寻找而不是/usr/lib/中寻找。

这就涉及到改变程序加载动态库默认搜索路径问题,有3个方法,

1)在配置文件/etc/ld.so.conf中指定动态库搜索路径,并用命令ldconfig使修改后的配置生效。

2通过环境变量LD_LIBRARY_PATH指定动态库搜索路径,多个路径之间使用:分隔。

3)在编译目标代码时指定该程序的动态库搜索路径。

此处我使用了第3种方法,在编译目标代码时指定程序的动态库搜索路径-Wl,表示后面的参数将传给link程序ld。通过gcc的参数"-Wl,-rpath,"指定。当指定多个动态库搜索路径时,路径之间用冒号""分隔。

-lX11 ./lib/libncurses.so.5 ./lib/libIrrKlang.so ./lib/libtinfo.so.5 -Wl,-rpath,./lib

这样上面列出的3个动态库就从指定的./lib中搜到得到,其他依赖的动态库则依然从默认的搜索路径中得到。

动态库是有搜索顺序的,动态库的搜索路径搜索的先后顺序是:

1.编译目标代码时指定的动态库搜索路径;

2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;

4.默认的动态库搜索路径/lib;

5.默认的动态库搜索路径/usr/lib。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章