Search code examples
c++macosclang++llvm-clangundefined-symbol

std::to_chars compile but not linking on MacOS / clang


I have problem compiling a project under MacOS with clang.

I did "pinpoint" the problem inside charconv header:

#include <charconv>
#include <array>
#include <iostream>

int main(){
    std::array<char, 64> buffer;

    auto[p, ec] = std::to_chars(buffer.begin(), buffer.end(), 123);

    if (ec != std::errc() )
        std::cout << "error" << '\n';

    std::cout << (const char *) buffer.data() << '\n';
}

Here is how I am compiling it.

Nikolays-MacBook-Air:~ nmmm$ clang --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Nikolays-MacBook-Air:~ nmmm$ clang -std=c++17 x.cc -lstdc++
Undefined symbols for architecture x86_64:
  "std::__1::__itoa::__u32toa(unsigned int, char*)", referenced from:
      std::__1::__itoa::__traits_base<unsigned int, void>::__convert(unsigned int, char*) in x-9b1746.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Nikolays-MacBook-Air:~ nmmm$ 

Any help will be appreciated.

update

I tried clang++, but it gives me same error message.


Solution

  • The <charconv> header contains declarations and uses of std::__1::__itoa::__u32toa, a function which is not defined in that header. The function is defined in libc++.dylib. However, Apple does not ship libc++.dylib with the same frequency as it ships headers; and, possibly more important, libc++ failed to include the new symbol in its "abilist" for Apple until 2018-09-23, even though the header change landed on 2018-08-01. So there was a period of about 53 days where (this aspect of) libc++ just didn't work on OSX. Maybe Apple picked it up and shipped it during that period.

    One way to make your code work is to build libc++ yourself. Instructions here, as of late 2019.

    $ clang++ -std=c++17 test.cc $ROOT/llvm-project/build/lib/libc++.dylib \
        -Wl,-rpath,$ROOT/llvm-project/build/lib
    $ ./a.out
    123
    

    Some commenters on your question are suggesting that you could make your code work by using GNU libstdc++ instead of LLVM libc++. That's vaguely true, but I suspect that building libstdc++ for OSX will be even harder than building libc++ for OSX. (And the latter is not simple!) I am not aware of any way to install libstdc++ on OSX. There is brew install gcc@8, but I bet GCC 8 didn't have <charconv> either.

    As of early 2020, no vendor (except just recently Microsoft) provides a full implementation of <charconv> — the floating-point to_chars and from_chars turn out to be difficult, so most vendors don't provide them. ("Why didn't they just copy an existing implementation?" Well, it turns out that <charconv> was standardized as part of C++17 before any implementation existed. Nobody guessed that it would be difficult!)