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

问题描述:

我试图编译一个使用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

较旧的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