如何使用 cmake 确保 C++14 编译器与实验文件系统 TS 库链接?

How do I use cmake to ensure a C++14 compiler links with the experimental filesystem TS library?

我正在(切换到)在我的 C++14 代码中使用 <std::experimental::filesystem>,我需要能够在 Linux 上使用 GCC 5.x 构建它(并且任何支持 C++14 的编译器,或者至少是 - clang、msvc 和 icc 的相关版本)。

现在,当我 link 时,我收到有关丢失所有文件系统相关符号的错误,例如:

foo.cpp:(.text+0x9cd): undefined reference to `std::experimental::filesystem::v1::__cxx11::path::_M_split_cmpts()'

现在,如果我 "manually" 添加对 libstdc++fs 的依赖:

target_link_libraries(foo other_lib stdc++fs)

然后一切 link 都很好 - 但我如何将其推广到任何支持 C++14 的编译器?

注意:我的 CMakeLists.txt 的相关部分看起来像这样:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_library(bar src/bar.cpp)
add_executable(foo src/foo.cpp)
target_link_libraries(foo bar other_lib)

* (当我使用 boost::filesystem 时,它反而更容易 - 我只需要使用任何 FindBoost.cmake 产生的东西。)
** 我猜,使用 -Wall 对其他编译器也是一个问题。

不幸的是,这正是它的用途。见 the relevant part of libstdc++ documentation:

GCC 5.3 includes an implementation of the Filesystem library defined by the technical specification ISO/IEC TS 18822:2015. Because this is an experimental library extension, not part of the C++ standard, it is implemented in a separate library, libstdc++fs.a, and there is no shared library for it. To use the library you should include and link with -lstdc++fs. The library implementation is incomplete on non-POSIX platforms, specifically Windows support is rudimentary.

Due to the experimental nature of the Filesystem library the usual guarantees about ABI stability and backwards compatibility do not apply to it. There is no guarantee that the components in any header will remain compatible between different GCC releases.

(强调我的)

要link libstdc++fs显式只在GCC下,可以使用relevant CMake variable:

target_link_libraries(foo other_lib)
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU)
    target_link_libraries(foo stdc++fs)
endif()

或者,以更奇特的方式,

if (CMAKE_CXX_COMPILER_ID STREQUAL GNU)
    set(CXX_FILESYSTEM_LIBRARIES stdc++fs)
else()
    set(CXX_FILESYSTEM_LIBRARIES)
endif()
target_link_libraries(foo other_lib ${CXX_FILESYSTEM_LIBRARIES})