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
0102 if(TARGET std::filesystem)
0103 # This module has already been processed. Don't do it again.
0104 return()
0105 endif()
0106
0107 cmake_minimum_required(VERSION 3.10)
0108
0109 include(CMakePushCheckState)
0110 include(CheckIncludeFileCXX)
0111
0112 # If we're not cross-compiling, try to run test executables.
0113 # Otherwise, assume that compile + link is a sufficient check.
0114 if(CMAKE_CROSSCOMPILING)
0115 include(CheckCXXSourceCompiles)
0116 macro(_cmcm_check_cxx_source code var)
0117 check_cxx_source_compiles("${code}" ${var})
0118 endmacro()
0119 else()
0120 include(CheckCXXSourceRuns)
0121 macro(_cmcm_check_cxx_source code var)
0122 check_cxx_source_runs("${code}" ${var})
0123 endmacro()
0124 endif()
0125
0126 cmake_push_check_state()
0127
0128 set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
0129
0130 # All of our tests required C++17 or later
0131 set(CMAKE_CXX_STANDARD 17)
0132
0133 # Normalize and check the component list we were given
0134 set(want_components ${Filesystem_FIND_COMPONENTS})
0135 if(Filesystem_FIND_COMPONENTS STREQUAL "")
0136 set(want_components Final)
0137 endif()
0138
0139 # Warn on any unrecognized components
0140 set(extra_components ${want_components})
0141 list(REMOVE_ITEM extra_components Final Experimental)
0142 foreach(component IN LISTS extra_components)
0143 message(WARNING "Extraneous find_package component for Filesystem: ${component}")
0144 endforeach()
0145
0146 # Detect which of Experimental and Final we should look for
0147 set(find_experimental TRUE)
0148 set(find_final TRUE)
0149 if(NOT "Final" IN_LIST want_components)
0150 set(find_final FALSE)
0151 endif()
0152 if(NOT "Experimental" IN_LIST want_components)
0153 set(find_experimental FALSE)
0154 endif()
0155
0156 if(find_final)
0157 check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
0158 mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
0159 if(_CXX_FILESYSTEM_HAVE_HEADER)
0160 # We found the non-experimental header. Don't bother looking for the
0161 # experimental one.
0162 set(find_experimental FALSE)
0163 endif()
0164 else()
0165 set(_CXX_FILESYSTEM_HAVE_HEADER FALSE)
0166 endif()
0167
0168 if(find_experimental)
0169 check_include_file_cxx("experimental/filesystem" _CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
0170 mark_as_advanced(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
0171 else()
0172 set(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER FALSE)
0173 endif()
0174
0175 if(_CXX_FILESYSTEM_HAVE_HEADER)
0176 set(_have_fs TRUE)
0177 set(_fs_header filesystem)
0178 set(_fs_namespace std::filesystem)
0179 set(_is_experimental FALSE)
0180 elseif(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
0181 set(_have_fs TRUE)
0182 set(_fs_header experimental/filesystem)
0183 set(_fs_namespace std::experimental::filesystem)
0184 set(_is_experimental TRUE)
0185 else()
0186 set(_have_fs FALSE)
0187 endif()
0188
0189 set(CXX_FILESYSTEM_HAVE_FS ${_have_fs} CACHE BOOL "TRUE if we have the C++ filesystem headers")
0190 set(CXX_FILESYSTEM_HEADER ${_fs_header} CACHE STRING "The header that should be included to obtain the filesystem APIs")
0191 set(CXX_FILESYSTEM_NAMESPACE ${_fs_namespace} CACHE STRING "The C++ namespace that contains the filesystem APIs")
0192 set(CXX_FILESYSTEM_IS_EXPERIMENTAL ${_is_experimental} CACHE BOOL "TRUE if the C++ filesystem library is the experimental version")
0193
0194 set(_found FALSE)
0195
0196 if(CXX_FILESYSTEM_HAVE_FS)
0197 # We have some filesystem library available. Do link checks
0198 string(CONFIGURE [[
0199 #include <cstdlib>
0200 #include <@CXX_FILESYSTEM_HEADER@>
0201
0202 int main() {
0203 auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
0204 printf("%s", cwd.c_str());
0205 return EXIT_SUCCESS;
0206 }
0207 ]] code @ONLY)
0208
0209 # Check a simple filesystem program without any linker flags
0210 _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
0211
0212 set(can_link ${CXX_FILESYSTEM_NO_LINK_NEEDED})
0213
0214 if(NOT CXX_FILESYSTEM_NO_LINK_NEEDED)
0215 set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
0216 # Add the libstdc++ flag
0217 set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
0218 _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
0219 set(can_link ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
0220 if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
0221 # Try the libc++ flag
0222 set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
0223 _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
0224 set(can_link ${CXX_FILESYSTEM_CPPFS_NEEDED})
0225 endif()
0226 endif()
0227
0228 if(can_link)
0229 add_library(std::filesystem INTERFACE IMPORTED)
0230 set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
0231 set(_found TRUE)
0232
0233 if(CXX_FILESYSTEM_NO_LINK_NEEDED)
0234 # Nothing to add...
0235 elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
0236 set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lstdc++fs)
0237 elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
0238 set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lc++fs)
0239 endif()
0240 endif()
0241 endif()
0242
0243 cmake_pop_check_state()
0244
0245 set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
0246
0247 if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
0248 message(FATAL_ERROR "Cannot run simple program using std::filesystem")
0249 endif()