From 573e53ebfdc134fb0506160aed5d21a0c457b2b9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Mon, 29 Sep 2025 11:29:07 +0200 Subject: [PATCH] Ugly workarounds to not depend on std::filesystem #7131 --- src/ifcparse/IfcFile.cpp | 55 ++++++++++++++++++++++++++++++++------ src/ifcwrap/CMakeLists.txt | 4 +-- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/ifcparse/IfcFile.cpp b/src/ifcparse/IfcFile.cpp index be5632112f..25cd414c4c 100644 --- a/src/ifcparse/IfcFile.cpp +++ b/src/ifcparse/IfcFile.cpp @@ -6,6 +6,10 @@ #include #endif +#include +#include +#include + IfcParse::parse_context::~parse_context() { for (auto& t : tokens_) { std::visit([](auto& v) { @@ -570,23 +574,58 @@ IfcParse::IfcFile::~IfcFile() { } } -#include -#include +namespace { + // Utility functions for path handling in order not to rely on C++17's std::filesystem +#ifdef _WIN32 +#define stat_t struct _stat + inline int stat_(const char* p, stat_t* s) { return ::_stat(p, s); } +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & _S_IFDIR) != 0) +#endif +#ifndef S_ISREG +#define S_ISREG(m) (((m) & _S_IFREG) != 0) +#endif +#else + using stat_t = struct stat; + inline int stat_(const char* p, stat_t* s) { return ::stat(p, s); } +#endif + + inline bool path_exists_(const std::string& p, stat_t* out = nullptr) { + stat_t tmp; + stat_t* s = out ? out : &tmp; + return stat_(p.c_str(), s) == 0; + } + + inline bool path_is_directory_(const stat_t& s) { return S_ISDIR(s.st_mode); } + inline bool path_is_regular_file_(const stat_t& s) { return S_ISREG(s.st_mode); } + + inline std::string path_join_(const std::string& dir, const std::string& name) { + if (dir.empty()) return name; + const char last = dir.back(); + if (last == '/' || last == '\\') return dir + name; +#ifdef _WIN32 + const char sep = '\\'; +#else + const char sep = '/'; +#endif + return dir + sep + name; + } +} // namespace IfcParse::filetype IfcParse::guess_file_type(const std::string& fn) { - namespace fs = std::filesystem; - - if (!fs::exists(fn)) { + stat_t st{}; + if (!path_exists_(fn, &st)) { // @todo this is just weird, but for consistency with earlier behaviour // for now the only intent for this function is to auto-detect RocksDB return FT_IFCSPF; } - if (fs::is_directory(fn)) { + if (path_is_directory_(st)) { // Typical RocksDB file to look for - auto currentFile = fs::path(fn) / "CURRENT"; + auto currentFile = path_join_(fn, "CURRENT"); + stat_t cst{}; - if (!fs::exists(currentFile) || !fs::is_regular_file(currentFile)) { + if (!path_exists_(currentFile, &cst) || !path_is_regular_file_(cst)) { return FT_UNKNOWN; } diff --git a/src/ifcwrap/CMakeLists.txt b/src/ifcwrap/CMakeLists.txt index 2cca5f764d..71346ec27b 100644 --- a/src/ifcwrap/CMakeLists.txt +++ b/src/ifcwrap/CMakeLists.txt @@ -88,9 +88,9 @@ swig_add_library(ifcopenshell_wrapper LANGUAGE python SOURCES IfcPython.i) SET_PROPERTY(TARGET ${SWIG_MODULE_ifcopenshell_wrapper_REAL_NAME} PROPERTY SWIG_DEPENDS ${IFCOPENSHELL_LIBRARIES}) if("$ENV{LDFLAGS}" MATCHES ".undefined.suppress") # On osx there is some state in the python dylib. With `-Wl,undefined,suppress` we can ignore the missing symbols at compile time. -SWIG_LINK_LIBRARIES(ifcopenshell_wrapper IfcGeom IfcParse Serializers ${kernel_libraries} geometry_serializer ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${LIBSVGFILL}) +SWIG_LINK_LIBRARIES(ifcopenshell_wrapper ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${LIBSVGFILL}) else() -SWIG_LINK_LIBRARIES(ifcopenshell_wrapper IfcGeom IfcParse Serializers ${kernel_libraries} geometry_serializer ${PYTHON_LIBRARIES} ${LIBSVGFILL}) +SWIG_LINK_LIBRARIES(ifcopenshell_wrapper ${IFCOPENSHELL_LIBRARIES} ${PYTHON_LIBRARIES} ${LIBSVGFILL}) endif() if ((NOT WIN32) AND BUILD_SHARED_LIBS) SET_INSTALL_RPATHS(${SWIG_MODULE_ifcopenshell_wrapper_REAL_NAME} "${IFCDIRS};${OCC_LIBRARY_DIR}")