Skip to content

Commit cd49672

Browse files
authored
Merge pull request #276 from rpavlik/debug-cmake-gcc11
Cmake GCC11 fixes
2 parents e385e69 + 6b8f48b commit cd49672

File tree

4 files changed

+133
-78
lines changed

4 files changed

+133
-78
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
- issue.260.gh.OpenXR-SDK-Source
3+
- issue.1571.gl
4+
---
5+
- Fix detection of std::filesystem options on GCC 11 and newer.

src/cmake/StdFilesystemFlags.cmake

Lines changed: 82 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#
33
# SPDX-License-Identifier: BSL-1.0
44

5+
set(_FILESYSTEM_UTILS_DIR "${PROJECT_SOURCE_DIR}/src/common")
6+
57
if(MSVC AND MSVC_VERSION GREATER 1890)
68
set(HAVE_FILESYSTEM_WITHOUT_LIB
79
ON
@@ -18,87 +20,107 @@ if(MSVC AND MSVC_VERSION GREATER 1890)
1820
else()
1921
include(CheckCXXSourceCompiles)
2022

21-
# This is just example code that is known to not compile if std::filesystem isn't working right
23+
###
24+
# Test Sources
25+
###
26+
27+
# This is just example code that is known to not compile if std::filesystem isn't working right.
28+
# It depends on having the proper includes and `using namespace` so it can use the `is_regular_file`
29+
# function unqualified.
30+
# It is at the end of every test file below.
2231
set(_stdfs_test_source
2332
"int main() {
2433
(void)is_regular_file(\"/\");
2534
return 0;
2635
}
2736
"
2837
)
29-
set(_stdfs_conditions
30-
"// If the C++ macro is set to the version containing C++17, it must support
31-
// the final C++17 package
32-
#if __cplusplus >= 201703L
33-
#define USE_FINAL_FS 1
34-
35-
#elif defined(_MSC_VER) && _MSC_VER >= 1900
36-
37-
#if defined(_HAS_CXX17) && _HAS_CXX17
38-
// When MSC supports c++17 use <filesystem> package.
39-
#define USE_FINAL_FS 1
40-
#endif // !_HAS_CXX17
41-
42-
// Right now, GCC still only supports the experimental filesystem items starting in GCC 6
43-
#elif (__GNUC__ >= 6)
44-
#define USE_EXPERIMENTAL_FS 1
45-
46-
// If Clang, check for feature support
47-
#elif defined(__clang__) && (__cpp_lib_filesystem || __cpp_lib_experimental_filesystem)
48-
#if __cpp_lib_filesystem
49-
#define USE_FINAL_FS 1
50-
#else
51-
#define USE_EXPERIMENTAL_FS 1
52-
#endif
53-
54-
#endif
55-
"
56-
)
38+
39+
# This is preprocessor code included in all test compiles, which pulls in the conditions
40+
# originally found in filesystem_utils.cpp.
41+
#
42+
# It defines:
43+
# USE_FINAL_FS = 1 if it thinks we have the full std::filesystem in <filesystem> as in C++17
44+
# USE_EXPERIMENTAL_FS = 1 if it thinks we don't have the full c++17 filesystem, but should have
45+
# std::experimental::filesystem and <experimental/filesystem>
46+
#
47+
# Ideally the first condition (__cplusplus >= 201703L) would handle most cases,
48+
# however you're not supposed to report that unless you're fully conformant with all
49+
# of c++17, so you might have a c++17 build flag and the final filesystem library but
50+
# a lower __cplusplus value if some other part of the standard is missing.
51+
set(_stdfs_conditions "#include <stdfs_conditions.h>
52+
")
53+
54+
# This should only compile if our common detection code decides on the
55+
# **final** (non-experimental) filesystem library.
5756
set(_stdfs_source
5857
"${_stdfs_conditions}
59-
#ifdef USE_FINAL_FS
58+
#if defined(USE_FINAL_FS) && USE_FINAL_FS
6059
#include <filesystem>
6160
using namespace std::filesystem;
6261
#endif
6362
${_stdfs_test_source}
6463
"
6564
)
65+
66+
# This should only compile if our common detection code decides on the
67+
# **experimental** filesystem library.
6668
set(_stdfs_experimental_source
6769
"${_stdfs_conditions}
68-
#ifdef USE_EXPERIMENTAL_FS
70+
#if defined(USE_EXPERIMENTAL_FS) && USE_EXPERIMENTAL_FS
6971
#include <experimental/filesystem>
7072
using namespace std::experimental::filesystem;
7173
#endif
7274
${_stdfs_test_source}
7375
"
7476
)
77+
78+
# This should compile if the common detection code decided that either
79+
# the experimental or final filesystem library is available.
80+
# We use this when trying to detect what library to link, if any:
81+
# earlier checks are the ones that care about how we include the headers.
7582
set(_stdfs_needlib_source
7683
"${_stdfs_conditions}
77-
#ifdef USE_FINAL_FS
84+
#if defined(USE_FINAL_FS) && USE_FINAL_FS
7885
#include <filesystem>
7986
using namespace std::filesystem;
8087
#endif
81-
#ifdef USE_EXPERIMENTAL_FS
88+
#if defined(USE_EXPERIMENTAL_FS) && USE_EXPERIMENTAL_FS
8289
#include <experimental/filesystem>
8390
using namespace std::experimental::filesystem;
8491
#endif
8592
${_stdfs_test_source}
8693
"
8794
)
8895

96+
###
97+
# Identifying header/namespace and standards flags
98+
###
99+
89100
# First, just look for the include.
90101
# We're checking if it compiles, not if the include exists,
91-
# because the source code uses similar conditionals to decide.
102+
# because the source code uses the same conditionals to decide.
103+
# (Static libraries are just object files, they don't get linked)
92104
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
105+
set(CMAKE_REQUIRED_INCLUDES "${_FILESYSTEM_UTILS_DIR}")
93106
unset(CMAKE_REQUIRED_LIBRARIES)
94-
unset(CMAKE_REQUIRED_FLAGS)
95-
check_cxx_source_compiles("${_stdfs_source}" HAVE_FILESYSTEM_IN_STD)
96-
check_cxx_source_compiles("${_stdfs_experimental_source}" HAVE_FILESYSTEM_IN_STDEXPERIMENTAL)
107+
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0)
108+
# GCC 11+ defaults to C++17 mode and acts badly in these tests if we tell it to use a different version.
109+
set(HAVE_FILESYSTEM_IN_STD_17 ON)
110+
set(HAVE_FILESYSTEM_IN_STD OFF)
111+
else()
112+
set(CMAKE_REQUIRED_FLAGS "-DCMAKE_CXX_STANDARD=14 -DCMAKE_CXX_STANDARD_REQUIRED=TRUE")
113+
check_cxx_source_compiles("${_stdfs_source}" HAVE_FILESYSTEM_IN_STD)
114+
check_cxx_source_compiles("${_stdfs_experimental_source}" HAVE_FILESYSTEM_IN_STDEXPERIMENTAL)
97115

98-
set(CMAKE_REQUIRED_FLAGS "-DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=TRUE")
99-
check_cxx_source_compiles("${_stdfs_source}" HAVE_FILESYSTEM_IN_STD_17)
100-
unset(CMAKE_REQUIRED_FLAGS)
116+
# See if the "final" version builds if we try to specify C++17 explicitly
117+
set(CMAKE_REQUIRED_FLAGS "-DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=TRUE")
118+
check_cxx_source_compiles("${_stdfs_source}" HAVE_FILESYSTEM_IN_STD_17)
119+
unset(CMAKE_REQUIRED_FLAGS)
120+
endif()
101121

122+
# If we found the final version of filesystem when specifying C++17 explicitly,
123+
# but found it no other way, then we record that we must use C++17 flags.
102124
if(HAVE_FILESYSTEM_IN_STD_17 AND NOT HAVE_FILESYSTEM_IN_STD)
103125
set(HAVE_FILESYSTEM_NEEDS_17
104126
ON
@@ -112,21 +134,37 @@ else()
112134
)
113135
endif()
114136

115-
# Now, see if we need libstdc++fs
137+
###
138+
# Identifying library to link
139+
###
140+
141+
# Now, see if we need to link against libstdc++fs, and what it's called
142+
# If we needed C++17 standard flags to find it, they've already been set above.
116143
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
144+
145+
# Try with no lib specified
117146
check_cxx_source_compiles("${_stdfs_needlib_source}" HAVE_FILESYSTEM_WITHOUT_LIB)
147+
148+
# Try with stdc++fs
118149
set(CMAKE_REQUIRED_LIBRARIES stdc++fs)
119150
check_cxx_source_compiles("${_stdfs_needlib_source}" HAVE_FILESYSTEM_NEEDING_LIBSTDCXXFS)
151+
152+
# Try with c++fs (from clang's libc++)
120153
set(CMAKE_REQUIRED_LIBRARIES c++fs)
121154
check_cxx_source_compiles("${_stdfs_needlib_source}" HAVE_FILESYSTEM_NEEDING_LIBCXXFS)
155+
156+
# Clean up these variables before the next user.
122157
unset(CMAKE_REQUIRED_LIBRARIES)
123158
unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
124-
159+
unset(CMAKE_REQUIRED_INCLUDES)
125160
endif()
126161

162+
# Use the observations of the code above to add the filesystem_utils.cpp
163+
# file to a target, along with any required compiler settings and libraries.
164+
# Also handles our BUILD_WITH_STD_FILESYSTEM option.
127165
function(openxr_add_filesystem_utils TARGET_NAME)
128-
target_sources(${TARGET_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/src/common/filesystem_utils.cpp)
129-
target_include_directories(${TARGET_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/src/common)
166+
target_sources(${TARGET_NAME} PRIVATE ${_FILESYSTEM_UTILS_DIR}/filesystem_utils.cpp)
167+
target_include_directories(${TARGET_NAME} PRIVATE ${_FILESYSTEM_UTILS_DIR})
130168
if(NOT BUILD_WITH_STD_FILESYSTEM)
131169
target_compile_definitions(${TARGET_NAME} PRIVATE DISABLE_STD_FILESYSTEM)
132170
else()

src/common/filesystem_utils.cpp

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,40 +20,7 @@
2020
#define USE_FINAL_FS 0
2121

2222
#else
23-
// If the C++ macro is set to the version containing C++17, it must support
24-
// the final C++17 package
25-
#if __cplusplus >= 201703L
26-
#define USE_EXPERIMENTAL_FS 0
27-
#define USE_FINAL_FS 1
28-
29-
#elif defined(_MSC_VER) && _MSC_VER >= 1900
30-
31-
#if defined(_HAS_CXX17) && _HAS_CXX17
32-
// When MSC supports c++17 use <filesystem> package.
33-
#define USE_EXPERIMENTAL_FS 0
34-
#define USE_FINAL_FS 1
35-
#endif // !_HAS_CXX17
36-
37-
// Right now, GCC still only supports the experimental filesystem items starting in GCC 6
38-
#elif (__GNUC__ >= 6)
39-
#define USE_EXPERIMENTAL_FS 1
40-
#define USE_FINAL_FS 0
41-
42-
// If Clang, check for feature support
43-
#elif defined(__clang__) && (__cpp_lib_filesystem || __cpp_lib_experimental_filesystem)
44-
#if __cpp_lib_filesystem
45-
#define USE_EXPERIMENTAL_FS 0
46-
#define USE_FINAL_FS 1
47-
#else
48-
#define USE_EXPERIMENTAL_FS 1
49-
#define USE_FINAL_FS 0
50-
#endif
51-
52-
// If all above fails, fall back to standard C++ and OS-specific items
53-
#else
54-
#define USE_EXPERIMENTAL_FS 0
55-
#define USE_FINAL_FS 0
56-
#endif
23+
#include "stdfs_conditions.h"
5724
#endif
5825

5926
#if USE_FINAL_FS == 1

src/common/stdfs_conditions.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) 2017-2021 The Khronos Group Inc.
2+
// Copyright (c) 2017 Valve Corporation
3+
// Copyright (c) 2017 LunarG, Inc.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0 OR MIT
6+
7+
#ifndef _STDFS_CONDITIONS_H
8+
#define _STDFS_CONDITIONS_H
9+
10+
// If the C++ macro is set to the version containing C++17, it must support
11+
// the final C++17 package
12+
#if __cplusplus >= 201703L
13+
#define USE_EXPERIMENTAL_FS 0
14+
#define USE_FINAL_FS 1
15+
16+
#elif defined(_MSC_VER) && _MSC_VER >= 1900
17+
18+
#if defined(_HAS_CXX17) && _HAS_CXX17
19+
// When MSC supports c++17 use <filesystem> package.
20+
#define USE_EXPERIMENTAL_FS 0
21+
#define USE_FINAL_FS 1
22+
#endif // !_HAS_CXX17
23+
24+
// GCC supports the experimental filesystem items starting in GCC 6
25+
#elif (__GNUC__ >= 6)
26+
#define USE_EXPERIMENTAL_FS 1
27+
#define USE_FINAL_FS 0
28+
29+
// If Clang, check for feature support
30+
#elif defined(__clang__) && (__cpp_lib_filesystem || __cpp_lib_experimental_filesystem)
31+
#if __cpp_lib_filesystem
32+
#define USE_EXPERIMENTAL_FS 0
33+
#define USE_FINAL_FS 1
34+
#else
35+
#define USE_EXPERIMENTAL_FS 1
36+
#define USE_FINAL_FS 0
37+
#endif
38+
39+
// If all above fails, fall back to standard C++ and OS-specific items
40+
#else
41+
#define USE_EXPERIMENTAL_FS 0
42+
#define USE_FINAL_FS 0
43+
#endif
44+
45+
#endif // !_STDFS_CONDITIONS_H

0 commit comments

Comments
 (0)