Как получить libstdc ++ с заголовками C ++ 17 / filesystem в Ubuntu 18 (bionic)?

В 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 делает компиляцию работоспособной.

0
задан 5 July 2020 в 05:19

1 ответ

Всякий раз, когда ошибка компиляции 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)
8
ответ дан 1 November 2020 в 18:34

Другие вопросы по тегам:

Похожие вопросы: