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。