How to set 2 byte wchar_t output?
Asked Answered
U

2

7

The GCC uses a 4-byte wchar_t by default. I can set the option -fshort-wchar to get 2 bytes per wchar_t in the L"string constants". But when I set the compiler option to my source file I get the famous warning message

foo.o uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail

Since I really want 2-byte wchar_t I also want the output to use this variant. Is there any linker option to tell it what I want?

Edit

This warning doesn't inhibit the linker to produce a valid output. But the dozens of false warnings cover other messages.

Undry answered 21/10, 2013 at 8:18 Comment(0)
C
18

In binutils you can find this error message in bfd/elf32-arm.c as:

"warning: %B uses %u-byte wchar_t yet the output is to use %u-byte wchar_t; use of wchar_t values across objects may fail"

However, if you look further at binutils, you'd realize that the output's wchar_t size is not initialized to 4 anywhere. So what determines the "output wchar_t size"? Actually, the first object given to ld initializes the output attributes. The next objects merge their attributes into it. If you link with gcc/g++, it executes ld internally, so try gcc -v and see how ld is executed. This will give you insight into what internal object files (in addition to your own) it implicitly links into your executable.

For example, linking with gcc (e.g. gcc -v -shared -o libfoobar.so foo.o bar.o) results in invocation of:

ld ... crtbegin_so.o foo.o bar.o crtend_so.o ...

i.e. the following objects are actually linked (in order):

  • crtbegin_so.o (implicitly)
  • foo.o
  • bar.o
  • crtend_so.o (implicitly)

Here's what ld does:

  1. The output attributes set starts off empty.
  2. Merging crtbegin_so.o attributes. Now output attributes contain out_attr[Tag_ABI_PCS_wchar_t] == 4
  3. Merging foo.o attributes. If foo.o was built with -fshort-wchar, then in_attr[Tag_ABI_PCS_wchar_t] == 2 and this will result in a conflict and the warning you're seeing.

If you were to swap crtbegin_so.o and foo.o on the ld command line, you'd get the following warning instead:

ld: warning: android-ndk-r9d/platforms/android-16/arch-arm/usr/lib/crtbegin_so.o uses 4-byte wchar_t yet the output is to use 2-byte wchar_t; use of wchar_t values across objects may fail

As you can see, it's not a matter of incompatibility of the input with the output, but rather (perceived) incompatibility between two object files linked together.

What can we do about it?

  • As of 2008, ld supports the --no-wchar-size-warning flag to suppress this warning. But as you said, indiscriminately suppressing warnings has its drawbacks.

  • You can rebuild your toolchain with -fshort-wchar.

  • You can strip the Tag_ABI_PCS_wchar_t tags from your internal gcc object binaries if you truly believe they're sizeof(wchar_t)-agnostic. This might be easier than rebuilding your toolchain. For that, you can use this utility I once wrote. (You might need to unpack libgcc.a, change its object files and repack it.)

Caplan answered 27/5, 2014 at 18:49 Comment(2)
+1 for rebuilding the toolchain. I'd guess you'd need a libc(++) as well.Papain
AFAIK libstdc++ is built (only) as part of the toolchain (g++).Caplan
F
1

That's a warning, not error. You can ignore it but that will cause problems if you link against others libraries that were compiled with 4-byte wchar_t. If you must use 2-byte wchar_t then you'll have to find a replacement for those libraries or recompile them

You may also try -fwide-exec-charset=UTF-16

  • -fwide-exec-charset=charset
    • Set the wide execution character set, used for wide string and character constants. The default is UTF-32 or UTF-16, whichever corresponds to the width of wchar_t. As with -fexec-charset, charset can be any encoding supported by the system's iconv library routine; however, you will have problems with encodings that do not fit exactly in wchar_t.

If you have C11 support you can just use char16_t (with the u prefix for string literals) and convert to wchar_t when necessary

Fireproofing answered 21/10, 2013 at 8:30 Comment(5)
I didn't write about an error message though. It's hard to ignore, when you get a dozen of such messages. Well I replaced the wchar_t function implementation. So none of "those libraries" are linked. So the question is still "How to the the output".Undry
If you want to disable the warning just use -w or #1080497Fireproofing
Well I would like having the wchar_t message suppressed to see the other, probably more important warnings.Undry
you can selectively disable a specific warning. Look at the latter link on my comment aboveFireproofing
Your link points to "Many options have long names starting with ..." but there is also an answer with a link to gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/… But this controls compiler diagnostics while the warning in question is issued by the linker.Undry

© 2022 - 2024 — McMap. All rights reserved.