Warning, /acts/cmake/FindFilesystem.cmake is written in an unsupported language. File is not indexed.
0001 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
0002 # file Copyright.txt or https://cmake.org/licensing for details.
0003
0004 # originally from https://github.com/vector-of-bool/CMakeCM/blob/master/modules/FindFilesystem.cmake
0005
0006 #[=======================================================================[.rst:
0007
0008 FindFilesystem
0009 ##############
0010
0011 This module supports the C++17 standard library's filesystem utilities. Use the
0012 :imp-target:`std::filesystem` imported target to
0013
0014 Options
0015 *******
0016
0017 The ``COMPONENTS`` argument to this module supports the following values:
0018
0019 .. find-component:: Experimental
0020 :name: fs.Experimental
0021
0022 Allows the module to find the "experimental" Filesystem TS version of the
0023 Filesystem library. This is the library that should be used with the
0024 ``std::experimental::filesystem`` namespace.
0025
0026 .. find-component:: Final
0027 :name: fs.Final
0028
0029 Finds the final C++17 standard version of the filesystem library.
0030
0031 If no components are provided, behaves as if the
0032 :find-component:`fs.Final` component was specified.
0033
0034 If both :find-component:`fs.Experimental` and :find-component:`fs.Final` are
0035 provided, first looks for ``Final``, and falls back to ``Experimental`` in case
0036 of failure. If ``Final`` is found, :imp-target:`std::filesystem` and all
0037 :ref:`variables <fs.variables>` will refer to the ``Final`` version.
0038
0039
0040 Imported Targets
0041 ****************
0042
0043 .. imp-target:: std::filesystem
0044
0045 The ``std::filesystem`` imported target is defined when any requested
0046 version of the C++ filesystem library has been found, whether it is
0047 *Experimental* or *Final*.
0048
0049 If no version of the filesystem library is available, this target will not
0050 be defined.
0051
0052 .. note::
0053 This target has ``cxx_std_17`` as an ``INTERFACE``
0054 :ref:`compile language standard feature <req-lang-standards>`. Linking
0055 to this target will automatically enable C++17 if no later standard
0056 version is already required on the linking target.
0057
0058
0059 .. _fs.variables:
0060
0061 Variables
0062 *********
0063
0064 .. variable:: CXX_FILESYSTEM_IS_EXPERIMENTAL
0065
0066 Set to ``TRUE`` when the :find-component:`fs.Experimental` version of C++
0067 filesystem library was found, otherwise ``FALSE``.
0068
0069 .. variable:: CXX_FILESYSTEM_HAVE_FS
0070
0071 Set to ``TRUE`` when a filesystem header was found.
0072
0073 .. variable:: CXX_FILESYSTEM_HEADER
0074
0075 Set to either ``filesystem`` or ``experimental/filesystem`` depending on
0076 whether :find-component:`fs.Final` or :find-component:`fs.Experimental` was
0077 found.
0078
0079 .. variable:: CXX_FILESYSTEM_NAMESPACE
0080
0081 Set to either ``std::filesystem`` or ``std::experimental::filesystem``
0082 depending on whether :find-component:`fs.Final` or
0083 :find-component:`fs.Experimental` was found.
0084
0085
0086 Examples
0087 ********
0088
0089 Using `find_package(Filesystem)` with no component arguments:
0090
0091 .. code-block:: cmake
0092
0093 find_package(Filesystem REQUIRED)
0094
0095 add_executable(my-program main.cpp)
0096 target_link_libraries(my-program PRIVATE std::filesystem)
0097
0098
0099 #]=======================================================================]
0100
0101 if(TARGET std::filesystem)
0102 # This module has already been processed. Don't do it again.
0103 return()
0104 endif()
0105
0106 cmake_minimum_required(VERSION 3.10)
0107
0108 include(CMakePushCheckState)
0109 include(CheckIncludeFileCXX)
0110
0111 # If we're not cross-compiling, try to run test executables.
0112 # Otherwise, assume that compile + link is a sufficient check.
0113 if(CMAKE_CROSSCOMPILING)
0114 include(CheckCXXSourceCompiles)
0115 macro(_cmcm_check_cxx_source code var)
0116 check_cxx_source_compiles("${code}" ${var})
0117 endmacro()
0118 else()
0119 include(CheckCXXSourceRuns)
0120 macro(_cmcm_check_cxx_source code var)
0121 check_cxx_source_runs("${code}" ${var})
0122 endmacro()
0123 endif()
0124
0125 cmake_push_check_state()
0126
0127 set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
0128
0129 # All of our tests required C++17 or later
0130 if(DEFINED CMAKE_CXX_STANDARD)
0131 set(_prior_cmake_cxx_standard ${CMAKE_CXX_STANDARD})
0132 endif()
0133
0134 set(CMAKE_CXX_STANDARD 17)
0135
0136 # Normalize and check the component list we were given
0137 set(want_components ${Filesystem_FIND_COMPONENTS})
0138 if(Filesystem_FIND_COMPONENTS STREQUAL "")
0139 set(want_components Final)
0140 endif()
0141
0142 # Warn on any unrecognized components
0143 set(extra_components ${want_components})
0144 list(REMOVE_ITEM extra_components Final Experimental)
0145 foreach(component IN LISTS extra_components)
0146 message(
0147 WARNING
0148 "Extraneous find_package component for Filesystem: ${component}"
0149 )
0150 endforeach()
0151
0152 # Detect which of Experimental and Final we should look for
0153 set(find_experimental TRUE)
0154 set(find_final TRUE)
0155 if(NOT "Final" IN_LIST want_components)
0156 set(find_final FALSE)
0157 endif()
0158 if(NOT "Experimental" IN_LIST want_components)
0159 set(find_experimental FALSE)
0160 endif()
0161
0162 if(find_final)
0163 check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
0164 mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
0165 if(_CXX_FILESYSTEM_HAVE_HEADER)
0166 # We found the non-experimental header. Don't bother looking for the
0167 # experimental one.
0168 set(find_experimental FALSE)
0169 endif()
0170 else()
0171 set(_CXX_FILESYSTEM_HAVE_HEADER FALSE)
0172 endif()
0173
0174 if(find_experimental)
0175 check_include_file_cxx(
0176 "experimental/filesystem"
0177 _CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER
0178 )
0179 mark_as_advanced(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
0180 else()
0181 set(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER FALSE)
0182 endif()
0183
0184 if(_CXX_FILESYSTEM_HAVE_HEADER)
0185 set(_have_fs TRUE)
0186 set(_fs_header filesystem)
0187 set(_fs_namespace std::filesystem)
0188 set(_is_experimental FALSE)
0189 elseif(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
0190 set(_have_fs TRUE)
0191 set(_fs_header experimental/filesystem)
0192 set(_fs_namespace std::experimental::filesystem)
0193 set(_is_experimental TRUE)
0194 else()
0195 set(_have_fs FALSE)
0196 endif()
0197
0198 set(CXX_FILESYSTEM_HAVE_FS
0199 ${_have_fs}
0200 CACHE BOOL
0201 "TRUE if we have the C++ filesystem headers"
0202 )
0203 set(CXX_FILESYSTEM_HEADER
0204 ${_fs_header}
0205 CACHE STRING
0206 "The header that should be included to obtain the filesystem APIs"
0207 )
0208 set(CXX_FILESYSTEM_NAMESPACE
0209 ${_fs_namespace}
0210 CACHE STRING
0211 "The C++ namespace that contains the filesystem APIs"
0212 )
0213 set(CXX_FILESYSTEM_IS_EXPERIMENTAL
0214 ${_is_experimental}
0215 CACHE BOOL
0216 "TRUE if the C++ filesystem library is the experimental version"
0217 )
0218
0219 set(_found FALSE)
0220
0221 if(CXX_FILESYSTEM_HAVE_FS)
0222 # We have some filesystem library available. Do link checks
0223 string(
0224 CONFIGURE
0225 [[
0226 #include <cstdlib>
0227 #include <@CXX_FILESYSTEM_HEADER@>
0228
0229 int main() {
0230 auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
0231 printf("%s", cwd.c_str());
0232 return EXIT_SUCCESS;
0233 }
0234 ]]
0235 code
0236 @ONLY
0237 )
0238
0239 # Check a simple filesystem program without any linker flags
0240 _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
0241
0242 set(can_link ${CXX_FILESYSTEM_NO_LINK_NEEDED})
0243
0244 if(NOT CXX_FILESYSTEM_NO_LINK_NEEDED)
0245 set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
0246 # Add the libstdc++ flag
0247 set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
0248 _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
0249 set(can_link ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
0250 if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
0251 # Try the libc++ flag
0252 set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
0253 _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
0254 set(can_link ${CXX_FILESYSTEM_CPPFS_NEEDED})
0255 endif()
0256 endif()
0257
0258 if(can_link)
0259 add_library(std::filesystem INTERFACE IMPORTED)
0260 set_property(
0261 TARGET std::filesystem
0262 APPEND
0263 PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17
0264 )
0265 set(_found TRUE)
0266
0267 if(CXX_FILESYSTEM_NO_LINK_NEEDED)
0268 # Nothing to add...
0269 elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
0270 set_property(
0271 TARGET std::filesystem
0272 APPEND
0273 PROPERTY INTERFACE_LINK_LIBRARIES -lstdc++fs
0274 )
0275 elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
0276 set_property(
0277 TARGET std::filesystem
0278 APPEND
0279 PROPERTY INTERFACE_LINK_LIBRARIES -lc++fs
0280 )
0281 endif()
0282 endif()
0283 endif()
0284
0285 cmake_pop_check_state()
0286
0287 set(Filesystem_FOUND
0288 ${_found}
0289 CACHE BOOL
0290 "TRUE if we can run a program using std::filesystem"
0291 FORCE
0292 )
0293
0294 if(DEFINED _prior_cmake_cxx_standard)
0295 set(CMAKE_CXX_STANDARD ${_prior_cmake_cxx_standard})
0296 else()
0297 unset(CMAKE_CXX_STANDARD)
0298 endif()
0299
0300 if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
0301 message(FATAL_ERROR "Cannot run simple program using std::filesystem")
0302 endif()