在 Docker 的 ubuntu bionic 上,我得到了这个:
No such file or directory
#include <filesystem>
在执行此操作的 C++ 文件上:
#if __cplusplus >= 201703L
#include <filesystem>
#endif
尝试使用 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
我猜测 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}"
只需更改bionic
为focal
即可使编译工作。
答案1
每当 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 无法编译,是因为您仍在使用不包含标<filesystem>
头的系统旧 libstdc++。您必须安装包含较新 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
现在 clang 10 可以正确编译。
困难的解决方案:
使用此解决方案,代码将编译并支持较旧的 C++ 标准库。此解决方案的缺点是需要一个额外的编译标志,GNU libstdc++ 和 LLVM libc++ 之间有所不同。
如果您确实需要使用 9.1 之前的 GNU libstdc++ 和 9.0 之前的 LLVM libc++ 进行编译,则必须修改 OpenVPN3 中的代码。因为OpenVPN3是开源的,如果你更改他们的代码,你可以发送拉取请求,他们可能会接受你的贡献。
困难解决方案的第一部分-代码更改:
您需要修改 OpenVPN3 代码,以便它根据可用的标头在std::filesystem
和命名空间之间进行选择。std::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
现在您必须使用命名空间fs
namepsace 而不是std::filesystem
。
之前的代码:
std::filesystem::path file("document.txt");
之后的代码:
fs::path file("document.txt");
std::filesystem
请小心,因为和之间存在一些差异std::experimental::filesystem
。
困难解决方案的第二部分-编译标志:
对于使用 gcc 或 clang 的 9.1 之前的 GNU libstdc++,您需要将该标志用作-lstdc++fs
最后一个标志。顺序很重要。
g++ -std=c++17 your_code.cpp -lstdc++fs
或者
clang++ -std=c++17 your_code.cpp -lstdc++fs
要使用 CMake 执行上述操作,请在后面添加以下内容add_executable()
:
target_link_libraries(project_name_here stdc++fs)
对于使用 clang 的 9.0 之前的 LLVM libc++,您需要使用标志-lc++fs
作为最后一个标志。要使用 libc++,请不要忘记安装libc++-dev
和libc++abi-dev
。
clang++ -std=c++17 -stdlib=libc++ -lc++abi your_code.cpp -lstdc++fs
要使用 CMake 执行上述操作,请在后面添加以下内容add_executable()
:
target_link_libraries(project_name_here c++fs)