Issue
This is a continuation of trying to compile a license-free GPL version of the Microchip XC32 microcontroller g++ XC32 v4.35 cross-compiler from source.
See href="https://stackoverflow.com/q/77414776/4561887">my Q&A here, and my repo here: https://github.com/ElectricRCAircraftGuy/Microchip_XC32_Compiler.
Note that this builds perfectly to completion on Linux Ubuntu 22.04 with gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
.
However, when compiling on Windows in the MSYS2 UCRT64 environment (set up per my instructions here) with gcc --version
gcc.exe (Rev2, Built by MSYS2 project) 13.2.0
, I now get the following error in gcc/gcc/system.h
:
./../../pic32m-source/gcc/gcc/prefix.c
../../../pic32m-source/gcc/gcc/system.h:737:30: error: expected identifier before string constant
737 | #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
| ^~~~~~~~
../../../pic32m-source/gcc/gcc/system.h:737:30: error: expected ',' or '...' before string constant
../../../pic32m-source/gcc/gcc/system.h:737:30: error: expected identifier before string constant
737 | #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
| ^~~~~~~~
../../../pic32m-source/gcc/gcc/system.h:737:30: error: expected ',' or '...' before string constant
make[1]: *** [Makefile:1112: prefix.o] Error 1
make[1]: Leaving directory '/c/Users/gabriel/GS/dev/Microchip_XC32_Compiler/xc32-v4.35-src/pic32m-build/gcc/gcc'
make: *** [Makefile:4290: all-gcc] Error 2
Here is the system.h
file I am using, at line 737:
/* Redefine abort to report an internal error w/o coredump, and
reporting the location of the error in the source file. */
extern void fancy_abort (const char *, int, const char *)
ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
This definition of abort()
is getting called, for instance, inside a C++ template class in fibonacci_heap.h
line 460, here:
template<class K, class V>
V*
fibonacci_heap<K,V>::delete_node (fibonacci_node<K,V> *node, bool release)
{
V *ret = node->m_data;
/* To perform delete, we just make it the min key, and extract. */
replace_key (node, m_global_min_key);
if (node != m_min)
{
fprintf (stderr, "Can't force minimum on fibheap.\n");
abort (); // <=========== HERE ===========
}
extract_min (release);
return ret;
}
How do I resolve this build error?
And, why is it occurring on Windows, but not on Linux?
Additional research:
Useful Google search: msys gcc abort fancy_abort error: expected identifier before string constant
Possible bug: https://sourceforge.net/p/mingw-w64/bugs/974/
Possible fix: https://github.com/yosshin4004/xdev68k/blob/main/build_m68k-toolchain.sh#L199-L210
# # 新しい mingw 環境では以下のようなエラーとなる。 # ../../../src/gcc-10.2.0/gcc/system.h:743:30: error: expected identifier before string constant # 743 | #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) # 応急処置として、問題を起こす行を除去する。 # abort() は stdlib.h 内で宣言された実装のままの挙動となる。 # if [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then cat ${SRC_DIR}/${GCC_DIR}/gcc/system.h |\ perl -e 'my $before="#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)";my $after="/* $before */";$before=quotemeta($before);while(<>){$_=~s/$before/$after/g;print $_;}' > ${SRC_DIR}/${GCC_DIR}/gcc/system.h.tmp; mv ${SRC_DIR}/${GCC_DIR}/gcc/system.h.tmp ${SRC_DIR}/${GCC_DIR}/gcc/system.h fi
Translation of the comments from Japanese to English:
# # In the new mingw environment, the following error will occur. # ../../../src/gcc-10.2.0/gcc/system.h:743:30: error: expected identifier before string constant # 743 | #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) # As a workaround, remove the offending line. # abort() behaves as the implementation declared in stdlib.h.
The code above simply finds
#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
ingcc/system.h
, and comments it out as/* #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) */
, thereby removing it.Just commenting out this offending macro define seems really hacky. I don't fully understand the repercussions of this change.
Solution
Big thanks to @Tim Roberts and "@n. m. could be an AI" for their help and comments under the question which contributed to this answer.
Solution:
Comment out #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
in system.h
to make gcc compile.
Simply commenting out the abort()
define, as done here and as documented at the bottom of my question, worked.
There seems to be a bug in MSYS2 in Windows stopping the build from working with it defined, so simply open up xc32-v4.35-src/pic32m-source/gcc/gcc/system.h
, find this on line 737:
#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
...and comment it out like this:
/* #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) */
The build now goes to completion when I run time Microchip_XC32_Compiler/build-xc32-v4.35m.sh
, and the MSYS2 UCRT64 gcc toolchain is able to build the PIC32 mcu gcc cross-compiler to completion!
Is this hack safe?
Yes, we think so.
There are 3 layers here: I'm using the MSYS2 UCRT GCC compiler on Windows (layer 1) to compile the Microchip XC32 PIC32 gcc microcontroller cross-compiler (layer 2), which will cross-compile programs (on Windows in this Q&A, though I have it built on Linux Ubuntu too) for PIC32 microcontrollers (layer 3).
Per the discussion with @Tim Roberts under my question (for example, this comment, and others), we think this change is pretty benign and should only affect the layer 2 XC32 cross-compiler (which is what is being compiled in this Q&A), by making it produce less-useful runtime error messages (missing the __FILE__, __LINE__, __FUNCTION__
content) if it crashes while running and compiling for a layer 3 target. So, not a big deal. Layer 3 (the target mcu) remains unaffected. Layer 2 will just have less-useful error messages if it crashes. But, that's unlikely. I can't recall the gcc compiler ever crashing on me. It has produced tons of compilation errors while compiling, of course, but I can't recall having seen it ever produce a run-time crash and output its own internal error. This is what we are talking about. That's the part my change has affected.
Other fixes
Tony Yu on SourceForge has what looks like a good alternative fix too, here.
Basically, just comment out #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
in system.h
, like I did, but then also replace all calls to abort()
in gcc/gcc.c
with fancy_abort (__FILE__, __LINE__, __FUNCTION__)
instead. The challenge here is replacing all of the correct abort()
calls, not just here, but anywhere they may be calling fancy_abort()
. So...that seems hard. I think just commenting it out is fine instead. 👍
Bug reports
I opened this bug report. Feel free to leave a comment: https://github.com/msys2/MSYS2-packages/issues/4142
Update: better fix
Apply this patch to a bunch of gcc files: https://gcc.gnu.org/pipermail/gcc-patches/2023-January/609514.html. This link comes from a reply to my bug report above.
Basically, you should always #define WIN32_LEAN_AND_MEAN
before calling #include <windows.h>
. This, apparently, is the proper fix.
Reason: from here: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=902c755930326cb4405672aa3ea13c35c653cbff (emphasis added):
Always define
WIN32_LEAN_AND_MEAN
before<windows.h>
Recently, mingw-w64 has got updated
<msxml.h>
from Wine which is included indirectly by<windows.h>
ifWIN32_LEAN_AND_MEAN
is not defined. TheIXMLDOMDocument
class has a member function namedabort()
, which gets affected by ourabort()
macro in "system.h".
WIN32_LEAN_AND_MEAN
should, nevertheless, always be defined. This can exclude 'APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets' [1], and speed up compilation of these files a bit.
So, I plan to manually do the fix, produce a git diff
-based patch file, commit the patch file, and then make the patch via git apply
(see my answer here) as part of the build script process.
Answered By - Gabriel Staples Answer Checked By - Marilyn (WPSolving Volunteer)