1

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

4

2 回答 2

0

我设法克服了这个问题,尽管没有完全理解它的细节。最初我在 mkspecs 文件中有这两行,虽然它们在构建 Qt 时没有导致任何错误,但将它们注释掉可以解决问题:

QMAKE_RANLIB    = i686-apple-darwin10-ranlib
QMAKE_STRIP     = i686-apple-darwin10-strip

我已将这些设置为像这样认为有必要的交叉编译器可执行文件,但似乎只需指定正确的 gcc 和 g++ 即可处理工具链中的所有内容。

于 2012-08-07T22:06:04.383 回答
0

我没有完整的答案,但我可以告诉你 nm 输出中的“U”表示该符号未在该可执行文件(或本例中的库)中定义,但应在外部定义链接库,表明该库实际上可能有问题。

作为旁注,您可以使用 nm 的 -C 参数来解开您的 C++ 符号。

于 2012-08-06T22:56:01.730 回答