改變動態庫搜索路徑

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。


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