Gcc 如何设置2字节wchar\t输出?

Gcc 如何设置2字节wchar\t输出?,gcc,ld,binutils,eabi,Gcc,Ld,Binutils,Eabi,默认情况下,GCC使用4字节的wchar\u t。我可以将选项-fshort wchar设置为在L“字符串常量”中为每个wchar\u t获取2个字节。但是,当我将编译器选项设置为源文件时,我得到了著名的警告消息 foo.o使用2字节wchar\u t,但输出使用4字节wchar\u t;跨对象使用wchar\u t值可能会失败 因为我真的需要2字节的wchar\u t,所以我还希望输出使用这个变量。有没有链接器选项可以告诉它我想要什么 编辑 此警告不会禁止链接器生成有效输出。但是几十个错误警告

默认情况下,GCC使用4字节的
wchar\u t
。我可以将选项
-fshort wchar
设置为在
L“字符串常量”
中为每个
wchar\u t
获取2个字节。但是,当我将编译器选项设置为源文件时,我得到了著名的警告消息

foo.o使用2字节
wchar\u t
,但输出使用4字节
wchar\u t
;跨对象使用
wchar\u t
值可能会失败

因为我真的需要2字节的
wchar\u t
,所以我还希望输出使用这个变量。有没有链接器选项可以告诉它我想要什么

编辑


此警告不会禁止链接器生成有效输出。但是几十个错误警告涵盖了其他信息。

这是一个警告,而不是错误。您可以忽略它,但如果您链接使用4字节
wchar\u t
编译的其他库,则会导致问题。如果必须使用2字节
wchar\u t
,则必须找到这些库的替换项或重新编译它们

您也可以尝试
-fwide exec charset=UTF-16

  • -fwide exec charset=charset
    • 设置宽执行字符集,用于宽字符串和字符常量。默认值为UTF-32或UTF-16,以与
      wchar\u t
      的宽度相对应的值为准。与
      -fexec字符集
      一样,字符集可以是系统iconv库例程支持的任何编码;但是,如果编码不完全符合
      wchar\t
      ,则会出现问题

如果您有C11支持,您只需使用(带有字符串文字的
u
前缀)并在必要时在binutils中转换为
wchar\t
,您可以在
bfd/elf32 arm.c
中找到此错误消息,如下所示:

“警告:%B使用了%u字节wchar\t但输出将使用%u字节 wchar\u t;跨对象使用wchar\u t值可能会失败”

但是,如果进一步查看binutils,您会发现输出的wchar\t大小在任何地方都没有初始化为4。那么,是什么决定了“输出wchar\t大小”?实际上,给
ld
的第一个对象初始化输出属性。下一个对象将其属性合并到其中。如果您链接到gcc/g++,它会在内部执行
ld
,因此请尝试
gcc-v
,看看
ld
是如何执行的。这将使您了解它隐式链接到可执行文件的内部对象文件(除了您自己的文件之外)

例如,与gcc链接(例如,
gcc-v-shared-o libfoobar.so foo.o bar.o
)会导致调用:

ld。。。crtbegin\u so.o foo.o bar.o crtend\u so.o…

i、 e.以下对象实际链接(按顺序):

  • crtbegin_so.o(隐式)
  • 富奥
  • 酒吧
  • crtend_so.o(隐式)
以下是ld的工作:

  • 输出属性集开始时为空
  • 合并crtbegin\u so.o属性。现在输出属性包含
    out\u attr[Tag\u ABI\u PCS\u wchar\u t]==4
  • 合并foo.o属性。如果foo.o是用
    -fshort wchar
    构建的,那么
    在\u attr[Tag\u ABI\u PCS\u wchar\t]==2
    中,这将导致冲突和您看到的警告
  • 如果在ld命令行上交换crtbegin_so.o和foo.o,则会收到以下警告:

    劳工处:警告: android-ndk-r9d/platforms/android-16/arch-arm/usr/lib/crtbegin_-so.o 使用4字节wchar\u t,但输出使用2字节wchar\u t;使用 跨对象的wchar\t值可能会失败

    正如您所看到的,这不是输入和输出不兼容的问题,而是链接在一起的两个对象文件之间(感知到)不兼容的问题

    我们能做些什么

    • ld
      支持
      --no-wchar size警告
      标志以抑制此警告。但正如你所说,不加区别地压制警告有其缺点

    • 可以使用-fshort-wchar重建工具链

    • 如果您真的相信内部gcc对象二进制文件中的
      标记(wchar\t)
      是不可知的,那么您可以从中去掉
      标记(wchar\t)
      。这可能比重建工具链更容易。为此,你可以用我曾经写过的。(您可能需要解压缩libgcc.a,更改其对象文件并重新打包。)


    不过,我没有写关于错误消息的文章。当你收到一打这样的信息时,你很难忽视它。我替换了wchar\t函数的实现。因此,“那些库”都没有链接。所以问题仍然是“如何输出”。如果您想禁用警告,请使用或我希望抑制wchar__t消息以查看其他可能更重要的警告。您可以有选择地禁用特定警告。请看我上面评论中的后一个链接。您的链接指向“许多选项都有以…开头的长名称”,但也有一个带有链接的答案,但该链接控制编译器诊断,而相关警告是由链接器发出的。+1用于重建工具链。我猜您也需要一个libc(+++)。AFAIK libstdc++是作为工具链(g++)的一部分构建的。