From 8e6f6d3752752bfe45b1b2ca0c6fcba4dd9dbadb Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Thu, 30 Jul 2026 06:53:31 +0200 Subject: [PATCH] cmake: auto-detect if std::filesystem needs -lstdc++fs (fixes RHEL8/gcc-8.5) On gcc-8 (e.g. RHEL8's system compiler, 8.5), std::filesystem is present but still split out into a separate archive, libstdc++fs.a, so linking msr2msr failed with undefined references such as std::filesystem::remove(std::filesystem::__cxx11::path const&, std::error_code&). gcc>=9 and clang/libc++ ship it in the main runtime library already. Detect this via an actual compile+link try (first with no extra lib, then with -lstdc++fs/-lc++fs) instead of guessing from compiler/OS, so macOS, RHEL9/10, Ubuntu, etc. are unaffected. Co-Authored-By: Claude Sonnet 5 --- CMakeLists.txt | 39 +++++++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a4d0e64..61c5260d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,6 +162,45 @@ find_package(FFTW3 REQUIRED) #--- check for libxml2 -------------------------------------------------------- find_package(LibXml2 REQUIRED) +#--- check whether needs an extra library to link ---------------- +#--- On most current toolchains (gcc>=9, clang/libc++, MSVC, macOS) std::filesystem +#--- lives in the main runtime library and just works. On gcc-8 (e.g. RHEL8's +#--- system gcc, 8.5) it is present but still split out into a separate static +#--- archive, libstdc++fs.a, and needs an explicit -lstdc++fs, otherwise linking +#--- fails with 'undefined reference to std::filesystem::remove(...)' etc. +#--- Detected via an actual compile+link try, so this adapts automatically +#--- instead of guessing from compiler/OS name and risks affecting unrelated +#--- platforms. ----------------------------------------------------------- +include(CheckCXXSourceCompiles) +set(STDFS_TEST_SRC " +#include +int main() { + std::filesystem::path p(\"foo\"); + std::error_code ec; + std::filesystem::remove(p, ec); + return 0; +} +") +check_cxx_source_compiles("${STDFS_TEST_SRC}" HAVE_STD_FILESYSTEM_NOLIB) + +set(STDFS_LIBRARY "") +if (NOT HAVE_STD_FILESYSTEM_NOLIB) + foreach (_stdfs_lib stdc++fs c++fs) + set(CMAKE_REQUIRED_LIBRARIES ${_stdfs_lib}) + unset(HAVE_STD_FILESYSTEM_WITH_${_stdfs_lib} CACHE) + check_cxx_source_compiles("${STDFS_TEST_SRC}" HAVE_STD_FILESYSTEM_WITH_${_stdfs_lib}) + unset(CMAKE_REQUIRED_LIBRARIES) + if (HAVE_STD_FILESYSTEM_WITH_${_stdfs_lib}) + set(STDFS_LIBRARY ${_stdfs_lib}) + break () + endif () + endforeach () + if (NOT STDFS_LIBRARY) + message(FATAL_ERROR "std::filesystem is required but no linkable implementation could be found") + endif () + message(STATUS "std::filesystem needs extra library: ${STDFS_LIBRARY}") +endif () + #--- check for OpenMP --------------------------------------------------------- if (try_OpenMP) #--- AppleClang has no built-in OpenMP runtime; MacPorts' 'libomp' port diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da69a3f9..105f6146 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,7 +76,7 @@ target_include_directories(msr2msr BEFORE PRIVATE $ ) -target_link_libraries(msr2msr ${ROOT_LIBRARIES}) +target_link_libraries(msr2msr ${ROOT_LIBRARIES} ${STDFS_LIBRARY}) add_executable(musrfit musrfit.cpp) target_compile_options(musrfit BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")