使用GCC链接器强制使用32位枚举

9

我正在为ARM设备编写裸机应用程序(没有操作系统)。 我需要32位枚举,因此我使用-fno-short-enums编译器标志编译应用程序。 如果没有这个标志,我会得到变量枚举(通过为每个枚举添加额外的0xFFFFFFFF值来强制设置大小不是选项)。

现在我对每个对象都得到以下链接器警告:

c:/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/bin/ld.exe: warning: ./src/test.o uses 32-bit enums yet the output is to use variable-size enums; use of enum values across objects may fail

这只是一个警告,没有错误。但它确切地意味着什么?我该如何指定“输出”?

我尝试使用上述标志重新编译newlib,以确保所有对象使用相同的枚举大小,但我仍然收到警告。我错过了什么吗?


为什么需要32位的枚举? - user933161
也许你应该给链接器添加一些标志,并为所有对象使用短枚举。 - user933161
我需要它以便与其他平台/处理器上的软件部件兼容。我绝对需要32位枚举。 - Schlumpf
什么样的兼容性?网络? - user933161
顺便问一下,你有没有使用其他库?展示完整的构建日志 :) - user933161
3个回答

3

过了一段时间我终于搞定了。 我重新构建了整个工具链,包括编译器,并加上了这个标志。下面是我的操作步骤:

  1. Get the toolchain source from https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads

  2. Add 3 lines to some sections of the buildscript build-toolchain.sh:

    saveenv
    saveenvvar CFLAGS_FOR_TARGET '-fno-short-enums'
      [...build commands...]
    restoreenv
    

    Modified sections:

    • Task [III-1] /$HOST_NATIVE/gcc-first/
    • Task [III-2] /$HOST_NATIVE/newlib/
    • Task [III-4] /$HOST_NATIVE/gcc-final/
    • Task [IV-3] /$HOST_MINGW/gcc-final/

    I Skipped building newlib-nano and gcc-size-libstdcxx.

  3. Run the modified Scripts build-prerequisites.sh and build-toolchain.sh to build everything.


在此之后,编译器使用了大型枚举模式,链接器也能正常处理我的对象。但现在,我对一些newlib的对象(lib_a-mbtowc_r.o, lib_a-svfiprintf.o, lib_a-svfprintf.o, lib_a-vfprintf.olib_a-vfiprintf.o)得到了相反的警告:

c:/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/bin/ld.exe: warning: c:/gcc-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib\libc.a(lib_a-mbtowc_r.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail

我查看了这些对象的makefile,它们都明确设置为可变大小枚举,但不幸的是。唯一的“解决方案”是添加链接器标志以消除此警告:

-Xlinker -no-enum-size-warning

这就是全部。


应该是 -Xlinker(小写的 l)。 arm-none-eabi-g++: 错误:无法识别命令行选项“-XLinker”;您是否指的是“-Xlinker”? - Tejas Kale
在gcc中,替代语法为-Wl,-no-enum-size-warning - Sergey

0

我遇到了同样的问题,因为我的数据结构中有很多映射到硬件的枚举。在我的情况下,我的解决方法是执行以下操作:

struct x {
  union {
      enum my_enum eval;
      uint32_t :32;
  };
  uint32_t some_val;
  ...
}

这个方法在数据结构外部是透明的,但这意味着每次在数据结构中使用枚举时都需要使用这个联合包装器。我想宏也可能是一个选择。我同意这很麻烦。我曾经使用过的其他32位和64位环境都将枚举视为32位,而且不要让我开始谈论将uint32_t作为ARM嵌入式ABI中的unsigned long的决定(我使用过的其他ABI都是unsigned int,使得与64位ABI的可移植性变得容易)。


-1

我有一个部分答案,因为我曾经有同样的问题。这个问题是链接器的警告信息,当使用-fno-short-enums时会出现。该消息指示目标对象不兼容。所以我花了很多时间寻找如何改变目标以使其兼容。

但那不是问题所在。gcc编译器默认会构建32位枚举!因此,除非您不想要32位枚举,否则此选项是不必要的。但是,如果您确实指定了-fno-short-enums,则会收到警告消息。不幸的是,我不知道为什么。

因此,底线是,no-short-enums标志不是实现32位枚举所必需的。如果您确实指定它,则会收到警告消息。


2
不,对于ARM架构,gcc默认使用最小的枚举大小来存储值。请查看gcc文档中的“4.9结构体、联合体、枚举和位域”章节。 - calandoa
@calandoa 是的,但如果需要32位枚举(基于值),那么枚举将是32位的。这就是重点。该标志强制所有枚举都具有相同的X大小,而不是让它们具有必要的任何大小。只有在出于某种原因需要固定大小时才需要这样做。 - Kurt E. Clothier
1
这个回答的意思是“gcc编译器默认会构建32位的枚举!”。针对问题指定的目标,这种说法是错误的。因此,答案是错误的。我不明白为什么你在别处看到了一个观点。 - calandoa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接