从静态库动态链接?

Dynamically linking from a static libarary?

我目前正在尝试在我的 Ubuntu 14.04 机器上重建 FlightGear。一切都很顺利,直到我决定构建需要 Qt 的 fgrun。我决定将 Qt 编译为静态库,因为我不希望自建库超过 运行 系统上的任何库。

我是这样在系统上静态构建 Qt 的:

./configure -static -opensource -nomake tests -gtkstyle -prefix /home/user/Qt/5.4/Src/qtbuild -no-rpath -no-compile-examples -system-proxies -skip qtwebkit -skip qtwebkit-examples -nomake tools -nomake examples -skip script -release -skip multimedia -verbose -l dl -skip location -skip multimedia -skip quick1 -skip quickcontrols -skip sensors -skip serialport -skip svg -skip tools -skip translations -skip wayland -skip webchannel -skip webengine -skip xmlpatterns -skip activeqt -skip connectivity -skip declarative -skip doc -skip enginio -skip graphicaleffects -skip imageformats -skip websockets

我向 FlightGear 的 CMake 展示了在哪里可以找到这些库,一切都很好,直到最后的 linking 阶段:

Linking CXX executable fgfs
/usr/bin/ld: /home/user/Qt/5.4/Src/qtbuild/lib/libQt5Core.a(qlibrary_unix.o): undefined reference to symbol 'dlclose@@GLIBC_2.2.5'
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libdl.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

现在,我已经 运行 解决过这个问题,问题是没有通过 -ldl linking 动态 linker 库。但是,我已经确保 Qt 和 FlightGear 都是使用 -ldl 标志构建的,但我仍然收到此错误。

所以现在,这引出了我心中的问题:是否有可能从静态库中动态 link?我想 -ldl 必须包含在静态库中,这将是一个坏主意,这是正确的吗?

错误消息说您缺少 dlclose@@GLIBC_2.2.5,它是 glibc(GCC 使用的 GNU C 库)的一部分。此符号是 dl.so 的一部分,它映射到我系统上的 /lib/x86_64-linux-gnu/libdl.so.2

将其添加到构建时,请确保 -ldl 位于命令的末尾。链接器将在处理库时收集丢失的符号,但它只会处理每个库一次。所以你需要确保 -dl 在需要它的库之后。

is it even possible to dynamically link from a static library?

是的。静态库被添加到您的代码中,就像它是您自己的源代码的一部分一样,即库只是一堆编译对象 (*.o) 文件。函数名是查找目标文件的关键。您也可以解压库并写入:

gcc -o exe main.o qtfoo.o -ldl

其中 qtfoo.o 是来自 libQt5Core.a

的条目

另一种解决方案是使用动态加载构建 Qt 并将其安装到 $HOME/local/。构建设置应该允许指定安装文件夹。

构建 FlightGear 时,您可以将 $HOME/local/lib 作为共享库的附加文件夹传递。要启动FlightGear,您需要设置环境变量LD_LIBRARY_PATH。如果您在启动脚本中执行此操作,则只有 FlightGear 能够 see/use 您自己的 Qt 版本。