Celestia

Форк
0
/
FindFilesystem.cmake 
247 строк · 7.9 Кб
1
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
# file Copyright.txt or https://cmake.org/licensing for details.
3

4
#[=======================================================================[.rst:
5

6
FindFilesystem
7
##############
8

9
This module supports the C++17 standard library's filesystem utilities. Use the
10
:imp-target:`std::filesystem` imported target to
11

12
Options
13
*******
14

15
The ``COMPONENTS`` argument to this module supports the following values:
16

17
.. find-component:: Experimental
18
    :name: fs.Experimental
19

20
    Allows the module to find the "experimental" Filesystem TS version of the
21
    Filesystem library. This is the library that should be used with the
22
    ``std::experimental::filesystem`` namespace.
23

24
.. find-component:: Final
25
    :name: fs.Final
26

27
    Finds the final C++17 standard version of the filesystem library.
28

29
If no components are provided, behaves as if the
30
:find-component:`fs.Final` component was specified.
31

32
If both :find-component:`fs.Experimental` and :find-component:`fs.Final` are
33
provided, first looks for ``Final``, and falls back to ``Experimental`` in case
34
of failure. If ``Final`` is found, :imp-target:`std::filesystem` and all
35
:ref:`variables <fs.variables>` will refer to the ``Final`` version.
36

37

38
Imported Targets
39
****************
40

41
.. imp-target:: std::filesystem
42

43
    The ``std::filesystem`` imported target is defined when any requested
44
    version of the C++ filesystem library has been found, whether it is
45
    *Experimental* or *Final*.
46

47
    If no version of the filesystem library is available, this target will not
48
    be defined.
49

50
    .. note::
51
        This target has ``cxx_std_17`` as an ``INTERFACE``
52
        :ref:`compile language standard feature <req-lang-standards>`. Linking
53
        to this target will automatically enable C++17 if no later standard
54
        version is already required on the linking target.
55

56

57
.. _fs.variables:
58

59
Variables
60
*********
61

62
.. variable:: CXX_FILESYSTEM_IS_EXPERIMENTAL
63

64
    Set to ``TRUE`` when the :find-component:`fs.Experimental` version of C++
65
    filesystem library was found, otherwise ``FALSE``.
66

67
.. variable:: CXX_FILESYSTEM_HAVE_FS
68

69
    Set to ``TRUE`` when a filesystem header was found.
70

71
.. variable:: CXX_FILESYSTEM_HEADER
72

73
    Set to either ``filesystem`` or ``experimental/filesystem`` depending on
74
    whether :find-component:`fs.Final` or :find-component:`fs.Experimental` was
75
    found.
76

77
.. variable:: CXX_FILESYSTEM_NAMESPACE
78

79
    Set to either ``std::filesystem`` or ``std::experimental::filesystem``
80
    depending on whether :find-component:`fs.Final` or
81
    :find-component:`fs.Experimental` was found.
82

83

84
Examples
85
********
86

87
Using `find_package(Filesystem)` with no component arguments:
88

89
.. code-block:: cmake
90

91
    find_package(Filesystem REQUIRED)
92

93
    add_executable(my-program main.cpp)
94
    target_link_libraries(my-program PRIVATE std::filesystem)
95

96

97
#]=======================================================================]
98

99

100
if(TARGET std::filesystem)
101
    # This module has already been processed. Don't do it again.
102
    return()
103
endif()
104

105
cmake_minimum_required(VERSION 3.10)
106

107
include(CMakePushCheckState)
108
include(CheckIncludeFileCXX)
109

110
# If we're not cross-compiling, try to run test executables.
111
# Otherwise, assume that compile + link is a sufficient check.
112
if(CMAKE_CROSSCOMPILING)
113
    include(CheckCXXSourceCompiles)
114
    macro(_cmcm_check_cxx_source code var)
115
        check_cxx_source_compiles("${code}" ${var})
116
    endmacro()
117
else()
118
    include(CheckCXXSourceRuns)
119
    macro(_cmcm_check_cxx_source code var)
120
        check_cxx_source_runs("${code}" ${var})
121
    endmacro()
122
endif()
123

124
cmake_push_check_state()
125

126
set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
127

128
# All of our tests required C++17 or later
129
set(CMAKE_CXX_STANDARD 17)
130

131
# Normalize and check the component list we were given
132
set(want_components ${Filesystem_FIND_COMPONENTS})
133
if(Filesystem_FIND_COMPONENTS STREQUAL "")
134
    set(want_components Final)
135
endif()
136

137
# Warn on any unrecognized components
138
set(extra_components ${want_components})
139
list(REMOVE_ITEM extra_components Final Experimental)
140
foreach(component IN LISTS extra_components)
141
    message(WARNING "Extraneous find_package component for Filesystem: ${component}")
142
endforeach()
143

144
# Detect which of Experimental and Final we should look for
145
set(find_experimental TRUE)
146
set(find_final TRUE)
147
if(NOT "Final" IN_LIST want_components)
148
    set(find_final FALSE)
149
endif()
150
if(NOT "Experimental" IN_LIST want_components)
151
    set(find_experimental FALSE)
152
endif()
153

154
if(find_final)
155
    check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
156
    mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
157
    if(_CXX_FILESYSTEM_HAVE_HEADER)
158
        # We found the non-experimental header. Don't bother looking for the
159
        # experimental one.
160
        set(find_experimental FALSE)
161
    endif()
162
else()
163
    set(_CXX_FILESYSTEM_HAVE_HEADER FALSE)
164
endif()
165

166
if(find_experimental)
167
    check_include_file_cxx("experimental/filesystem" _CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
168
    mark_as_advanced(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
169
else()
170
    set(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER FALSE)
171
endif()
172

173
if(_CXX_FILESYSTEM_HAVE_HEADER)
174
    set(_have_fs TRUE)
175
    set(_fs_header filesystem)
176
    set(_fs_namespace std::filesystem)
177
    set(_is_experimental FALSE)
178
elseif(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
179
    set(_have_fs TRUE)
180
    set(_fs_header experimental/filesystem)
181
    set(_fs_namespace std::experimental::filesystem)
182
    set(_is_experimental TRUE)
183
else()
184
    set(_have_fs FALSE)
185
endif()
186

187
set(CXX_FILESYSTEM_HAVE_FS ${_have_fs} CACHE BOOL "TRUE if we have the C++ filesystem headers")
188
set(CXX_FILESYSTEM_HEADER ${_fs_header} CACHE STRING "The header that should be included to obtain the filesystem APIs")
189
set(CXX_FILESYSTEM_NAMESPACE ${_fs_namespace} CACHE STRING "The C++ namespace that contains the filesystem APIs")
190
set(CXX_FILESYSTEM_IS_EXPERIMENTAL ${_is_experimental} CACHE BOOL "TRUE if the C++ filesystem library is the experimental version")
191

192
set(_found FALSE)
193

194
if(CXX_FILESYSTEM_HAVE_FS)
195
    # We have some filesystem library available. Do link checks
196
    string(CONFIGURE [[
197
        #include <cstdlib>
198
        #include <@CXX_FILESYSTEM_HEADER@>
199

200
        int main() {
201
            auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
202
            printf("%s", cwd.c_str());
203
            return EXIT_SUCCESS;
204
        }
205
    ]] code @ONLY)
206

207
    # Check a simple filesystem program without any linker flags
208
    _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
209

210
    set(can_link ${CXX_FILESYSTEM_NO_LINK_NEEDED})
211

212
    if(NOT CXX_FILESYSTEM_NO_LINK_NEEDED)
213
        set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
214
        # Add the libstdc++ flag
215
        set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
216
        _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
217
        set(can_link ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
218
        if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
219
            # Try the libc++ flag
220
            set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
221
            _cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
222
            set(can_link ${CXX_FILESYSTEM_CPPFS_NEEDED})
223
        endif()
224
    endif()
225

226
    if(can_link)
227
        add_library(std::filesystem INTERFACE IMPORTED)
228
        set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
229
        set(_found TRUE)
230

231
        if(CXX_FILESYSTEM_NO_LINK_NEEDED)
232
            # Nothing to add...
233
        elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
234
            set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lstdc++fs)
235
        elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
236
            set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lc++fs)
237
        endif()
238
    endif()
239
endif()
240

241
cmake_pop_check_state()
242

243
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
244

245
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
246
    message(FATAL_ERROR "Cannot run simple program using std::filesystem")
247
endif()
248

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.