How to set 2 byte wchar_t output?

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