How to get libstdc++ with C++17/filesystem headers on Ubuntu 18 (bionic)?

15,921

Whenever a C++ compilation error says the <filesystem> header is not found it is because GNU libstdc++ prior to 9.1 and LLVM libc++ prior to 9.0 have not implemented std::filesystem yet.

EASY SOLUTION:

With this solution the code will compile but it won't support older C++ standard libraries.

The easiest thing you can do is update to a newer C++ standard library. The version of the C++ standard library is the reason that Ubuntu 20.04 Focal Fossa works but Ubuntu 18.04 Bionic Beaver doesn't.

As for clang 10 on Ubuntu 18.04 not compiling is because you are still using the system's older libstdc++ that doesn't contain the <filesystem> header. You must install g++ 9 that contains a newer libstdc++ so you can compile with clang 10.

On Ubuntu 18.04 do the following :

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install gcc-9 g++-9

Now clang 10 will compile correctly.

DIFFICULT SOLUTION:

With this solution the code will compile and it will support older C++ standard libraries. The downside of this solution is that an extra compilation flag will be needed that is different between GNU libstdc++ and LLVM libc++.

If you absolutely need to compile with GNU libstdc++ prior to 9.1 and LLVM libc++ prior to 9.0 you have to modify the code from OpenVPN3. Since OpenVPN3 is open source if you change their code you can then send a pull request and they may accept your contribution.

FIRST PART OF DIFFICULT SOLUTION - CODE CHANGES :

You need to modify OpenVPN3 code so it chooses between the std::filesystem and std::experimental::filesystem namespaces depending on what header is available.

#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

Now you have to use the namespace fs namepsace instead of std::filesystem.

The code before :

std::filesystem::path file("document.txt");

The code after :

fs::path file("document.txt");

Be careful because there are some differences between std::filesystem and std::experimental::filesystem.

SECOND PART OF DIFFICULT SOLUTION - COMPILATION FLAGS:

For GNU libstdc++ before 9.1 with gcc or clang you need to use the flag -lstdc++fs as the last flag. The order is important.

g++ -std=c++17 your_code.cpp -lstdc++fs

or

clang++ -std=c++17 your_code.cpp -lstdc++fs

To do the above with CMake add the following after add_executable():

target_link_libraries(project_name_here stdc++fs)

For LLVM libc++ before 9.0 with clang you need to use the flag -lc++fs as the last flag. To use libc++ do not forget to install the libc++-dev and libc++abi-dev.

clang++ -std=c++17 -stdlib=libc++ -lc++abi your_code.cpp -lstdc++fs

To do the above with CMake add the following after add_executable():

target_link_libraries(project_name_here c++fs)
Share:
15,921
PPP
Author by

PPP

Updated on September 18, 2022

Comments

  • PPP
    PPP over 1 year

    On ubuntu bionic from Docker, I'm getting this:

    No such file or directory
     #include <filesystem>
    

    on a C++ file that does this:

    #if __cplusplus >= 201703L
    #include <filesystem>
    #endif
    

    when trying to compile with clang 6.0. Unfortunately I cannot move to experimental/filesystem because it's not my library, it's from OpenVPN3. I tried with clang 10 and still got the error.

    Ubuntu 20.04 (focal on docker) works! However I wanted to use a more older version to have compatibility with older systems.

    This is the output that cmake/make produces when compiling the file that gives the error:

    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
    

    I guess something's wrong with libstdc++ on 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}"
    

    simply changing bionic to focal makes the compilation work.

  • James
    James over 3 years
    with regards to your easy solution, my g++ --version g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 but I don't seem to have the filesystem lib. I'm checking now to see if I can still install the experimental or boost versions, if they exists...
  • Michael Trikergiotis
    Michael Trikergiotis over 3 years
    @James The filesystem library needs C++ 17. You probably missed the required -std=c++17 flag when compiling. Please also note that the easy solution states the steps are for Ubuntu 18.04 not Ubuntu 20. On Ubuntu 20 and you should not use the easy solution as it works out of the box. I downloaded a fresh copy of Ubuntu 18.04.5 and compiled several projects that use filesystem library and the easy solution is still accurate. I also downloaded Ubuntu 20.04.1 and it works out of the box. If you want further help please report Ubuntu version, compiler flags used and the exact error message.