【问题标题】:Is it possible to link libstdc++ statically in Mac OSX 10.6?是否可以在 Mac OSX 10.6 中静态链接 libstdc++?
【发布时间】:2010-10-14 20:12:51
【问题描述】:

我正在尝试在其他 Mac OSX 机器上运行我的 C++ 程序,这些机器可能具有较旧的 libstdc++ 副本,但具有所有其他工具。我试图关注这个approach,在this 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++ source 文件(sstream.h、list.h、vector.c)等并仅包含他们在编译。尽管这会使编译变慢,但它可能对某些应用程序很有用。它甚至可能带来更好的优化!

【问题讨论】:

  • 为了回答我自己的问题,我们可以先用 g++ -c 编译它,然后用 ld 链接所需的库。我在这里看不到任何破坏规则,因为我们使用 g++ 编译器来编译 c++,然后链接库以提供所有功能。我不知道我们需要向 ld 提供哪些库。显然我们需要的不仅仅是 libstdc++,因为 ld 会因缺少符号而产生大量错误。

标签: c++ macos gcc static-linking libstdc++


【解决方案1】:

听起来您只想针对较早的 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。编译的 with flag 正确执行,但是编译 without flag 说“Bad CPU type in executable”(尽管它是在同一台机器上编译的只是运行更高版本的 OS X)。

如果您已将 10.4 指定为最低目标(我不确定 C++ 标头,但 Cocoa、Foundation、AppKit 等. 框架头文件肯定可以)。

【讨论】:

  • 我同意, mmacosx-version-min 标志应该编译成与早期版本兼容的东西。尽管我给出了一个简单的例子,但我实际上使用了一些早期 libstdc++ 中未包含的 tr1 功能(std::tr1::unordered_set 和映射所需的某些哈希函数)。所以我实际上需要链接到较新的 libstdc++。但是,如果我要静态链接它,代码会运行!因此,操作系统不提供某些功能不是问题。这些功能由 c++ 提供,它可以在早期版本上运行。如果有人问,我可以举一个这样的玩具例子。
【解决方案2】:

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

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

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

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

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

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

【讨论】:

  • Frantz:我同意,而且我在前面对 dreamlax 的回答的评论中提到了一些内容。我试图找到这样一个makefile来查看。 xcode 会生成这些 makefile 吗?
  • 我尝试了 [此处][1] 的说明来获取 Makefile,但没有成功。 [1]:richarddingwall.name/2007/04/08/…
猜你喜欢
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
相关资源
最近更新 更多