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

How can I compile SDL2 and GLEW applications statically on Linux?

我正在尝试编译一个使用 SDL2 和 GLEW 的 OpenGl 应用程序,它会 运行 在任何版本的 Linux 它可能会找到自己 -- 而不仅仅是它在哪里最初编译。为此,我尝试了几种方法 none,其中一些有效。

我试过直接链接到 运行ning make 在每个图书馆网站下载的 GLEW 和 SDL 解压根目录中生成的 .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 进行编译。

提前感谢您在这个问题上能走到这一步。很抱歉文字墙,但是,我想提供尽可能多的信息。我期待任何答案!

较早的 Loki 游戏使用全静态 linking。可能不再值得了,如果你使用外部库会更困难。

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

GLEW 应该没有静态 linking 的问题。您需要更具体地说明您遇到的错误。也许您的库顺序有误,linker 无法解析 GL 函数。需要查看实际的 linking 行和一些 'undefined reference' 更具体的错误。

pkg-config--static 标志应该给你依赖列表(例如 -lpthread 应该在 sdl2-config --static-libs 的输出中等等),但它没有本身使用给定的库生成静态 linking。要请求静态 linking,有 -static gcc 标志生成静态可执行文件(硬!)和 -Bstatic linker 标志对其后指定的所有库使用静态版本(这样你就可以使用一些静态库和一些动态库)。 -Bdynamic是对口的,要求使用动态库。例如。使用静态 SDL 和 GLEW 但动态 GL linking 行应该是这样的(如果你使用 gcc 到 link,而不是直接使用 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 行可能有两个原因 - 静态 linking 或与您没有安装开发库的事实有关(例如 libasound2-devlibpulse-dev, ... - 至少他们在 debian 上这么叫,不太可能 ubuntu 有不同的名字)。 'User' 库通常包含例如libasound.so.2 但 linker 将找不到这个库,因为它有一个版本。开发包包含 headers 和 symlink libasound.so -> libasound.so.2 - 这样 link 就知道该用什么了。如果您通过 SDL2 间接使用它 - 您不需要它,共享 SDL2 已经有一个 link 版本库。

然而,这样做可能毫无意义。您可以将所需的共享库与您的软件一起分发,并通过 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 要复杂得多,老实说几乎是不现实的(除非你的程序很小并且只使用非常有限的一组具有良好 forward/backward 兼容性的库 - 但即使那样它也可能是难的)。大问题之一是 glibc;通常最好使用尽可能低的 glibc 版本来编译您的程序。

综上所述,有可能,但帮助不大。