Problem adding std::filesystem to CMake Project

Gcc 8.2. comes with <filesystem>, so there is no need to investigate with regard to the availability. Next, option 1 is sufficient, but needs a fix:

set(CMAKE_CXX_STANDARD 17) # no need to manually adjust the CXXFLAGS

add_executable(yourExecutable yourSourceFile.cpp)

target_link_libraries(yourExecutable stdc++fs)

This should result in compiling the sources with -std=c++17 or -std=gnu++17 and adding -lstdc++fs when linking.

Edit: Note that as @Ashkan has pointed out in the comments, setting CMAKE_CXX_STANDARD_REQUIRED to true results in an immediate error at configure time if C++17 isn't supported by the compiler, instead of a compilation error (due to the missing <filesystem> header) or at link time (due to the missing shared library). This might be desirable.


Besides from @lubgr's answer. I think a more complete way is to also do try_compile to see that you can actually use the filesystem header. This in my opinion is better because some compilers are not supporting std::filesystem yet. Also in gcc 7.x you have the filesystem under experimental namespace. This way you can have a separate try_compile in the else clause and detect that.

Here is the related cmake for it

# set everything up for c++ 17 features
set(CMAKE_CXX_STANDARD 17)
# Don't add this line if you will try_compile with boost.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# test that filesystem header actually is there and works
try_compile(HAS_FS "${CMAKE_BINARY_DIR}/temp" 
"${CMAKE_SOURCE_DIR}/tests/has_filesystem.cc" 
            CMAKE_FLAGS -DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=ON
            LINK_LIBRARIES stdc++fs)
if(HAS_FS)
    message(STATUS "Compiler has filesystem support")
else()
#   .... You could also try searching for boost::filesystem here.
    message(FATAL_ERROR "Compiler is missing filesystem capabilities")
endif(HAS_FS)

The file tests/has_filesystem.cc is very simple

#include <filesystem>

namespace fs = std::filesystem;

int main()
{
    fs::path aPath {"../"};

    return 0;
}

You could in your else clause try_compile for boost::filesystem and pass a directive that can be used in your source file where you decide if you want to use c++17 filesystem or boost.


CHECK_CXX_SYMBOL_EXISTS takes three arguments, not two:

CHECK_CXX_SYMBOL_EXISTS(std::filesystem::path::preferred_separator filesystem cxx17fs)

You forgot to tell CMake where to look for the symbols (the header that declares them).

Tags:

C++

Cmake