Problem adding std::filesystem to CMake Project

后端 未结 4 621
余生分开走
余生分开走 2020-12-19 09:29

I am new to CMake projects and I want to use the file system library in my project. I am running Ubuntu 18.04 with GCC 8.2 and CMake 3.13. In order to achieve this I tried t

4条回答
  •  渐次进展
    2020-12-19 10:01

    I have found a case when try_compile was not enough: when using the Intel C++ compiler (icpc (ICC) 19.1.1.216 20200306) in C++17 mode running on MacOS "Mojave" 10.14.6. The test program recommended by @Ashkan compiled without errors, and it even ran. However, my code uses fs::path::filename() at one point and that resulted in a runtime linker error (dyld: lazy symbol binding failed: Symbol not found:). In other words: the header is there, the implementation apparently isn't (?). I didn't investigate this any further.

    The solution is to use try_run instead of try_compile and (in my case) fall back to boost::filesystem if std::filesystem is not yet supported.

    Here is the relevant CMake code section:

    try_run(RUNS_WITH_STDFS COMPILES_WITH_STDFS
        "${CMAKE_BINARY_DIR}/try"
        "${CMAKE_SOURCE_DIR}/cmake/has_stdfs.cc"
        CMAKE_FLAGS CMAKE_CXX_STANDARD=17 CMAKE_CXX_STANDARD_REQUIRED=ON
        )
    if (RUNS_WITH_STDFS STREQUAL "FAILED_TO_RUN")
        message(STATUS "Using boost::filesystem instead of std::filesystem")
        set(_boost_components ${_boost_components} filesystem system)
        add_definitions(-DUSE_BOOST_FILESYSTEM)
    else()
        message(STATUS "std::filesystem supported")
    endif()
    

    Note that the variable RUNS_WITH_STDFS is not set to NO in case of failure but to "FAILED_TO_RUN" which is not interpreted as a FALSE Boolean (see CMake if() docs:

    if() True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. False if the constant is 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, the empty string, or ends in the suffix -NOTFOUND.

    so I had to string-compare its value.

    The little test program also changed a bit compared to @Ashkan's solution:

    // == PROGRAM has_stdfs.cc ==
    
    // Check if std::filesystem is available
    // Source: https://stackoverflow.com/a/54290906
    // with modifications
    
    #include 
    namespace fs = std::filesystem;
    
    int main(int argc, char* argv[]) {
        fs::path somepath{ "dir1/dir2/filename.txt" };
        auto fname = somepath.filename();
        return 0;
    }
    

提交回复
热议问题