From 82ade01381f1b1298f587e558ad12f6390e19dd0 Mon Sep 17 00:00:00 2001 From: Armel Thoni Date: Fri, 25 Jul 2025 12:24:45 +0200 Subject: [PATCH 1/2] Removing doc-related builds from Mac OS GHA --- .github/workflows/CI-macos.yaml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/CI-macos.yaml b/.github/workflows/CI-macos.yaml index ce51980a2..d9d04210e 100644 --- a/.github/workflows/CI-macos.yaml +++ b/.github/workflows/CI-macos.yaml @@ -23,12 +23,6 @@ jobs: gnuplot - name: Installation of pandoc uses: r-lib/actions/setup-pandoc@v2 - - name: Installation of latex - uses: teatimeguest/setup-texlive-action@v3 - with: - packages: | - scheme-full - bibtex - name: Checkout of source code uses: actions/checkout@v3 - name: Preparation @@ -36,7 +30,7 @@ jobs: echo "$(brew --prefix qt6)/bin" >> $GITHUB_PATH mkdir ./_build - name: Configuration - run: cmake .. -DCMAKE_PREFIX_PATH=$(brew --prefix qt6)/lib/cmake + run: cmake .. -DCMAKE_PREFIX_PATH=$(brew --prefix qt6)/lib/cmake -DOFBUILD_ENABLE_DOCS=OFF working-directory: ./_build - name: Build run: make -j 2 From 52d2d31c503cf31a71e68ae698a3a22c04dd666c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armel=20Th=C3=B6ni?= Date: Wed, 30 Jul 2025 15:11:14 +0200 Subject: [PATCH 2/2] Handling boost process v2 in Process * changed process implementation for boost > 1.85 (references OpenFLUID/openfluid#1328) --- .github/workflows/CI-windows.yaml | 2 +- CMake.in.cmake | 5 +- src/openfluid/utils/CMakeLists.txt | 21 +++- src/openfluid/utils/Process.cpp | 159 +++++++++++++++++++++++++++-- 4 files changed, 171 insertions(+), 16 deletions(-) diff --git a/.github/workflows/CI-windows.yaml b/.github/workflows/CI-windows.yaml index 277d57609..40c1eed67 100644 --- a/.github/workflows/CI-windows.yaml +++ b/.github/workflows/CI-windows.yaml @@ -25,7 +25,7 @@ jobs: release: false install: >- mingw-w64-x86_64-toolchain mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc-fortran - mingw-w64-x86_64-cmake mingw-w64-x86_64-doxygen + mingw-w64-x86_64-cmake mingw-w64-x86_64-doxygen make mingw-w64-x86_64-boost mingw-w64-x86_64-gdal mingw-w64-x86_64-curl-winssl mingw-w64-x86_64-qt5 mingw-w64-x86_64-openssl git p7zip mingw-w64-x86_64-gnuplot mingw-w64-x86_64-graphviz diff --git a/CMake.in.cmake b/CMake.in.cmake index 08b1db5bc..0123ee43a 100644 --- a/CMake.in.cmake +++ b/CMake.in.cmake @@ -1,7 +1,8 @@ # # Configuration file for CMakeLists.txt files # -# Author : Jean-Christophe FABRE +# Authors : Jean-Christophe FABRE +# Armel THÖNI # # This file is included by the main CMakeLists.txt file, and defines variables # to configure the build and install @@ -23,7 +24,7 @@ SET(OFBUILD_CUSTOM_CMAKE_VERSION "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}. SET(OPENFLUID_VERSION_MAJOR 2) SET(OPENFLUID_VERSION_MINOR 2) SET(OPENFLUID_VERSION_PATCH 1) -SET(OPENFLUID_VERSION_STATUS "alpha5") # example: SET(OPENFLUID_VERSION_STATUS "rc1") +SET(OPENFLUID_VERSION_STATUS "alpha6") # example: SET(OPENFLUID_VERSION_STATUS "rc1") SET(OPENFLUID_VERSION_FULL "${OPENFLUID_VERSION_MAJOR}.${OPENFLUID_VERSION_MINOR}.${OPENFLUID_VERSION_PATCH}") diff --git a/src/openfluid/utils/CMakeLists.txt b/src/openfluid/utils/CMakeLists.txt index 5ed248f7c..fc5586ad9 100644 --- a/src/openfluid/utils/CMakeLists.txt +++ b/src/openfluid/utils/CMakeLists.txt @@ -1,14 +1,26 @@ INCLUDE_DIRECTORIES(${GDAL_INCLUDE_DIR} ${CURL_INCLUDE_DIRS}) -# Hack for boost::process on Windows/MinGW only +SET(BOOST_COMPONENTS ) +SET(BOOST_LINK_LIBRARIES Boost::boost) +IF(Boost_VERSION_MINOR GREATER 85) + SET(BOOST_COMPONENTS ${BOOST_COMPONENTS} process) + SET(BOOST_LINK_LIBRARIES ${BOOST_LINK_LIBRARIES} Boost::process) +ENDIF() + + IF(MINGW) - FIND_PACKAGE(Boost REQUIRED filesystem) + SET(BOOST_COMPONENTS ${BOOST_COMPONENTS} filesystem system thread) + # Hack for boost::process on Windows/MinGW only IF(Boost_VERSION GREATER 107000) ADD_DEFINITIONS(-DBOOST_USE_WINDOWS_H -DWIN32_LEAN_AND_MEAN) ENDIF() + IF(Boost_VERSION_MINOR GREATER 85) + SET(BOOST_LINK_LIBRARIES ${BOOST_LINK_LIBRARIES} bcrypt) + ENDIF() ENDIF() - +FIND_PACKAGE(Boost REQUIRED ${BOOST_COMPONENTS}) +ADD_COMPILE_DEFINITIONS(Boost_VERSION_MINOR=${Boost_VERSION_MINOR}) SET(OPENFLUID_UTILS_CPP GDALHelpers.cpp Process.cpp @@ -46,12 +58,11 @@ TARGET_LINK_LIBRARIES(openfluid-utils openfluid-tools ${GDAL_LIBRARIES} ${CURL_LIBRARIES} - Boost::boost + ${BOOST_LINK_LIBRARIES} $<$:Boost::filesystem> $<$:ws2_32> # MinGW hack ) - INSTALL(TARGETS openfluid-utils RUNTIME DESTINATION ${OFBUILD_BIN_INSTALL_PATH} LIBRARY DESTINATION ${OFBUILD_LIB_INSTALL_PATH} diff --git a/src/openfluid/utils/Process.cpp b/src/openfluid/utils/Process.cpp index ee73480df..4159f3385 100644 --- a/src/openfluid/utils/Process.cpp +++ b/src/openfluid/utils/Process.cpp @@ -42,7 +42,21 @@ #include #include +#if (Boost_VERSION_MINOR > 85) && defined(OPENFLUID_OS_WINDOWS) +#include // FIXME check if useful or necessary, theorically useful to respect include order +#endif +#if (Boost_VERSION_MINOR > 85) +#include +#include +#include +#include +#include +#include +#include +#include +#else #include +#endif #include #include @@ -136,6 +150,107 @@ bool Process::run() try { +#if (Boost_VERSION_MINOR > 85) + std::ofstream StdOutFile; + std::ofstream StdErrFile; + std::string LineOut; + std::string LineErr; + std::unordered_map ProcessEnv; + boost::asio::io_context Ctx; + boost::asio::readable_pipe PipeOut{Ctx}; + boost::asio::readable_pipe PipeErr{Ctx}; + + bool SinkOutToFile = !m_Cmd.OutFile.empty(); + bool SinkErrToFile = !m_Cmd.ErrFile.empty(); + + // prepare environment + if (m_Env.Inherits) + { + for(const auto& InheritedVar : boost::process::v2::environment::current()) + { + ProcessEnv[InheritedVar.key().string()] = InheritedVar.value().string(); + } + } + + for (const auto& Var : m_Env.Vars) + { + ProcessEnv[Var.first] = Var.second; + } + // Hotfix for windows bug when work dir is empty + std::string WorkDir; + if (m_Cmd.WorkDir.empty()) + { + WorkDir = "."; // warning boost : If your path is relative, it may fail on posix, + //because the directory is changed before a call to execve. + } + else + { + WorkDir = m_Cmd.WorkDir; + } + + // boost::process::shell, <- not relevant in new system? + boost::process::v2::process Proc(Ctx, m_Cmd.Program, m_Cmd.Args, + boost::process::v2::process_stdio{nullptr, PipeOut, PipeErr}, + boost::process::v2::process_start_dir(WorkDir), + boost::process::v2::process_environment(ProcessEnv)); + + // if out is redirected, create out file + if (SinkOutToFile) + { + openfluid::tools::Path(openfluid::tools::Path(m_Cmd.OutFile).dirname()).makeDirectory(); + StdOutFile.open(m_Cmd.OutFile,std::ios::out); + } + + // if error is redirected, create error file + if (SinkErrToFile) + { + openfluid::tools::Path(openfluid::tools::Path(m_Cmd.ErrFile).dirname()).makeDirectory(); + StdErrFile.open(m_Cmd.ErrFile,std::ios::out); + } + + boost::system::error_code Ec; + boost::asio::read(PipeOut, boost::asio::dynamic_buffer(LineOut), Ec); + if (!Ec || (Ec == boost::asio::error::eof)) + { + std::cout << "Boost process reading error in out stream: " << Ec.message() << std::endl; + openfluid::utils::log::error("Process", "Boost process reading error in out stream"); + } + boost::asio::read(PipeErr, boost::asio::dynamic_buffer(LineErr), Ec); + if (!Ec || (Ec == boost::asio::error::eof)) + { + std::cout << "Boost process reading error in err stream: " << Ec.message() << std::endl; + openfluid::utils::log::error("Process", "Boost process reading error in err stream"); + } + + Proc.wait(); + for (const auto& L : openfluid::tools::split(LineOut, "\n")) + { + if (SinkOutToFile) + { + // if out is redirected, sink out lines in file + StdOutFile << L << "\n"; + } + else + { + m_OutLines.push_back(L); + } + } + + for (const auto& L : openfluid::tools::split(LineErr, "\n")) + { + if (SinkErrToFile) + { + // if out is redirected, sink out lines in file + StdErrFile << L << "\n"; + } + else + { + m_ErrLines.push_back(L); + } + } + + m_ExitCode = Proc.exit_code(); +#else boost::process::environment ProcessEnv; boost::process::ipstream StdOutStr; boost::process::ipstream StdErrStr; @@ -229,17 +344,12 @@ bool Process::run() BPC.wait(); m_ExitCode = BPC.exit_code(); +#endif } - catch(const boost::process::process_error& E) + catch(const std::exception& E) { m_ErrorMsg = std::string(E.what()); - openfluid::utils::log::error("Process", std::string("Boost process error: ")+E.what()); - return false; - } - catch(...) - { - // TODO for logging purposes - openfluid::utils::log::error("Process", "Boost process error"); + openfluid::utils::log::error("Process", std::string("Boost process error: ")+m_ErrorMsg); return false; } @@ -291,6 +401,38 @@ int Process::system(const std::string& Program, const std::vector& int Process::system(const Command& Cmd, const Environment& Env) { +#if (Boost_VERSION_MINOR > 85) + boost::asio::io_context Ctx; + std::unordered_map ProcessEnv; + // prepare environment + if (Env.Inherits) + { + for(const auto& InheritedVar : boost::process::v2::environment::current()) + { + ProcessEnv[InheritedVar.key().string()] = InheritedVar.value().string(); + } + } + + for (const auto& Var : Env.Vars) + { + ProcessEnv[Var.first] = Var.second; + } + // Hotfix for windows bug when work dir is empty + std::string WorkDir; + if (Cmd.WorkDir.empty()) + { + WorkDir = "."; // warning boost : If your path is relative, it may fail on posix, + //because the directory is changed before a call to execve. + } + else + { + WorkDir = Cmd.WorkDir; + } + boost::process::v2::process Proc(Ctx, Cmd.Program, Cmd.Args, + boost::process::v2::process_start_dir(WorkDir), + boost::process::v2::process_environment(ProcessEnv)); + return Proc.wait(); +#else boost::process::environment ProcessEnv; // prepare environment @@ -321,6 +463,7 @@ int Process::system(const Command& Cmd, const Environment& Env) boost::process::args = Cmd.Args, boost::process::start_dir = WorkDir, ProcessEnv); +#endif }