Skip to content

Commit 5b995d1

Browse files
committed
Autodetect std::filesystem support
1 parent 8c43405 commit 5b995d1

File tree

5 files changed

+88
-13
lines changed

5 files changed

+88
-13
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ endfunction()
4545

4646
find_package(Threads MODULE REQUIRED)
4747

48-
find_package(pegtl 3.0.0 QUIET CONFIG)
48+
find_package(pegtl 3.0.1 QUIET CONFIG)
4949
if(NOT pegtl_FOUND)
5050
# If a compatible version of PEGTL is not already installed, build and install it from the submodule directory.
5151
set(PEGTL_BUILD_TESTS OFF CACHE BOOL "Disable PEGTL tests")

cmake/test_filesystem.cpp.in

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// This is a dummy program that just needs to compile and link to tell us if
2+
// the C++17 std::filesystem API is available. Use CMake's configure_file
3+
// command to replace the FILESYSTEM_HEADER and FILESYSTEM_NAMESPACE tokens
4+
// for each combination of headers and namespaces which we want to pass to the
5+
// CMake try_compile command.
6+
7+
#include <@FILESYSTEM_HEADER@>
8+
9+
int main()
10+
{
11+
try
12+
{
13+
throw @FILESYSTEM_NAMESPACE@::filesystem_error("instantiate one to make sure it links",
14+
std::make_error_code(std::errc::function_not_supported));
15+
}
16+
catch (const @FILESYSTEM_NAMESPACE@::filesystem_error& error)
17+
{
18+
return -1;
19+
}
20+
21+
return !@FILESYSTEM_NAMESPACE@::temp_directory_path().is_absolute();
22+
}

src/CMakeLists.txt

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,55 @@ if(GRAPHQL_BUILD_SCHEMAGEN)
5050

5151
set(BOOST_COMPONENTS program_options)
5252
set(BOOST_LIBRARIES Boost::program_options)
53-
54-
if(NOT MSVC)
55-
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} filesystem)
56-
set(BOOST_LIBRARIES ${BOOST_LIBRARIES} Boost::filesystem)
57-
target_compile_options(schemagen PRIVATE -DUSE_BOOST_FILESYSTEM)
53+
54+
# Try compiling a test program with std::filesystem or one of its alternatives.
55+
function(check_filesystem_impl FILESYSTEM_HEADER FILESYSTEM_NAMESPACE OPTIONAL_LIBS OUT_RESULT)
56+
set(TEST_FILE "test_${OUT_RESULT}.cpp")
57+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/test_filesystem.cpp.in ${TEST_FILE} @ONLY)
58+
59+
try_compile(TEST_RESULT
60+
${CMAKE_CURRENT_BINARY_DIR}
61+
${CMAKE_CURRENT_BINARY_DIR}/${TEST_FILE}
62+
CXX_STANDARD 17)
63+
64+
if(NOT TEST_RESULT)
65+
# Retry with each of the optional libraries.
66+
foreach(OPTIONAL_LIB IN LISTS OPTIONAL_LIBS)
67+
try_compile(TEST_RESULT
68+
${CMAKE_CURRENT_BINARY_DIR}
69+
${CMAKE_CURRENT_BINARY_DIR}/${TEST_FILE}
70+
LINK_LIBRARIES ${OPTIONAL_LIB}
71+
CXX_STANDARD 17)
72+
73+
if(TEST_RESULT)
74+
# Looks like the optional library was required, go ahead and add it to the link options.
75+
target_link_libraries(schemagen PRIVATE ${OPTIONAL_LIB})
76+
break()
77+
endif()
78+
endforeach(OPTIONAL_LIB)
79+
endif()
80+
81+
set(${OUT_RESULT} ${TEST_RESULT} PARENT_SCOPE)
82+
endfunction(check_filesystem_impl)
83+
84+
# Try compiling a minimal program with each header/namespace, in order of preference:
85+
# C++17: #include <filesystem> // std::filesystem
86+
# Experimental C++17: #include <experimental/filesystem> // std::experimental::filesystem
87+
# Boost.Filesystem: #include <boost/filesystem.hpp> // boost::filesystem
88+
check_filesystem_impl("filesystem" "std::filesystem" "stdc++fs;c++fs" STD_FILESYTEM)
89+
if(STD_FILESYTEM)
90+
target_compile_definitions(schemagen PRIVATE USE_STD_FILESYSTEM)
91+
else()
92+
check_filesystem_impl("experimental/filesystem" "std::experimental::filesystem" "stdc++fs;c++fs" STD_EXPERIMENTAL_FILESYTEM)
93+
if(STD_EXPERIMENTAL_FILESYTEM)
94+
target_compile_definitions(schemagen PRIVATE USE_STD_EXPERIMENTAL_FILESYSTEM)
95+
else()
96+
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} filesystem)
97+
set(BOOST_LIBRARIES ${BOOST_LIBRARIES} Boost::filesystem)
98+
target_compile_definitions(schemagen PRIVATE USE_BOOST_FILESYSTEM)
99+
endif()
58100
endif()
59-
101+
60102
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
61103
target_link_libraries(schemagen PRIVATE ${BOOST_LIBRARIES})
62104

src/SchemaGenerator.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@
55

66
#include <boost/program_options.hpp>
77

8-
#ifdef USE_BOOST_FILESYSTEM
9-
#include <boost/filesystem.hpp>
10-
namespace fs = boost::filesystem;
8+
// clang-format off
9+
#ifdef USE_STD_FILESYSTEM
10+
#include <filesystem>
11+
namespace fs = std::filesystem;
1112
#else
12-
#include <filesystem>
13-
namespace fs = std::filesystem;
13+
#ifdef USE_STD_EXPERIMENTAL_FILESYSTEM
14+
#include <experimental/filesystem>
15+
namespace fs = std::experimental::filesystem;
16+
#else
17+
#ifdef USE_BOOST_FILESYSTEM
18+
#include <boost/filesystem.hpp>
19+
namespace fs = boost::filesystem;
20+
#else
21+
#error "No std::filesystem implementation defined"
22+
#endif
23+
#endif
1424
#endif
25+
// clang-format on
1526

1627
#include <cctype>
1728
#include <fstream>

0 commit comments

Comments
 (0)