2016-09-30 359 views
0

我試圖編譯一個使用SDL2和GLEW的OpenGl應用程序,它可以在它可能發現的任何版本的Linux上運行,而不僅僅是它最初編譯的位置。要做到這一點,我嘗試了幾件事情,其中​​沒有一件可以工作。如何在Linux上靜態編譯SDL2和GLEW應用程序?

我試着直接連接到.a文件,通過在每個庫的網站下載中提取的GLEW和SDL根目錄下運行make生成。這將產生以下錯誤:

/usr/bin/ld: /opt/SDL2-2.0.4/build/.libs/libSDL2.a(SDL_syssem.o): undefined reference to symbol '[email protected]@GLIBC_2.2.5' 
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line 

我已經嘗試建設爲我做的動態鏈接庫,其中工程除跨平臺能力,(與pkg-config --libs sdl2pkg-config --libs glew),但加入-static精細,在這一點上我得到以下錯誤:

/usr/bin/ld: cannot find -lGLEW 
/usr/bin/ld: cannot find -lGL 

當我改變以前的情景指向我的靜態編譯GLEW庫,我得到了一個未定義引用錯誤,以OpenGL函數與像許多SDL功能的以下未定義的引用錯誤一起。添加-lGL不會改變任何東西。

/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadObject_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadObject_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadFunction_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadFunction_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadFunction_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_UnloadObject_REAL': 

當我嘗試使用pkg-config --libs --static <library name>所有庫,我得到以下錯誤:

/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/bin/ld: cannot find -lasound 
/usr/bin/ld: cannot find -lpulse-simple 
/usr/bin/ld: cannot find -lpulse 
/usr/bin/ld: cannot find -lsndio 
/usr/bin/ld: cannot find -lwayland-egl 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libwayland-cursor.a(libwayland_cursor_la-xcursor.o): In function `XcursorImagesDestroy': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libXcursor.a(file.o):(.text+0x7d0): first defined here 
/usr/bin/ld: cannot find -lGLEW 
/usr/bin/ld: cannot find -lGL 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libX11.a(GetDflt.o): In function `GetHomeDir.part.0': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libX11.a(GetDflt.o): In function `GetHomeDir.part.0': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libX11.a(xim_trans.o): In function `_XimXTransSocketINETConnect': 
collect2: error: ld returned 1 exit status 

注意:所有的輸出上面的命令g++ -o /path/to/outputExecutable <list of object files>.o <libraries as described above>

注:我不認爲這個問題是堆棧交換網絡上任何其他問題的重複,因爲我一直試圖弄清楚這個問題大約一個半月,而且我看到了很多這些問題並嘗試了其中的所有內容,因此,即使s基本問題是不同的,ymptoms是一樣的。

注意:這是一個封閉的源代碼應用程序,因此動態鏈接不是一個選項,因爲它需要分發源代碼以允許用戶在自己的系統上構建二進制文件。

注意:我目前正試圖通過g ++將它與Linux進行編譯,但是我打算使用mingw來爲Windows分發此應用程序。任何在那裏工作的建議都優於僅限於Linux的建議,但是,如果我無法弄清楚最終會發生什麼,那麼我可以提出另一個問題。

注:我正在使用Ubuntu 16.04 LTS x64進行編譯。

預先感謝您在這個問題中甚至得到這個。對不起,我想提供儘可能多的信息。我期待着任何答案!

+1

「我正在使用Ubuntu 16.04 LTS x64進行編譯。」不管怎麼說,都得退後一步,在Debian的舊版本上構建一切。 – genpfault

回答

3

較舊的Loki遊戲做了全面的靜態鏈接。可能不值得它了,而且如果你使用外部庫,則會更加困難。

庫往往不是自給自足的,需要其他庫,....動態庫有內置的依賴信息,但靜態庫只是.o文件的存檔 - 它可能取決於某些東西,但沒有特殊的部分描述應該使用哪些額外的庫。您的第一個錯誤是,libSDL2.a使用無法解析的符號[email protected]@GLIBC_2.2.5sem_getvalue函數,標記爲glibc版本) - 很可能是因爲您沒有將-lpthread添加到鏈接器標記。(libSDL.so取決於pthrtead的某些版本等 - 這就是爲什麼你不需要手動鏈接它,如果你不直接使用它)。

GLEW應該沒有靜態鏈接的問題。你需要對你遇到的錯誤更具體。也許你的庫命令錯了,鏈接器無法解析GL函數。需要看到實際的鏈接線和一些「未定義的參考」錯誤更具體。

pkg-config--static標誌應該給你的依賴列表(例如:-lpthread應在sdl2-config --static-libs輸出以及許多其他),但它本身產生與給定的庫靜態鏈接沒有。要請求靜態鏈接,有-static gcc標誌生成靜態可執行文件(hard!)和-Bstatic鏈接器標誌爲靜態版本指定後面指定的所有庫(這樣您可以使用一些靜態庫和一些動態)。 -Bdynamic是對等的,要求使用動態庫。例如。要使用靜態SDL和GLEW,但動態GL鏈接線應該類似於(如果使用gcc鏈接,而不是直接鏈接)gcc ${OBJECT_FILES} -Wl,-Bstatic -lSDL2 -lGLEW -Wl,-Bdynamic -lGL -lpthread -ldl -lm <everything else SDL2 requires - query with sdl2-config>

/usr/bin/ld: cannot find -lasound線可能有兩個原因 - 靜態鏈接或與之相關的事實,你沒有安裝開發庫做(例如libasound2-devlibpulse-dev,... - 至少他們稱那Debian的,這是不可能的ubuntu有不同的名字)。 '用戶'庫通常包含例如libasound.so.2但鏈接器不會找到這個庫,因爲它有一個版本。開發包包含頭文件和符號鏈接libasound.so -> libasound.so.2 - 鏈接器知道該使用什麼。如果您通過SDL2間接使用它 - 您不需要它,共享的SDL2已經鏈接到版本化的庫。

然而,這樣做可能沒有多大意義。您可以使用您的軟件分發必需的共享庫,並通過rpathLD_LIBRARY_PATH環境變量(maya,steam等)使用它們 - 幾乎每個人都在這些日子裏進行這些操作。而且,即使使用靜態SDL2最終用戶也可以自行覆蓋SDL2(這是SDL2中有意實現的功能)。如果存在一個錯誤(或者只是非常不同的環境),並且您的軟件不再獲取更新 - 那麼通過替換共享庫可能會解決問題。如果你原來的SDL2只支持X11,你會不會介意在路上或者是在mir上運行你的程序? (除非你有相當小的程序,只使用非常有限的一組庫,具有良好的向前/向後兼容性 - 但即使如此,它也可能很難實現)。其中一個大問題是glibc;通常使用最低版本的glibc來編譯程序是一個好主意。總結起來,這是可能的,但它沒有多大幫助。

+0

當您說要將.so文件與我的應用程序一起發佈時,由於您提到的原因這聽起來像是個好主意,我怎麼知道我需要包含哪些庫以及哪些庫可以安全地包含在內?例如,我是否需要包含所有SDL的依賴關係?如果是這樣,我如何找到所有這些列表?另外,我應該靜態鏈接libstdC++作爲[this](https://insanecoding.blogspot.com/2012/07/creating-portable-linux-binaries.html)文章推薦(因爲它似乎只是簡單地分發我自己可能無法正常工作因爲它可能不會覆蓋用戶的版本)? – john01dav

+1

您可以使用[ldd](https://linux.die.net/man/1/ldd)獲取依賴項列表(適用於可執行文件和共享庫)。它遞歸地工作,所以你得到的可執行文件是一個完整的列表。'libc','libm','libdl'和'libpthread'很可能存在,但是glibc版本會有影響(genpfault的註釋地址 - 這就是我所說的「儘可能低的glibc」,但忘記擴展進一步)。那麼你應該應用一些批判性思維 - 例如如果你的程序只能在圖形模式下運行,那麼它會帶來'libX11'。 – keltar

相關問題