GCC equivalent of MS's /bigobj
Asked Answered
F

5

48

We are making heavy use of boost::serialization and templates in general. All seems to be going well.

Except, we've hit a snag on our Windows builds. It seems to cause issues in the object files being too large. We're using MinGW/Msys with g++ 4.7.0.

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

Master google revealed this archived message, http://sourceforge.net/mailarchive/forum.php?thread_name=CA%2Bsc5mkLvj%3DW9w2%3DsY%3Dc_N%3DEwnsQuPDEX%3DiBcbsbxS3CuE_5Bg%40mail.gmail.com&forum_name=mingw-users

In it, it indicates that another person hit pretty much the same snag. It did point to an option for Visual Studio's /bigobj option which appears to do what we would need. However, we're unable to move to Visual Studio.

One suggestion was to add --hash-size to the assembler options. This did not help.

If I'm not mistaken, the issue lies in the fact that the object files have a limit of 2^16 entries in them. Actually, according to the error message, I would venture that it's a signed 2^16 entries, but that's peanuts. The /bigobj option for Visual Studio would change that to 2^32. The mailing list result did not know of an equivalent option for GCC. Further google results don't appear to be relevant to this.

At this point we'll have to refactor our code (ugh) to get around this limitation. But I am still concerned that, with heavy templating, we could run into the issue again and again (we've already run into it with three source files).

So my question is thus; is there a GCC equivalent to Microsoft's /bigobj option? Is there a third option that I'm not yet found?

Found answered 16/5, 2013 at 20:28 Comment(6)
Personally, I would love to. I'd have to learn the format of the object files that's currently being used. I'd have to come up with a new format. Sounds like a great personal project. Unfortunately, my employer doesn't want that kind of responsibility. :)Found
Another possibility is that the object file broke a 2 GB barrier or somesuch. How certain are you that it is the number of exported symbols? Some googling indicates that gcc doesn't have a hard barrier at 2^16... Did you look at mingw-w64.sourceforge.net ?Earthman
@Yakk, clever use of ProcessMonitor while g++ is running the assembler reveals that the intermediary assembler file (ccnAocvD.s in the error message) is around 60MiB in size. It then goes to create the object file (assumably to ensure it can open it). A few seconds later, it exits and the error message shows up on the console. I assume the few seconds is the amount of time it takes to process the assembly file and determine that there would be too many symbols. The 2GiB barrier was mentioned in the mailing list. I wanted to be sure that wasn't the culprit.Found
@inetkght If you look here, we have someone testing gcc to see if it has a hard limit on that value: gcc.gnu.org/ml/gcc-patches/2007-05/msg02104.html -- but that was back in '07. You might consider figuring out how to run these tests with the current compiler, which might isolate which limit is the problem.Earthman
That looks like it might be fun to go through. Thanks!Found
See also svn.boost.org/trac/boost/ticket/8786 apparently there are macros that can help reduce the size or some odd...Catricecatrina
D
55

The solution is to add the option -Wa,-mbig-obj if your version of GCC supports that option. You probably only need it during the compilation step, not the linker step.

If your compiler does not support that option, you should look into using mingw-w64 and MSYS2.

Denounce answered 9/8, 2015 at 19:12 Comment(3)
I'm going to accept this answer. I have long since moved on to a different project, different team, different employer and I haven't encountered this problem since which is why I haven't accepted it prior to now. However I've noticed that a lot of people come and upvote it so it's apparently still an active issue even six years later.Found
didn't help me with MinGW64 from MSYS2 (file too big)Demijohn
I think -mbig-obj only fixes the "too many sections" error. If you don't see that error, but you do see a "File too big" error, by guess is that the file you want to make is too big for your filesystem, but I haven't looked into this very much. I'd check what filesystem you are using (e.g. NTFS, FAT32), and what its limits are.Denounce
W
10

The error "%B: too many sections (%d)" comes from the function coff_compute_section_file_positions() located in bfd/coffcode.h. It's produced when the output .obj file (in COFF format) contains more than 32766 sections. There is no way to avoid this error, at least not if you want to use Windows' PE/COFF object format; COFF files use only two bytes for "NumberOfSections" in the file header.

It's not clear to me why as (the GNU assembler) caps the number of sections at 32768-minus-2, instead of 65536-minus-1 (section 0 is reserved); but either way, that might not be enough if you're making heavy use of templates and your compiler implements templates via COMDAT sections.

As you've already noticed, passing /bigobj to Microsoft's compiler causes it to output a munged COFF format with up to 231 sections, which "should be enough for anybody." However, the munged format is formally undocumented, and I don't see any informal documentation (blog posts or what-have-you) on the subject, so until someone with a copy of MSVC can write up a specification for /bigobj, it doesn't stand much chance of getting into the GNU tools.

IMHO, if you're trying to make a Windows build, you should just bite the bullet and use MSVC. Nobody besides Microsoft is particularly motivated to waste time wrestling with the PE/COFF format.

Woodard answered 13/10, 2013 at 4:49 Comment(1)
Good info here! Indeed, we make heavy use of templates. I'm not sure what COMDAT sections are, but we use gcc on mingw32. I agree we should use MSVC but unfortunately management does not. They're subscribers to the idea of "one code repository, one compiler, multiple platforms". So the question of a viable solution still exists. As-is, our workaround has been to split up our CPP files into multiple files to present separate compilation units. But that's less than ideal, as I'm sure you can imagine.Found
B
5

I faced the same problem when I compiled Poco library with MinGW-w64, it turned out that debug object was huge for one implementation file.

As you mentioned before you can split up cpp files and it will work, but when you face with someone's source code you can't do that without breaking something.

As a solution you can turn on compiler optimisations: start with -O1 up to -O3, with each step it will build smaller object file, it may solve the problem, it did in my case. Yes, for debug builds it may be undesirable, you can try -Og as well

Bitterweed answered 28/1, 2014 at 19:30 Comment(0)
M
4

I found some updates in this matter, it seems to be fixed in new binutils for x64 windows, see https://sourceware.org/ml/binutils/2014-03/msg00114.html and http://sourceforge.net/p/mingw-w64/bugs/341/. However, I did not test it as this fix does not apply to 32 bit versions I need.

Mythology answered 6/2, 2015 at 18:45 Comment(3)
Thanks for hte update. I wasn't using mingw64, only mingw (eg, 32-bit) because I also had to compile for 32-bit so wanted to ensure no 64-bit stuff even accidentally was compiled.Found
@inetknght: The MinGW-w64 project provides 32-bit and 64-bit compilers. The project is named like this because the original MinGW project only provided 32-bit compilers, and the goal of MinGW-w64 was to produce 64-bit compilers.Ernieernst
I've tested this new option with MinGW-w64 and it works. You need to pass -Wa,-mbig-obj to gcc to opt-in to big objects (-Wa means pass this option to the assembler).Ernieernst
A
0

As some people already pointed, if the error is raised after Fatal error: can't close xxx.obj: file too big, then -Wa,-mbig-obj will not work.

A workaround is to recompile the problematic line (do a make VERBOSE=1 to find it) by adding -Os (minimal code size according to this link, but another -O option might also work).

In summary :

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

Or you can set the flag globally in CMake for all files if you are not confident that optimization will not alter the behavior of the code.

Arellano answered 12/3, 2021 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.