【问题标题】:std::to_chars compile but not linking on MacOS / clangstd::to_chars 在 MacOS / clang 上编译但不链接
【发布时间】:2020-03-14 08:34:45
【问题描述】:

我在 MacOS 下使用 clang 编译项目时遇到问题。

我确实“查明”了charconv 标头中的问题:

#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';
}

这是我的编译方式。

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$ 

任何帮助将不胜感激。

更新

我试过 clang++,但它给了我同样的错误信息。

【问题讨论】:

    标签: c++ macos clang++ llvm-clang undefined-symbol


    【解决方案1】:

    &lt;charconv&gt; 标头包含 std::__1::__itoa::__u32toa 的声明和使用,该函数未在该标头中定义。该函数在libc++.dylib 中定义。 但是,Apple 发送 libc++.dylib 的频率与发送标头的频率不同;而且,可能更重要的是libc++ failed to include the new symbol in its "abilist" for Apple until 2018-09-23,即使the header change landed on 2018-08-01。因此,在大约 53 天的时间里,libc++ 的(这方面)在 OSX 上不起作用。也许苹果在那段时间捡到了它并发货了。

    让您的代码工作的一种方法是自己构建 libc++。 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
    

    您的问题的一些评论者建议您可以通过使用 GNU libstdc++ 而不是 LLVM libc++ 来使您的代码工作。这有点模糊,但我怀疑为 OSX 构建 libstdc++ 会比为 OSX 构建 libc++ 更难。 (而后者并不简单!)我不知道在 OSX 上安装 libstdc++ 的任何方法。有 brew install gcc@8,但我敢打赌 GCC 8 也没有 &lt;charconv&gt;

    截至 2020 年初,没有供应商 (except just recently Microsoft) 提供了 &lt;charconv&gt; 的完整实现——浮点 to_charsfrom_chars 变得很困难,所以大多数供应商不提供它们。 (“他们为什么不直接复制现有的实现?”嗯,事实证明 &lt;charconv&gt; 在任何实现存在之前就已被标准化为 C++17 的一部分。没人猜到这会很困难! em>)

    【讨论】:

    • 您知道 Apple 何时会为库提供仅针对整数的正确实现吗?我的意思是我们什么时候可以期待它?
    • 我在使用 clang-7 时遇到了同样的问题,升级到 clang-8 解决了。
    【解决方案2】:

    我为此写了一个很好的长答案,然后检查它是否适合我(linux 上的 clang 9.0.0)。您使用clang 而不是clang++ 进行编译。下面的长答案:

    Clang 的 libc++ 很长时间没有完全实现“基本字符串转换,修订版 5”(如 to_charsfrom_chars),并且有些部分仍然未完成,请参阅 here。但我认为你的应该可以工作,所以也许你应该更新你的图书馆。

    对于to_chars 的用法,请考虑它在字符串末尾显式添加no \0。因此,您不能只使用std::cout &lt;&lt; (const char *) buffer.data();。您必须使用指针(在您的代码中命名为 p)来标记字符串的结尾。通过插入\0、生成std::string_view sv(buffer.data(), static_cast&lt;size_t&gt;(p-buffer.data());、使用std::copy(buffer.begin(), p, std::ostream_iterator&lt;char&gt;(std::cout, "")); 或其他太多方式。

    【讨论】:

    • 我知道 \0,但示例适用于 gcc。在 MacOS 上更新库的任何简单方法?
    • 您没有阅读我的回答:您使用了错误的编译器。输入clang++ 而不是clang
    • clang++ 的输出完全相同。
    • 我不使用苹果系统,它也只是谷歌搜索让我知道该怎么做。如果它在那里工作,是否有理由不使用 g++?为什么要指定标准库而不使用默认库?
    • clang++ -std=c++17 x.cc -lstdc++ 这不是在 unix、linux 和 macos 上编译 c++17 的正确方法吗?没有-lstdc++ iostream 将无法工作。
    猜你喜欢
    • 2018-08-09
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2018-05-12
    • 2019-06-06
    • 1970-01-01
    相关资源
    最近更新 更多