是否可以在Mac OSX 10.6中静态链接libstdc ++?

时间:2010-10-14 20:12:52

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

我正在尝试在其他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 ++ 文件(sstream.h,list.h,vector.c)等,只包括他们在汇编中。即使这会使编译变慢,但它对某些应用程序可能很有用。它甚至可能导致更好的优化!

2 个答案:

答案 0 :(得分: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中引入的函数/类。框架标题绝对可以。)

答案 1 :(得分:1)

据我所知,这是一个延伸,但我在这里看到的答案很少!

GCC是一个编译器驱动程序,也会驱动链接器。 g ++对我的理解更多的只是一个编译器。因此,要使G ++正确构建,我相信您需要构建目标文件并手动链接它们。在我的头脑中,我不能说如何做到这一点,因为我此刻IDE脑部受损。

至于您所看到的错误可能是由于链接的文件错误。我现在正在我的iPhone上,所以我不打算删除您打印的错误消息。我不是所有MacPorts的粉丝,所以不要惊讶于那个装置搞砸了。首先,请确保您使用MacPorts编译器的MacPorts库。

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

当然,找到一个好的基于C ++的项目来学习并不容易。但我建议安装LLVM&amp; CLang特别考虑到新的转速假设是C ++就绪。显然,一组不同的工具,但CLang可能会解决您的问题或至少为您提供更好的调试信息。也许有人可以使用一个带有简单干净的make文件的开源C ++项目。我最近看到的最近的是一个名为HeeksCAD的项目。

最终,当构建任何不平凡的东西时,你最终需要的不仅仅是GCC。现在很多都是用IDE来处理的,但是我不确定XCode是否可以正确配置来做你想做的事情。