问题
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-bytewchar_t
; use ofwchar_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.
回答1:
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:
- The output attributes set starts off empty.
- Merging crtbegin_so.o attributes. Now output attributes contain
out_attr[Tag_ABI_PCS_wchar_t] == 4
- Merging foo.o attributes. If foo.o was built with
-fshort-wchar
, thenin_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'resizeof(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.)
回答2:
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 inwchar_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
来源:https://stackoverflow.com/questions/19489354/how-to-set-2-byte-wchar-t-output