From 8fe802354223c8bbbdec78000d650e424f23ee77 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Wed, 11 Jan 2023 23:48:37 +0000 Subject: [PATCH] Create save and config directories If a config directory did not exist, the ini file was not saved at all. Only implemented for targets that support `std::filesystem` or `std::experimental::filesystem`. These are all the targets except nxdk and iOS (only supported on iOS 13+). --- CMake/functions/set_relative_file_macro.cmake | 2 +- Source/CMakeLists.txt | 14 +++++++++++ Source/mpq/mpq_writer.cpp | 10 ++++++++ Source/options.cpp | 10 ++++++++ Source/utils/stdcompat/filesystem.hpp | 24 +++++++++++++++++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 Source/utils/stdcompat/filesystem.hpp diff --git a/CMake/functions/set_relative_file_macro.cmake b/CMake/functions/set_relative_file_macro.cmake index 07eabc055..a49503ea2 100644 --- a/CMake/functions/set_relative_file_macro.cmake +++ b/CMake/functions/set_relative_file_macro.cmake @@ -1,7 +1,7 @@ # Sets the __FILE__ macro value to be relative to CMAKE_SOURCE_DIR. function(set_relative_file_macro TARGET) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - if((CMAKE_CXX_COMPILER_ID MATCHES "CLANG" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12) + if((CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12) OR (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8)) target_compile_options(${TARGET} PUBLIC "-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=") else() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 53f97f129..f36a33212 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -288,3 +288,17 @@ foreach(path ${DEVILUTIONX_PLATFORM_SUBDIRECTORIES}) endforeach() target_link_libraries(libdevilutionx PUBLIC ${DEVILUTIONX_PLATFORM_LINK_LIBRARIES}) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9 AND NOT AMIGA) + target_link_libraries(libdevilutionx PUBLIC stdc++fs) + endif() +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Assumes libc++ (clang) is used rather than libstdc++ (gcc). + # This is not always true but these are ancient clang versions anyway. + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7) + target_link_libraries(libdevilutionx PUBLIC c++experimental) + elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9) + target_link_libraries(libdevilutionx PUBLIC c++fs) + endif() +endif() diff --git a/Source/mpq/mpq_writer.cpp b/Source/mpq/mpq_writer.cpp index 1d5262371..96bb63d24 100644 --- a/Source/mpq/mpq_writer.cpp +++ b/Source/mpq/mpq_writer.cpp @@ -13,6 +13,7 @@ #include "utils/file_util.h" #include "utils/language.h" #include "utils/log.hpp" +#include "utils/stdcompat/filesystem.hpp" #include "utils/str_cat.hpp" namespace devilution { @@ -87,6 +88,15 @@ bool IsUnallocatedBlock(const MpqBlockEntry *block) MpqWriter::MpqWriter(const char *path) { +#ifdef DVL_HAS_FILESYSTEM + { + std::error_code error; + std::filesystem::create_directories(std::filesystem::path(path).parent_path(), error); + if (error) { + LogError("failed to create directory: {}", error.message()); + } + } +#endif LogVerbose("Opening {}", path); std::string error; bool exists = FileExists(path); diff --git a/Source/options.cpp b/Source/options.cpp index b1392fafa..17a62b975 100644 --- a/Source/options.cpp +++ b/Source/options.cpp @@ -31,6 +31,7 @@ #include "utils/log.hpp" #include "utils/paths.h" #include "utils/stdcompat/algorithm.hpp" +#include "utils/stdcompat/filesystem.hpp" #include "utils/str_cat.hpp" #include "utils/str_split.hpp" #include "utils/utf8.hpp" @@ -234,6 +235,15 @@ void SaveIni() { if (!IniChanged) return; +#ifdef DVL_HAS_FILESYSTEM + { + std::error_code error; + std::filesystem::create_directories(paths::ConfigPath(), error); + if (error) { + LogError("failed to create directory: {}", error.message()); + } + } +#endif auto iniPath = GetIniPath(); auto stream = CreateFileStream(iniPath.c_str(), std::fstream::out | std::fstream::trunc | std::fstream::binary); GetIni().Save(*stream, true); diff --git a/Source/utils/stdcompat/filesystem.hpp b/Source/utils/stdcompat/filesystem.hpp new file mode 100644 index 000000000..938f029f7 --- /dev/null +++ b/Source/utils/stdcompat/filesystem.hpp @@ -0,0 +1,24 @@ +#pragma once + +#if defined(__APPLE__) +#include +#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500) \ + || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000) +#define DVL_NO_FILESYSTEM +#endif +#elif defined(NXDK) || (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) +#define DVL_NO_FILESYSTEM +#endif + +#ifndef DVL_NO_FILESYSTEM +#if defined(__has_include) +#if __has_include() +#define DVL_HAS_FILESYSTEM +#include // IWYU pragma: export +#elif __has_include() +#define DVL_HAS_FILESYSTEM +#include // IWYU pragma: export +#define filesystem experimental::filesystem +#endif +#endif +#endif