В ubuntu bionic из Docker я получаю следующее:
No such file or directory
#include <filesystem>
в файле C ++, который делает следующее:
#if __cplusplus >= 201703L
#include <filesystem>
#endif
при попытке компиляции с помощью clang 6.0. К сожалению, я не могу перейти в экспериментальную / файловую систему
, потому что это не моя библиотека, а из OpenVPN3. Я попробовал с clang 10, но все равно получил ошибку.
Ubuntu 20.04 (фокус на докере) работает! Однако я хотел использовать более старую версию, чтобы обеспечить совместимость со старыми системами.
Это результат, который 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
Я полагаю, что-то не так с libstdc ++ в Ubuntu 18?
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
] to focal
делает компиляцию работоспособной.
Всякий раз, когда ошибка компиляции C++ сообщает, что заголовок
не найден, это происходит потому, что GNU libstdc++ до версии 9.1 и LLVM libc++ до версии 9.0 не реализовали std::filesystem
пока что.
С этим решением код будет компилироваться, но не будет поддерживать старые стандартные библиотеки C++.
Самое простое, что вы можете сделать, это обновить стандартную библиотеку C++ до новой версии. Версия стандартной библиотеки C++ является причиной того, что Ubuntu 20.04 Focal Fossa работает, а Ubuntu 18.04 Bionic Beaver — нет.
Что касается clang 10 в Ubuntu 18.04, то он не компилируется из-за того, что вы все еще используете старую системную библиотеку libstdc++, которая не содержит заголовка
. Вы должны установить g++ 9, который содержит более новую libstdc++, чтобы вы могли скомпилировать с 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++.
Если вам абсолютно необходимо компилировать с помощью GNU libstdc++ до версии 9.1 и LLVM libc++ до версии 9.0, вам необходимо изменить код из 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
есть некоторые различия.
ВТОРАЯ ЧАСТЬ СЛОЖНОГО РЕШЕНИЯ — ФЛАГИ КОМПИЛЯЦИИ:
Для GNU libstdc++ до версии 9.1 с gcc или clang вам нужно использовать флаг -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)
Для LLVM libc++ до 9.0 с clang вам нужно использовать флаг -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)