C++:“错误:预期为”或“...”编译 gcc 时,在“fancy_abort (__FILE__, __LINE__, __FUNCTION__)”中的“__FILE__”之前

C++: `error: expected ',' or '...' before string constant` before `__FILE__` in `fancy_abort (__FILE__, __LINE__, __FUNCTION__)` when compiling gcc

提问人:Gabriel Staples 提问时间:11/7/2023 最后编辑:Gabriel Staples 更新时间:11/8/2023 访问量:143

问:

这是尝试从源代码编译 Microchip XC32 微控制器 g++ XC32 v4.35 交叉编译器的免许可 GPL 版本的延续。

在这里查看我的问答,在这里查看我的回购:https://github.com/ElectricRCAircraftGuy/Microchip_XC32_Compiler

请注意,这在 Linux Ubuntu 22.04 上完美地构建完成。gcc --versiongcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

但是,在 MSYS2 UCRT64 环境中的 Windows 上编译时(按照我的说明进行设置) ,我现在收到以下错误:gcc --versiongcc.exe (Rev2, Built by MSYS2 project) 13.2.0gcc/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

这是我正在使用的 system.h 文件,位于第 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__)

例如,在 fibonacci_heap.h 第 460 行的 C++ 模板类中调用此定义:abort()

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;
}

如何解决此构建错误?

而且,为什么它发生在 Windows 上,而不是在 Linux 上?


其他研究:

  1. 有用的 Google 搜索:msys gcc abort fancy_abort错误:字符串常量之前的预期标识符

  2. 可能的错误:https://sourceforge.net/p/mingw-w64/bugs/974/

  3. 可能的修复: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
    

    评论从日文到英文的翻译:

    #
    # 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.
    

    上面的代码只是在 中找到 ,并将其注释为 ,从而将其删除。#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)gcc/system.h/* #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) */

    只是注释掉这个令人反感的宏定义似乎真的很骇人听闻。我不完全理解这种变化的影响。

C++ GCC MINGW-W64 MSYS2

评论

2赞 Tim Roberts 11/7/2023
好吧,标准库包括一个终止程序的函数。宏唯一要做的就是提供一条错误消息,说明它发生的位置。删除宏允许库函数改为运行。这是一个安全的改变。abort()
1赞 Tim Roberts 11/7/2023
是的。这显然是一个 MINGW 问题,而 MINGW 正在编译的是交叉编译器。
1赞 Tim Roberts 11/7/2023
是的,它非常元。我认为在这一点上我们不知道您正在编译的交叉编译器是否有同样的问题。我怀疑它没有。因此,只是您的交叉编译器在遇到内部错误时会产生不太有用的消息,而您不太可能遇到。
1赞 n. m. could be an AI 11/7/2023
不,PIC32 mcu 交叉编译器有一个错误,它有 ,而不是 gcc。它是任何标准名称的 UB。#define abort()#define
1赞 n. m. could be an AI 11/7/2023
是的,这是正确的做法。未定义的行为是未定义的,它可以在这里按预期工作,但不能在那里工作,今天但明天不能。我不知道 MSYS2 gcc 是否存在问题,这也会阻止合法情况(不涉及保留名称,例如 )工作。abort

答:

2赞 Gabriel Staples 11/7/2023 #1

非常感谢 @Tim Roberts 和“@n. m. could be an AI”在问题下的帮助和评论,促成了这个答案。

溶液:

注释掉 system.h 中的 abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) #define 以使 gcc 编译。

简单地注释掉定义,就像这里所做的那样,正如我的问题底部所记录的那样,是有效的。abort()

Windows 中的 MSYS2 中似乎存在一个错误,阻止构建与它定义的构建一起工作,因此只需打开,在第 737 行找到它xc32-v4.35-src/pic32m-source/gcc/gcc/system.h

#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)

...并像这样注释它:

/* #define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) */

现在,当我运行时,构建完成,MSYS2 UCRT64 gcc 工具链能够构建 PIC32 mcu gcc 交叉编译器完成!time Microchip_XC32_Compiler/build-xc32-v4.35m.sh

这个黑客安全吗?

是的,我们是这么认为的。

这里有 3 层:我在 Windows(第 1 层)上使用 MSYS2 UCRT GCC 编译器来编译 Microchip XC32 PIC32 gcc 微控制器交叉编译器(第 2 层),它将交叉编译 PIC32 微控制器(第 3 层)的程序(在本问答中在 Windows 上,尽管我也在 Linux Ubuntu 上构建了它)。

根据在我的问题下与 @Tim Roberts 的讨论(例如,此评论和其他评论),我们认为此更改是相当良性的,并且应该只影响第 2 层 XC32 交叉编译器(这是本问答中正在编译的内容),如果它在运行和编译第 3 层目标时崩溃,则会生成不太有用的运行时错误消息(缺少内容)。所以,没什么大不了的。第 3 层(目标 MCU)不受影响。如果第 2 层崩溃,它只会有不太有用的错误消息。但是,这不太可能。我不记得 gcc 编译器曾经在我身上崩溃过。当然,它在编译时产生了大量的编译错误,但我不记得曾经见过它产生运行时崩溃并输出自己的内部错误。这就是我们正在谈论的。这就是我的更改影响的部分。__FILE__, __LINE__, __FUNCTION__

其他修复

SourceForge 上的 Tony Yu 在这里也有一个看起来不错的替代修复程序

基本上,就像我所做的那样,只需注释掉 ,然后也将所有对 in 的调用替换为 代替。这里的挑战是替换所有正确的呼叫,不仅在这里,而且在他们可能呼叫的任何地方。所以。。。这似乎很难。我认为只是把它注释掉就可以了。👍#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)system.habort()gcc/gcc.cfancy_abort (__FILE__, __LINE__, __FUNCTION__)abort()fancy_abort()

错误报告

我打开了这个错误报告。欢迎发表评论: https://github.com/msys2/MSYS2-packages/issues/4142

更新:更好的修复

将此修补程序应用于一堆 gcc 文件:https://gcc.gnu.org/pipermail/gcc-patches/2023-January/609514.html。此链接来自对我上面错误报告的回复。

基本上,在调用 #include < windows.h> 之前,应始终 #define WIN32_LEAN_AND_MEAN。显然,这是正确的解决方法。

原因:从这里开始:https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=902c755930326cb4405672aa3ea13c35c653cbff(强调后加):

始终在之前定义WIN32_LEAN_AND_MEAN<windows.h>

最近,mingw-w64 已从 Wine 中更新,其中包括 间接由 if 未定义。该类有一个名为 的成员函数,它得到 受“system.h”中的宏影响。<msxml.h><windows.h>WIN32_LEAN_AND_MEANIXMLDOMDocumentabort()abort()

WIN32_LEAN_AND_MEAN然而,应该始终被定义。这 可以排除“API”,例如加密、DDE、RPC、Shell 和 Windows 套接字的 [1],并稍微加快了这些文件的编译速度。

因此,我计划手动执行修复,生成基于补丁的文件,提交补丁文件,然后作为构建脚本过程的一部分通过(请参阅此处的答案)制作补丁。git diffgit apply