4

我正在尝试在其他 Mac OSX 机器上运行我的 C++ 程序,这些机器可能具有较旧的 libstdc++ 副本,但具有所有其他工具。我尝试遵循这种方法,在这个 SO question中也提到过,即使它讨论了 linux 设置。我有小程序try.cpp:

#include <iostream>

int main() {
        int a = 10;
        std::cout << a << '\n';
        return 1;
}

显然,如果我只是编译它,我会得到

$ /usr/bin/g++ try.cpp 
$ otool -L a.out 
a.out:
 /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

我理解对 libSystem.B.dylib 的依赖,我们可以把它放在一边。为了尝试摆脱 libstdc++,我试试这个:

$ /usr/bin/g++ try.cpp /usr/lib/libstdc++-static.a 
$ otool -L a.out 
a.out:
 /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

所以,我尝试

$ ln /usr/lib/libstdc++-static.a .
$ /usr/bin/g++ try.cpp -L.
$ otool -L a.out 
a.out:
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

或者,

$ /usr/bin/g++ try.cpp -L. -lstdc++-static
$ otool -L a.out 
a.out:
 /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

最后,这有效:

$ /usr/bin/gcc try.cpp -L. -lstdc++-static
$ otool -L a.out 
a.out:
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

这可以吗?(使用 gcc 将 C++ 程序与 libstdc++ 链接)。我在某处听说 g++ 实际上是一个使用 gcc 和 libstdc++ 编译 C++ 程序的脚本。如果是这样,并且我们正确使用它,应该没问题。

但是,我实际上使用的是 macport 编译器和一个更复杂的程序,gcc 会为此生成一些警告,但它与 C++ 兼容。大意是:

ld: warning: std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf() has different visibility (hidden) in /opt/local/lib/gcc44/libstdc++.a(sstream-inst.o) and (default) in /var/folders/2u/2uLPtE+3HMi-BQIEfFVbSE+++TU/-Tmp-//ccoE2rqh.o

这表明我们不应该将 gcc 用于 c++ 编译。所以总结起来,问题是:

  • 如何静态链接 libstdc++
  • 如果 g++ 不这样做,可以使用 gcc 并手动提供 libstdc++ 吗?那么为什么会出现能见度警告呢?
  • 如果由于编译库中的可见性问题,这两种方法都不起作用,那么为什么不使用 libstdc++文件(sstream.h、list.h、vector.c)等并将它们包含在编译中。尽管这会使编译变慢,但它可能对某些应用程序很有用。它甚至可能导致更好的优化!
4

2 回答 2

3

听起来您只想针对较早的 Mac OS X 版本,而无需静态链接libstdc++. 我认为 Xcode 附带的 GCC 默认以主机环境为目标。但是,它可以处理调用-mmacosx-version-min来更改目标环境的特殊标志。如果您提供了目标 OS X 版本号,那么它将自动创建与该版本的 Mac OS X 兼容的二进制文件。

#include <iostream>

int main(void)
{
    std::cout << "Hello world!" << std::endl;
    return 0;
}

像这样编译:

g++ -mmacosx-version-min=10.4 test.cpp

我编译了这个程序两次,一次带有标志,一次没有,然后我将两个二进制文件复制到运行 10.4 的 Mac 上。使用该标志编译的那个正确执行,但是没有该标志编译的那个说“可执行文件中的 CPU 类型错误”(尽管它是在运行更高版本的 OS X 的同一台机器上编译的)。

如果您已将 10.4 指定为最低目标(我不确定 C++ 标头,但 Cocoa、Foundation、AppKit 等框架标头,则某些标头具有宏保护,可防止您使用 10.5 或 10.6 中引入的函数/类)肯定会)。

于 2010-10-14T21:06:18.710 回答
0

这对我的知识来说是一个延伸,但我在这里看到的回应很少!

GCC 是一个编译器驱动程序,它也将驱动链接器。我理解的 g++ 更像是一个编译器。因此,要让 G++ 正确构建,我相信您需要构建目标文件并手动链接它们。在我的头顶上,我不能说如何做到这一点,因为我现在是 IDE 大脑受损。

至于您看到的错误,可能是由于链接了错误的文件。我现在在我的 iPhone 上,所以我不打算解密您打印的错误消息。我完全不是 MacPorts 的粉丝,所以请不要惊讶,安装被搞砸了。首先,请确保您将 MacPorts 库与 MacPorts 编译器一起使用。

最后我毫不怀疑你可以做你想做的事。但是,您需要开始阅读 Make 文件和更多 GCC 工具集的文档。专注于构建文件并将其链接到程序中。您可能想找到一个可以在 Mac 上很好构建的小型开源程序,并查看那里的 Make 文件。

当然,要找到一个好的基于 C++ 的项目来学习并不容易。但是,我建议安装 LLVM 和 CLang,特别是考虑到新的 rev 应该是 C++ 准备好的。显然是一组不同的工具,但 CLang 可以解决您的问题,或者至少为您提供更好的调试信息。也许有人可以用简单干净的 make 文件加入一个开源 C++ 项目。我最近看到的最接近的是一个名为 HeeksCAD 的项目。

最后,当构建任何不平凡的东西时,您最终需要的不仅仅是 GCC。如今,IDE 可以解决很多问题,但是我不确定 XCode 是否可以正确配置为您想要的。

于 2010-10-15T03:24:35.927 回答