我正在尝试链接我为 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/
库位置和设置看起来不错:
$ 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 库中找不到(配置问题......?)。这并没有让我知道应该做些什么来解决这个问题,但也许它可能会给其他人一个线索。