从静态库中动态链接?

时间:2015-04-30 10:58:10

标签: linux static-libraries ld

我目前正在尝试在我的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 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链接动态链接库。但是,我确保Qt和FlightGear都使用-ldl标志构建,但我仍然遇到此错误。

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

1 个答案:

答案 0 :(得分:2)

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

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

  

是否可以从静态库动态链接?

是。静态库被添加到您的代码中,就好像它是您自己的源代码的一部分,即库只是一堆编译对象(*.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能够查看/使用您自己的Qt版本。