【问题标题】:How can I compile SDL2 and GLEW applications statically on Linux?如何在 Linux 上静态编译 SDL2 和 GLEW 应用程序?
【发布时间】:2016-09-30 02:12:25
【问题描述】:

我正在尝试编译一个使用 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 库时,我会收到对 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>

注意:我不认为这个问题与 Stack Exchange 网络上的任何其他问题重复,因为我已经尝试了大约一个半月来解决这个问题,并且我已经看到了很多这样的问题并尝试了其中的所有方法,因此,即使症状相同,潜在的问题也不同。

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

注意:我目前正在尝试通过 g++ 在 Linux 上编译它,但是,我确实打算使用 mingw 来分发这个适用于 Windows 的应用程序。任何可行的建议都比仅适用于 Linux 的建议更可取,但是,如果我无法从最终的结果中弄清楚那部分,我可以问另一个问题。

注意:我使用的是 Ubuntu 16.04 LTS x64 进行编译。

提前感谢您在这个问题上做得这么好。对不起,文字墙,但是,我想提供尽可能多的信息。我期待任何答案!

【问题讨论】:

  • "我正在使用 Ubuntu 16.04 LTS x64 进行编译。"不,必须退回并在 Debian oldstable 上构建所有内容。

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


【解决方案1】:

较早的 Loki 游戏进行了完整的静态链接。可能已经不值得了,如果你使用外部库,那就更难了。

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

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

pkg-config--static 标志应该为您提供依赖项列表(例如,-lpthread 应该在 sdl2-config --static-libs 的输出中等等),但它本身不会产生与给定库的静态链接。要请求静态链接,有-static gcc 标志生成静态可执行文件(硬!)和-Bstatic linker 标志为它之后指定的所有库使用静态版本(这样你就可以使用一些静态库和一些动态库)。 -Bdynamic 是对应的,要求使用动态库。例如。使用静态 SDL 和 GLEW 但动态 GL 链接线应该类似于(如果您使用 gcc 链接,而不是直接 ld)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,您真的介意人们在 wayland 或 mir 上运行您的程序吗?

in such a way that it will run on any version of Linux it may find itself -- not just where it was originally compiled 要复杂得多,老实说几乎不切实际(除非您的程序非常小,并且只使用非常有限的一组具有良好前向/后向兼容性的库 - 但即使那样也可能很难)。 glibc 是一大问题。通常最好使用尽可能低的 glibc 版本来编译您的程序。

总结一下,是可以的,但是帮助不大。

【讨论】:

  • 当您说使用我的应用程序分发 .so 文件时,由于您提到的原因,这听起来是个好主意,我怎么知道我需要包含哪些库以及哪些库可以安全包含?例如,我是否需要包含所有 SDL 的依赖项?如果是这样,我如何找到所有这些的列表?另外,我是否应该按照this 文章的建议静态链接 libstdc++(因为似乎简单地分发我自己的可能行不通,因为它可能不会覆盖用户的版本)?
  • 您可以使用ldd 获取依赖项列表(适用于可执行库和共享库)。它以递归方式工作,因此您获得的可执行文件是一个完整的列表。 libclibmlibdllibpthread 很可能会出现,但对 glibc 版本有影响(genpfault 的评论地址 - 这就是我所说的“最低可能的 glibc”但忘记扩展的意思进一步)。然后你应该应用一些批判性思维 - 例如。如果您的程序仅在图形模式下工作,那么它带来libX11 有点意义。
猜你喜欢
  • 1970-01-01
  • 2019-05-21
  • 2020-05-23
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
相关资源
最近更新 更多