Qt 交叉编译 Linux -> MacOS 无法链接到 Qt 库
Posted
技术标签:
【中文标题】Qt 交叉编译 Linux -> MacOS 无法链接到 Qt 库【英文标题】:Qt cross-compile Linux -> MacOS cannot link to Qt libs 【发布时间】:2012-08-06 22:46:03 【问题描述】:我正在尝试链接我为 Linux 主机上的 MacOS 目标交叉编译的 Qt 程序。我按照此处的说明 (https://github.com/Tatsh/xchain) 成功构建了 gcc,我可以编译和链接该页面上的两个简单测试程序,以生成在 MacOS 上运行良好的可执行文件。
我已经使用这个 gcc 从源代码构建了我自己的 Qt,我可以顺利编译我的 Qt 程序。问题出现在链接阶段,当我的程序的目标文件应该链接到 Qt 库时,似乎根本找不到 Qt 库,或者因为它们不兼容而被忽略。
我的程序的目标文件和我构建的 Qt 库似乎都可以:
$ file MainWindow.o
MainWindow.o: Mach-O object i386
$ file /usr/local/myqt/mac32/Qt-4.8.2/lib/libQtCore.dylib.4.8.2
/usr/local/myqt/mac32/Qt-4.8.2/lib/libQtCore.dylib.4.8.2: Mach-O dynamically linked shared library i386
g++ 调用如下:
$ i686-apple-darwin10-g++ -o myapp.app/Contents/MacOS/myapp
main.o MainWindow.o ...
-L/usr/local/myqt/mac32/Qt-4.8.2/lib -lQtCore -lQtGui ...
当然还有更多的目标文件和更多的 Qt 库,为简洁起见,我将它们省略了。
我得到的错误是典型的没有将对象或库添加到命令行,例如:
...
"QMainWindow::event(QEvent*)", referenced from:
vtable for MainWindowin moc_MainWindow.o
"QDir::~QDir()", referenced from:
_main in main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
而且似乎基本上没有找到每个 Qt 库。
我也尝试过直接指定 lib 文件而不是 -L/path 和 -lQtFoo 组合,我什至尝试将它们从 .dylib 重命名为 .so :)
如果我使用 -v 运行 g++ 来查看链接器调用,然后在其中添加 -v,我可以看到正在检查库的路径看起来没问题:
$ i686-apple-darwin10-ld64 -dynamic -arch i386 -headerpad_max_install_names
-macosx_version_min 10.4 -syslibroot /usr/i686-apple-darwin10
-weak_reference_mismatches non-weak -o myapp.app/Contents/MacOS/myapp
-lcrt1.o /usr/i686-apple-darwin10/SDKs/MacOSX10.6.sdk/usr/bin/../lib/gcc/i686-apple-darwin10/4.2.1/crt3.o
main.o MainWindow.o
...
-L/usr/local/myqt/mac32/Qt-4.8.2/lib -lQtCore -lQtGui ...
-v
@(#)PROGRAM:ld64 PROJECT:odcctools-622.3od16
Library search paths:
/usr/local/myqt/mac32/Qt-4.8.2/lib
/usr/i686-apple-darwin10/usr/X11/lib
/usr/local/myqt/mac32/Qt-4.8.2/lib
/usr/i686-apple-darwin10/usr/lib/i686-apple-darwin10/4.2.1
/usr/i686-apple-darwin10/usr/lib
/usr/i686-apple-darwin10/SDKs/MacOSX10.6.sdk/usr/lib/gcc/i686-apple-darwin10/4.2.1
/usr/i686-apple-darwin10/SDKs/MacOSX10.6.sdk/usr/lib/gcc
/usr/i686-apple-darwin10/usr/lib/gcc/i686-apple-darwin10/4.2.1
/usr/i686-apple-darwin10/SDKs/MacOSX10.6.sdk/usr/i686-apple-darwin10/lib
/usr/i686-apple-darwin10/SDKs/MacOSX10.6.sdk/usr/i686-apple-darwin10/lib
/usr/i686-apple-darwin10/usr/lib
/usr/local/lib
Framework search paths:
/usr/i686-apple-darwin10/Library/Frameworks/
/usr/i686-apple-darwin10/System/Library/Frameworks/
lib 位置和设置看起来没问题:
$ ls -lh /usr/local/myqt/mac32/Qt-4.8.2/lib/libQtCore.dylib*
lrwxrwxrwx. 1 root root 21 Aug 7 05:22 /usr/local/myqt/mac32/Qt-4.8.2/lib/libQtCore.dylib -> libQtCore.dylib.4.8.2
lrwxrwxrwx. 1 root root 21 Aug 7 05:22 /usr/local/myqt/mac32/Qt-4.8.2/lib/libQtCore.dylib.4 -> libQtCore.dylib.4.8.2
lrwxrwxrwx. 1 root root 21 Aug 7 05:22 /usr/local/myqt/mac32/Qt-4.8.2/lib/libQtCore.dylib.4.8 -> libQtCore.dylib.4.8.2
-rwxr-xr-x. 1 root root 2.7M Aug 7 05:22 /usr/local/myqt/mac32/Qt-4.8.2/lib/libQtCore.dylib.4.8.2
lib 的内容似乎还可以,但是我对这部分不太熟悉...实际上我刚刚在另一个问题上发现了“nm”。
$ i686-apple-darwin10-nm /usr/local/myqt/mac32/Qt-4.8.2/lib/libQtGui.dylib.4.8.2 | grep event
U __ZN16QCoreApplication5eventEP6QEvent
U __ZN16QEventTransition5eventEP6QEvent
U __ZN16QEventTransition9eventTestEP6QEvent
U __ZN17QVariantAnimation5eventEP6QEvent
U __ZN19QAbstractTransition5eventEP6QEvent
U __ZN23QCoreApplicationPrivate15eventDispatcherE
U __ZN7QObject11eventFilterEPS_P6QEvent
U __ZN7QObject5eventEP6QEvent
我也不太熟悉“名称修改”,但我觉得这可能与此有关。
到目前为止,整个交叉编译的过程已经很长了,所以在接近尾声的时候遇到了让我非常难过的东西,真是太糟糕了——任何建议都将不胜感激!
** 编辑 ***
我发现如果我为 ld64 调用去掉 -dynamic 标志,不同的函数名会显示为缺失。例如上面提到的对“QMainWindow::event(QEvent*)”的缺失引用变为:
"__ZN11QMainWindow5eventEP6QEvent", referenced from:
__ZTV10MainWindow in moc_MainWindow.o
现在我可以看到这些名称确实在我构建的 Qt 库中找不到(配置问题...?)。这并没有让我知道应该怎么做才能解决这个问题,但也许它可能会给其他人一些线索。
【问题讨论】:
【参考方案1】:我没有完整的答案,但我可以告诉你,nm 输出中的“U”表示该符号未在该可执行文件(或本例中的库)中定义,但预计会被定义在外部链接的库中,表明该库实际上可能有问题。
作为旁注,您可以使用 nm 的 -C 参数来解开您的 C++ 符号。
【讨论】:
【参考方案2】:我设法克服了这个问题,尽管没有完全理解它的细节。最初我在 mkspecs 文件中有这两行,虽然它们在构建 Qt 时没有导致任何错误,但将它们注释掉可以解决问题:
QMAKE_RANLIB = i686-apple-darwin10-ranlib
QMAKE_STRIP = i686-apple-darwin10-strip
我已将这些设置为像这样认为有必要的交叉编译器可执行文件,但似乎只需指定正确的 gcc 和 g++ 即可处理工具链中的所有内容。
【讨论】:
以上是关于Qt 交叉编译 Linux -> MacOS 无法链接到 Qt 库的主要内容,如果未能解决你的问题,请参考以下文章
从 Mac 为 Windows、Linux 交叉编译 C++/QT [关闭]
如何配置 Qt 以实现从 Linux 到 Windows 目标的交叉编译?