Как использовать cmake для обеспечения связи компилятора C++14 с экспериментальной библиотекой файловой системы TS?
Я (переключаюсь на) использую <std::experimental::filesystem>
в моем коде C++14, и мне нужно иметь возможность построить его, используя GCC 5.x в Linux (и любой компилятор с поддержкой C++14 или, по крайней мере, соответствующие версии clang, msvc и, возможно, icc),
Теперь, когда я делаю ссылку, я получаю ошибки об отсутствии всех символов, связанных с файловой системой, например:
foo.cpp:(.text+0x9cd): undefined reference to `std::experimental::filesystem::v1::__cxx11::path::_M_split_cmpts()'
Теперь, если я "вручную" добавить зависимость от libstdc++fs
:
target_link_libraries(foo other_lib stdc++fs)
тогда все нормально связывается - но как мне обобщить это на любой компилятор с поддержкой 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
Я думаю, это проблема и для других компиляторов.
1 ответ
К сожалению, это именно то, как он предназначен для использования. Смотрите соответствующую часть документации libstdC++:
GCC 5.3 включает реализацию библиотеки файловой системы, определенной технической спецификацией ISO/IEC TS 18822:2015. Поскольку это экспериментальное расширение библиотеки, не являющееся частью стандарта C++, оно реализовано в отдельной библиотеке libstdC++fs.a, и для него нет общей библиотеки. Чтобы использовать библиотеку, вы должны включить и связать ее с -lstdC++ fs. Реализация библиотеки является неполной на не POSIX платформах, в частности, поддержка Windows является зачаточной.
Из-за экспериментального характера библиотеки файловой системы обычные гарантии стабильности ABI и обратной совместимости к ней не применяются. Нет гарантии, что компоненты в любом заголовке останутся совместимыми между различными версиями GCC.
(акцент мой)
Связывать libstdc++fs
только в GCC вы можете использовать соответствующую переменную CMake:
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})