如何在 Ubuntu 18(仿生)上使用 C++17/文件系统头文件获取 libstdc++?

Luc*_*lla 3 compiling c++ make docker 18.04

在 Docker 的 ubuntu 仿生上,我得到了这个:

No such file or directory
 #include <filesystem>
Run Code Online (Sandbox Code Playgroud)

在执行此操作的 C++ 文件上:

#if __cplusplus >= 201703L
#include <filesystem>
#endif
Run Code Online (Sandbox Code Playgroud)

尝试使用 clang 6.0 进行编译时。不幸的是,我无法移动,experimental/filesystem因为它不是我的图书馆,它来自 OpenVPN3。我尝试了 clang 10,但仍然出现错误。

Ubuntu 20.04(专注于 docker)工作!但是我想使用更旧的版本来与旧系统兼容。

这是编译给出错误的文件时 cmake/make 产生的输出:

cd /workspaces/libopenvpnclient/build/src && /usr/local/clang/bin/clang++  -DASIO_STANDALONE

 -DHAVE_LZ4 -DLZ4_DISABLE_DEPRECATE_WARNINGS -DMBEDTLS_DEPRECATED_REMOVED -DUSE_ASIO 

-DUSE_OPENSSL -I/workspaces/libopenvpnclient/src/../openvpn3 -I/workspaces/libopenvpnclient

/src/../libtins/include -I/workspaces/libopenvpnclient/src/../asio/asio/include -I/workspaces

/libopenvpnclient/src/../literal_ipaddr -I/workspaces/libopenvpnclient/openvpn3/cmake/..

 -I/workspaces/libopenvpnclient/openvpn3/cmake/../../deps/asio/asio/include  -Wall -Wsign-

compare -Wno-missing-field-initializers -std=c++1z -o CMakeFiles/libopenvpn_example.dir

/OpenVPNClient.cpp.o -c /workspaces/libopenvpnclient/src/OpenVPNClient.cpp
Run Code Online (Sandbox Code Playgroud)

我猜 Ubuntu 18 上的 libstdc++ 有问题?

Dockerfile:

FROM ubuntu:bionic

RUN export DEBIAN_FRONTEND=noninteractive && apt-get update \
&& apt-get install -y clang-6.0 lldb iptables iproute2 cmake \
build-essential libmbedtls-dev libssl-dev liblz4-dev curl git \
xz-utils wget libncurses5

RUN curl --proto '=https' --tlsv1.2 -o rust.sh https://sh.rustup.rs\
    && /bin/bash rust.sh -y


RUN wget -O clang.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz \
&& mkdir clang && tar xf clang.tar.xz -C clang --strip-components 1 \
&& mv clang /usr/local/clang

WORKDIR /home/project

ENV PATH="/root/.cargo/bin:${PATH}"
ENV PATH="/usr/local/cmake/bin:${PATH}"
Run Code Online (Sandbox Code Playgroud)

只需更改bionicfocal使编译工作。

小智 5

每当 C++ 编译错误说<filesystem>找不到头文件时,这是因为 9.1 之前的 GNU libstdc++ 和 9.0 之前的 LLVM libc++ 尚未实现std::filesystem

简单的解决方案:

使用此解决方案,代码可以编译,但不支持旧的 C++ 标准库。

您可以做的最简单的事情是更新到更新的 C++ 标准库。C++ 标准库的版本是 Ubuntu 20.04 Focal Fossa 工作但 Ubuntu 18.04 Bionic Beaver 不工作的原因。

至于 Ubuntu 18.04 上的 clang 10 未编译是因为您仍在使用系统的旧版 libstdc++,它不包含<filesystem>标头。您必须安装包含更新的 libstdc++ 的 g++ 9,以便您可以使用 clang 10 进行编译。

在 Ubuntu 18.04 上执行以下操作:

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install gcc-9 g++-9
Run Code Online (Sandbox Code Playgroud)

现在 clang 10 将正确编译。

困难的解决方案:

使用此解决方案,代码将被编译并支持旧的 C++ 标准库。这个解决方案的缺点是需要一个额外的编译标志,这在 GNU libstdc++ 和 LLVM libc++ 之间是不同的。

如果您绝对需要使用 9.1 之前的 GNU libstdc++ 和 9.0 之前的 LLVM libc++ 进行编译,则必须修改 OpenVPN3 中的代码。由于OpenVPN3是开源的,如果您更改他们的代码,您可以发送拉取请求,他们可能会接受您的贡献。

困难解决方案的第一部分 - 代码更改:

您需要修改 OpenVPN3 代码,以便它根据可用的标头在std::filesystemstd::experimental::filesystem命名空间之间进行选择。

#if __has_include(<filesystem>)
  #include <filesystem>
  namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
  #include <experimental/filesystem> 
  namespace fs = std::experimental::filesystem;
#else
  error "Missing the <filesystem> header."
#endif
Run Code Online (Sandbox Code Playgroud)

现在您必须使用命名空间命名空间fs而不是std::filesystem.

之前的代码:

std::filesystem::path file("document.txt");
Run Code Online (Sandbox Code Playgroud)

之后的代码:

fs::path file("document.txt");
Run Code Online (Sandbox Code Playgroud)

请注意,因为std::filesystem和之间存在一些差异std::experimental::filesystem

困难解决方案的第二部分 - 编译标志:

对于带有 gcc 或 clang 的 9.1 之前的 GNU libstdc++,您需要使用该标志-lstdc++fs作为最后一个标志。顺序很重要。

g++ -std=c++17 your_code.cpp -lstdc++fs
Run Code Online (Sandbox Code Playgroud)

或者

clang++ -std=c++17 your_code.cpp -lstdc++fs
Run Code Online (Sandbox Code Playgroud)

要使用 CMake 执行上述操作,请在之后添加以下内容add_executable()

target_link_libraries(project_name_here stdc++fs)
Run Code Online (Sandbox Code Playgroud)

对于带有 clang 的 9.0 之前的 LLVM libc++,您需要使用该标志-lc++fs作为最后一个标志。要使用 libc++,不要忘记安装libc++-devlibc++abi-dev.

clang++ -std=c++17 -stdlib=libc++ -lc++abi your_code.cpp -lstdc++fs
Run Code Online (Sandbox Code Playgroud)

要使用 CMake 执行上述操作,请在之后添加以下内容add_executable()

target_link_libraries(project_name_here c++fs)
Run Code Online (Sandbox Code Playgroud)