Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linking error. Undefined std::__2::__itoa::__u64toa(unsigned long long, char*) when compiling to WebAssembly #71

Closed
suy opened this issue Nov 26, 2020 · 9 comments
Assignees
Labels
bug Something isn't working

Comments

@suy
Copy link

suy commented Nov 26, 2020

Environment

toml++ version and/or commit hash: v2.2.0

Compiler: em++ 1.39.8

C++ standard mode (e.g. 17, 20, 'latest'): Tried with c++17 and -std=c++2a

Target arch (e.g. x64): WebAssembly

Tried with:

  • TOML_UNRELEASED_FEATURES 1 in a test case which is one of the examples copied verbatim.
  • TOML_EXCEPTIONS 0 in the application in which I actually wanted to use TOML.

Relevant compilation flags: None that I know of

Describe the bug

I get a linking error when compiling an application to WebAssembly:

error: undefined symbol: _ZNSt3__26__itoa8__u32toaEjPc
warning: Link with `-s LLD_REPORT_UNDEFINED` to get more information on undefined symbols
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
error: undefined symbol: _ZNSt3__26__itoa8__u64toaEyPc

The symbol, according to c++filt is std::__2::__itoa::__u64toa(unsigned long long, char*).

Steps to reproduce (or a small repro code sample)

I've followed the instructions here: https://emscripten.org/docs/getting_started/downloads.html

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

This will get the WebAssembly compiler downloaded and in the PATH variable for easy access. I'm not a fan of this kind of installation methods, but this seems clean and safe enough. It should not leave files scattered outside the place where you cloned the repository.

Then I made a test case using the simple_parser.cpp file from tomlplusplus' examples directory, and copied the utf8_console.h file as well. I made a build using qmake, because that's what I'm familiar with (and what I'm using for the actual application where I wanted tomlplusplus), but the compiler invocation is simple enough to copy paste and reproduce the issue.

em++ -c -pipe -O2 -std=gnu++2a -s ALLOW_MEMORY_GROWTH=1 -Wall -Wextra -I. -o main.o simple_parser.cpp
em++ -s WASM=1 -s FULL_ES2=1 -s FULL_ES3=1 -s USE_WEBGL2=1 -s EXIT_RUNTIME=1 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16"] --bind -s FETCH=1 -O2 -s ALLOW_MEMORY_GROWTH=1 -o toml-wasm-test-case.js main.o

Additional information

First things first: thanks for this library!

I know that WebAssembly is fairly new. I personally don't have much experience with it. But from what I see, there is no reason why most library code like TOML++ should not work out of the box on WebAssembly. The compiler (if I understood correctly) is a sort of LLVM/Clang branch, so if it works in one, it should work on the other. For my application I needed to do minimal changes to account for the use of threads or files.

Since the missing symbol is in the standard library, it might be an issue in emsdk itself, so feel free to point me there if you are confident that this is the problem. But I would be very grateful if you could point me where in TOML++ this symbol might be used directly or indirectly, as I'm quite lost in the code. :) I suppose it comes from some stream that tries to convert an unsigned long long to text. But I tried making a simpler test case fail, and I can't (it links well in that case).

Thank you again!

@suy suy added the bug Something isn't working label Nov 26, 2020
@marzer
Copy link
Owner

marzer commented Nov 26, 2020

Oooh, linker issues, everybody's favourite!

itoa() isn't called directly anywhere, but you're right in that it's probably used by the implementation internally when the formatter converts ints to text (or in the parser's error message generation code, maybe).

One thing you can try is setting TOML_INT_CHARCONV to 0 before including toml++; it's an undocumented override that controls whether the library uses anything from <charconv>.

@marzer
Copy link
Owner

marzer commented Nov 26, 2020

Here's a list of the places where the library does int-to-string conversions:

That's it as far as I can tell. I won't be able to attempt a repro for a few days at least, but if you want to try digging as bit deeper, that's where I'd start.

Thanks for the bug report!

@suy
Copy link
Author

suy commented Nov 26, 2020

One thing you can try is setting TOML_INT_CHARCONV to 0 before including toml++; it's an undocumented override that controls whether the library uses anything from .

Excellent, that did the trick! At a glance, seems that just disables a simpler code path inside TOML++, right?

I will try to make a shorter test case with your hints, but I also will need some days to be able to try it out.

Thank you very much, I can now work on TOML and WebAssembly support for my project at the same time. :-) <3

@marzer
Copy link
Owner

marzer commented Nov 26, 2020

Excellent, that did the trick!

Awesome, good to hear.

At a glance, seems that just disables a simpler code path inside TOML++, right?

Yup. Functionality should be identical, just that charconv is ' better'.

I will try to make a shorter test case with your hints, but I also will need some days to be able to try it out.

That probably isn't necessary; since charconv was to blame I can just switch it off for your environment. All I need is a way to uniquely identify that environment (a preprocessor macro set by the compiler, or similar).

@marzer
Copy link
Owner

marzer commented Nov 26, 2020

@suy You said that em++ is based on LLVM/Clang, would you be able to tell me what the value of __clang__ is?

@suy
Copy link
Author

suy commented Nov 26, 2020

__clang__ seems to be just 1, but __clang_version__ is 11.0.0. I've not been able to copy&paste easily (nor print to the console), so here is a screenshot of slapping those values into UI controls.
image

@marzer
Copy link
Owner

marzer commented Nov 26, 2020

Oh, awesome, that'll do nicely. The lowest version of clang I'm able to test on is 6.0, so I can just disable all charconv on lower versions, which should cover clang-based custom compilers.

Wait, never mind, I just realised that I actually needed __clang_major__, which in your case would be 11. The plot thickens. I'll do some digging and come up with something.

@marzer marzer closed this as completed in d95ff4c Nov 26, 2020
@marzer
Copy link
Owner

marzer commented Nov 26, 2020

Turns out the compiler defines __EMSCRIPTEN__, so I've added a check for that to disable the use of <charconv> automatically. Thanks for reporting this @suy!

@suy
Copy link
Author

suy commented Nov 26, 2020

Thanks to you for the quick fix! And again, thanks for the library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants