是否可以链接 libstdc++在 Mac OSX 10.6 中静态?
我正在尝试在其他 Mac OSX 计算机上运行我的 C++ 程序,这些计算机可能具有较旧的 libstdc++ 副本,但具有所有其他工具。我尝试遵循这个方法,也在这个SO问题,即使它讨论了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)等并将它们包含在汇编。尽管这会使编译速度变慢,但它对于某些应用程序可能很有用。它甚至可能带来更好的优化!
I am trying to run my C++ program on other Mac OSX machines which may have an older copy of libstdc++, but have all the other tools. I tried to follow this approach, also mentioned in this SO question, even though it discusses a linux setup. I have small program try.cpp:
#include <iostream>
int main() {
int a = 10;
std::cout << a << '\n';
return 1;
}
Obviously, if I just compile it, I get
$ /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)
I understand the dependency on libSystem.B.dylib, and we can leave that aside. To try to get rid of libstdc++, I try this:
$ /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)
So, I try
$ 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)
or,
$ /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)
Finally, this works:
$ /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)
Is this alright? (To use gcc to link C++ programs with libstdc++). I've heard somewhere that g++ is actually a script that uses gcc and libstdc++ to compile C++ programs. If that is the case, and we use it correctly, it should be ok.
However, I am actually using the macport compiler and a more complicated program, for which gcc generates some warnings, while it is C++ compliant. Something to the effect of:
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
This suggests that we shouldnt be using gcc for c++ compilations. So to sum up, the questions are:
- How to link libstdc++ statically
- If g++ doesn't do it, is it ok to use gcc and supply the libstdc++ manually? Then why the visibility warnings?
- If neither of the two approaches work because of the visibility problems in the compiled libraries, why not use libstdc++ source files (sstream.h, list.h, vector.c) etc and just include them in the compilation. Even though this will make the compilation slow, it might be useful for certain applications. It might even lead to better optimization!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
听起来您只想定位早期的 Mac OS X 版本,这可以在不与
libstdc++
静态链接的情况下完成。我认为 Xcode 附带的 GCC 默认针对主机环境。但是,它可以处理名为-mmacosx-version-min
的特殊标志来更改目标环境。如果您提供目标 OS X 版本号,那么它将自动创建与该版本的 Mac OS X 兼容的二进制文件。像这样编译:
我编译了这个程序两次,一次带标志,一次不带标志,然后我复制了两个二进制文件到运行 10.4 的 Mac。编译时使用该标志的编译器正确执行,然而编译时不使用该标志的编译器显示“可执行文件中的 CPU 类型错误”(尽管事实上它是在同一台机器上编译的)只是运行更高版本的 OS X)。
一些标头具有宏保护,如果您已指定 10.4 作为最低目标,它们会阻止您使用 10.5 或 10.6 中引入的函数/类(我不确定 C++ 标头,但 Cocoa、Foundation、AppKit 等框架标头肯定会)。
It sounds like you just want to target earlier Mac OS X versions, which can be done without statically linking with
libstdc++
. I think the GCC that ships with Xcode targets the host environment by default. However, it can handle a special flag called-mmacosx-version-min
to change the target environment. If you provide this with the target OS X version number then it will automatically create binaries compatible with that version of Mac OS X.Compile like this:
I compiled this program twice, once with the flag and once without, and then I copied both binaries to a Mac running 10.4. The one compiled with the flag executed properly, however the one compiled without the flag said “Bad CPU type in executable” (despite the fact that it was compiled on an identical machine just running a later version of OS X).
Some of the headers have macro guards that prevent you from using functions/classes introduced in 10.5 or 10.6 if you have specified 10.4 as a minimum target (I'm not sure about C++ headers, but the Cocoa, Foundation, AppKit etc. framework headers definitely do).
这是我知识的延伸,但我在这里看到的回复很少,所以!
GCC 是一个编译器驱动程序,也将驱动链接器。根据我的理解,g++ 更多的是一个编译器。因此,为了让 G++ 正确构建,我相信您需要构建目标文件并手动链接它们。我无法说出该怎么做,因为我现在 IDE 大脑受损了。
至于您所看到的错误,可能是由于链接了错误的文件所致。我现在正在使用 iPhone,所以我不打算解密您打印的错误消息。我根本不是 MacPorts 的粉丝,所以如果安装搞砸了,请不要感到惊讶。首先,请确保您将 MacPorts 库与 MacPorts 编译器一起使用。
最后,我毫不怀疑你可以做你想做的事。然而,您需要开始阅读 Make 文件和更多 GCC 工具集的文档。专注于构建文件并将其链接到程序中。您可能想找到一个可以在 Mac 上很好地构建的小型开源程序,并查看那里的 Make 文件。
当然,找到一个好的基于 C++ 的项目来学习并不容易。不过,我建议安装 LLVM &特别是考虑到新版本的 CLang 应该已经为 C++ 做好了准备。显然是一组不同的工具,但 CLang 可以解决您的问题,或者至少为您提供更好的调试信息。也许有人可以用简单干净的 make 文件参与开源 C++ 项目。我最近看到的最接近的是一个名为 HeeksCAD 的项目。
最后,当构建任何重要的东西时,您最终需要的不仅仅是 GCC。现在很多事情都是用 IDE 来处理的,但是我不确定 XCode 是否可以正确配置来完成你想要的事情。
This is a stretch for my knowledge but I see few responses here so!
GCC is a compiler driver that will also drive the linker. g++ to my understanding is more of just a compiler. So to get G++ to build properly I believe you need to build the object files and link them manually. Of the top of my head I can't say how to do this as I'm IDE brain damaged at the moment.
As to the error you have seen that might be due to the wrong files being linked in. I'm on my iPhone right now so I'm not about to dechiper the error message you printed. I'm not a fan at all of MacPorts so don't be surprised that, that installation is screwed up. First though make sure you are using the MacPorts libs with the MacPorts compiler.
In the end I have no doubt that you can do what you want to do. You will need to however start reading Make files and more of the documentation of the GCC tool set. Focus on building and linking files into programs. You might want to find a small open source program tha builds nicely on a mac and look at the Make files there.
Of course finding a good C++ based project to learn from is not easy. I would however reccomend installing LLVM & CLang especially considering the new rev is suppose to be C++ ready. Obviously a different set of tools but CLang may resolve your issues or at least give you better debugging info. Maybe somebody can chime in with an opensource C++ project with simple clean make files. The closest I've seen lately is a project called HeeksCAD.
In the end when building anything non trivial you end up needing more than just GCC. A lot of that is taken care of with IDEs these days, however I'm not certain if XCode can be properly configured to do what you want.