GCC 相当于 MS 的 /bigobj

GCC equivalent of MS's /bigobj

本文关键字:bigobj MS 相当于 GCC      更新时间:2023-10-16

我们正在大量使用boost::serialization和模板。一切似乎都很顺利。

但是,我们的Windows版本遇到了一个障碍。这似乎会导致目标文件过大的问题。我们在g++ 4.7.0中使用MinGW/Msys。

c:/mingw/bin/../lib/gcc/mingw32/4.7.0/../../../../mingw32/bin/as.exe: CMakeFiles/source.dir/sourcecode.cpp.obj: too many sections (33396)
C:UsersusernameAppDataLocalTempccnAocvD.s: Assembler messages:
C:UsersusernameAppDataLocalTempccnAocvD.s: Fatal error: can't write CMakeFiles/source.dir/sourcecode.cpp.obj: File too big

Master google揭示了这个存档消息,http://sourceforge.net/mailarchive/forum.php?thread_name=CA%2Bsc5mkLvj%3DW9w2%3DsY%3Dc_N%3DEwnsQuPDEX%3DiBcbsbxS3CuE_5Bg%40mail.gmail.com&forum_name=mingw-users

在其中,它表示另一个人遇到了几乎相同的障碍。它确实指出了Visual Studio的/bigobj选项的一个选项,它似乎可以做我们需要的事情。但是,我们无法迁移到Visual Studio。

一个建议是在汇编器选项中添加——hash-size。

如果我没弄错的话,问题在于目标文件中有2^16个条目的限制。实际上,根据错误信息,我敢说它是一个有符号的2^16项,但这是微不足道的。Visual Studio的/bigobj选项会将其更改为2^32。邮件列表结果不知道GCC的等效选项。进一步的谷歌搜索结果似乎与此无关。

在这一点上,我们将不得不重构我们的代码来绕过这个限制。但是我仍然担心,使用沉重的模板,我们可能会一次又一次地遇到这个问题(我们已经在三个源文件中遇到过这个问题)。

我的问题是这样的;是否有一个GCC等同于微软的/bigobj选项?有没有我还没找到的第三种选择?

解决方案是添加-Wa,-mbig-obj选项,如果您的GCC版本支持该选项。您可能只在编译步骤中需要它,而不是在链接器步骤中。

如果你的编译器不支持这个选项,你应该考虑使用mingw-w64和MSYS2。

错误"%B: too many sections (%d)"来自位于bfd/coffcode.h中的函数coff_compute_section_file_positions()。当输出的.obj文件(COFF格式)包含超过32766个节时,就会产生它。没有办法避免这个错误,至少如果你想使用Windows的PE/COFF对象格式;COFF文件只使用两个字节用于文件头中的"NumberOfSections"。

我不清楚为什么as (GNU汇编器)将节数上限为32768- -2,而不是65536- -1(节0保留);但无论哪种方式,如果你大量使用模板,编译器通过COMDAT部分实现模板,这可能还不够。

正如您已经注意到的,将/bigobj传递给Microsoft的编译器会导致它输出最多231节的修改后的COFF格式,这"对任何人来说都应该足够了"。然而,修改后的格式是没有正式文档的,我没有看到任何关于这个主题的非正式文档(博客文章或其他),所以直到有人有MSVC的副本可以为/bigobj编写规范,它不会有太大的机会进入GNU工具。

恕我直言,如果你想做一个Windows版本,你应该咬紧牙关使用MSVC。除了微软,没有人会特别愿意浪费时间在PE/COFF格式上。

我在使用MinGW-w64编译Poco库时遇到了同样的问题,结果发现调试对象对于一个实现文件来说太大了。

正如你之前提到的,你可以拆分cpp文件,它会工作,但是当你面对别人的源代码时,你不能在不破坏某些东西的情况下这样做。

作为一种解决方案,你可以打开编译器优化:从-O1到-O3开始,每一步它将构建更小的目标文件,它可能解决问题,它在我的情况下。是的,对于调试版本,它可能是不可取的,您也可以尝试-Og

我在这个问题上发现了一些更新,它似乎在x64 windows的新binutils中得到了修复,请参阅https://sourceware.org/ml/binutils/2014-03/msg00114.html和http://sourceforge.net/p/mingw-w64/bugs/341/。但是,我没有测试它,因为这个修复不适用于我需要的32位版本。

正如一些人已经指出的那样,如果在Fatal error: can't close xxx.obj: file too big之后引发错误,那么-Wa,-mbig-obj将无法工作。

一个解决方法是通过添加-Os(根据此链接最小的代码大小,但另一个-O选项也可能工作)来重新编译有问题的行(做make VERBOSE=1来找到它)。

总结:

C:/msys64/mingw64/bin/c++.exe [...] -Wa,-mbig-obj -c D:/Dev/a_installer/llvm-project/llvm/lib/Passes/PassBuilder.cpp # -> file too big error
C:/msys64/mingw64/bin/c++.exe -Os [...] -Wa,-mbig-obj -c D:/Dev/a_installer/llvm-project/llvm/lib/Passes/PassBuilder.cpp # -> compilation ok

或者你可以在CMake中为所有文件全局设置标志,如果你不确信优化不会改变代码的行为。