簡體   English   中英

使用 GCC linker 強制執行 32 位枚舉

[英]Enforce 32-bit enums with GCC linker

我正在為 ARM 設備(無操作系統)編寫裸機應用程序。 我需要 32 位枚舉,所以我使用-fno-short-enums編譯器標志編譯了應用程序。 沒有這個標志,我會得到變量枚舉(並且通過向每個枚舉添加額外的0xFFFFFFFF值來強制大小不是一個選項)。

現在,對於每個 object,我都會收到以下 linker 警告:

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 以確保所有對象都使用相同的枚舉大小,但我仍然收到警告。 我錯過了什么嗎?

我有一個部分答案,因為我有同樣的問題。 問題是來自鏈接器的警告消息,它將使用-fno-short-enums出現。 該消息表明目標對象不兼容。 所以我花了一段時間尋找現在改變目標以兼容。

但那不是問題。 gcc編譯器默認會構建32位枚舉! 因此,除非您不想要32位枚舉,否則此選項是沒有必要的。 但是,如果您指定-fno-short-enums,您將收到警告消息。 不幸的是我不知道為什么。

所以最重要的是,無需短枚舉標志就不需要實現32位枚舉。 如果您確實指定了它,那么您將收到警告消息。

過了一會兒,我開始工作了。 我重建了整個工具鏈,包括帶有此標志的編譯器。 這是我的方式:

  1. https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads獲取工具鏈源代碼

  2. 在buildscript build-toolchain.sh某些部分添加3行:

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

    修改部分:

    • 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/

    我跳過構建newlib-nanogcc-size-libstdcxx

  3. 運行修改后的Scripts build-prerequisites.shbuild-toolchain.sh來構建所有內容。


之后,編譯器正在使用large-enum-mode,並且鏈接器對我的對象很好。 但是現在,我得到了newlib的一些對象的對等警告( lib_a-mbtowc_r.olib_a-svfiprintf.olib_a-svfprintf.olib_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,遺憾的是它們被明確地設置為variable-size-enums。 對此唯一的“解決方案”是添加鏈接器標志以靜音此警告:

-Xlinker -no-enum-size-warning

而已。

我遇到了同樣的問題,因為我在數據結構中有很多枚舉 map 到硬件。 就我而言,我的解決方法是執行以下操作:

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

這有效並且在數據結構之外是透明的,盡管這意味着每次在數據結構中使用枚舉時都需要這個聯合包裝器。 我想宏也可能是可能的。 我同意這是一種痛苦。 我使用過的所有其他 32 位和 64 位環境都將枚舉視為 32 位,並且不要讓我開始決定在 ARM 嵌入式 ABI 中將 uint32_t 設為無符號長整數(我已經使用它是一個無符號整數,使 64 位 ABI 的可移植性變得容易)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM