如何在Linux上静态编译SDL2和GLEW应用程序?

时间:2016-09-30 02:12:25

标签: c++ opengl sdl-2 static-linking glew

我正在尝试编译一个使用SDL2和GLEW的OpenGl应用程序,它可以在它可能找到的任何版本的Linux上运行 - 而不仅仅是它最初编译的位置。要做到这一点,我尝试了几件不起作用的事情。

我已尝试直接链接到通过在每个库的网站下载的GLEW和SDL的解压缩根目录中运行make生成的.a文件。这会产生以下错误:

/usr/bin/ld: /opt/SDL2-2.0.4/build/.libs/libSDL2.a(SDL_syssem.o): undefined reference to symbol 'sem_getvalue@@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库时,我得到未定义的参考错误以及未定义的引用错误,如许多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>

注意:我不认为这个问题与Stack Exchange网络上的任何其他问题是重复的,因为我一直试图解决这个问题大约一个半月,我看到了很多这些问题并尝试了其中的一切,因此,即使症状相同,潜在的问题也是不同的。

注意:这是一个闭源应用程序,因此动态链接不是一个选项,它需要分发源代码以允许用户在自己的系统上构建二进制文件。

注意:我目前正在尝试通过g ++使用Linux进行编译,但是,我打算使用mingw来为Windows分发此应用程序。在那里工作的任何建议都比Linux专用建议更可取,但是,如果我能够从最终结果中找出那部分,我可以提出另一个问题。

注意:我正在使用Ubuntu 16.04 LTS x64进行编译。

提前感谢您在这个问题上做到这一点。对于文本墙感到抱歉,但是,我想提供尽可能多的信息。我期待着任何答案!

1 个答案:

答案 0 :(得分:3)

较早的Loki游戏进行了完全静态链接。可能不值得了,如果使用外部库则要困难得多。

库通常不是自给自足的,需要其他库,......动态库内置了依赖信息,但静态库只是.o文件的存档 - 它可能依赖于某些东西但是那里有没有特殊的部分描述应该使用哪些额外的库。您的第一个错误说libSDL2.a使用无法解析的符号sem_getvalue@@GLIBC_2.2.5sem_getvalue函数,标记为glibc版本) - 很可能是因为您没有将-lpthread添加到链接器标志。 (libSDL.so取决于某些版本的pthrtead等等 - 这就是为什么如果不直接使用它就不需要手动链接它。)

GLEW应该没有静态链接的问题。您需要更加具体地了解您遇到的错误。也许你的库命令错了,链接器无法解析GL函数。需要看到实际的链接线和一些“未定义的引用”错误更具体。

pkg-config的{​​{1}}标志应该为您提供依赖项列表(例如,--static应该在-lpthread的输出中,但它本身并不存在与给定的库生成静态链接。要请求静态链接,有sdl2-config --static-libs gcc标志生成静态可执行文件(硬!)和-static 链接器标志,以便为其后指定的所有库使用静态版本(以便你可以使用一些静态库和一些动态的方式)。 -Bstatic是一个对应物,要求使用动态库。例如。使用静态SDL和GLEW,但动态GL链接线应该类似(如果你使用gcc链接,而不是直接ld)-Bdynamic

您的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 -lasoundlibasound2-dev,... - at至少他们在debian上调用它,ubuntu不太可能有不同的名字)。 '用户'库通常包含例如libpulse-dev但链接器将找不到此库,因为它有一个版本。开发包包含头文件和符号链接libasound.so.2 - 这样链接器就知道要使用什么。如果您通过SDL2间接使用它 - 您不需要它,共享SDL2已经有版本化库的链接。

然而,这样做可能没什么意义。您可以使用您的软件分发需要的共享库,并通过libasound.so -> libasound.so.2rpath环境变量(maya,steam等等)使用它们 - 几乎每个人都在这些日子里这样做。此外,即使使用静态SDL2,最终用户也可以使用自己的SDL2覆盖SDL2(这是在SDL2中有意实现的功能)。如果存在错误(或者只是非常不同的环境)并且您的软件不再获得更新 - 可能只需更换共享库就可以解决问题。如果您的原始SDL2仅支持X11,您真的会介意人们在Wayland或mir上运行您的程序吗?

LD_LIBRARY_PATH要复杂得多,而且实际上几乎是不切实际的(除非你的程序非常小,并且只使用非常有限的一组具有良好向前/向后兼容性的库 - 但即使这样也可能很难)。一个大问题是glibc;通常最好使用最低版本的glibc来编译程序。

总结一下,这是可能的,但它没有多大帮助。