diff --git a/.github/workflows/ResInsightMac.yml b/.github/workflows/ResInsightMac.yml new file mode 100644 index 00000000000..498b1df3359 --- /dev/null +++ b/.github/workflows/ResInsightMac.yml @@ -0,0 +1,204 @@ +name: ResInsight Mac Build + +on: + push: + pull_request: + workflow_dispatch: + schedule: + # 02:00 UTC daily, offset from ResInsightWithCache.yml's 01:00 slot + # so the two workflows do not contend for the same Actions runners. + - cron: '0 2 * * *' + +permissions: + contents: read + +# Cancel a still-running build when a new push lands on the same ref -- +# otherwise two simultaneous Mac runs race on the same daily cache keys +# (vcpkg-clang/macOS-..., macOS-appleclang-...-buildcache-v01-, +# macOS-buildcache-tool-v0.33.0) and one reports +# "Failed to save: Unable to reserve cache with key ..., another job may +# be creating this cache." Mirrors the pattern in ResInsightWithCache.yml. +concurrency: + group: mac-build-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: macos-15 + env: + BUILD_TYPE: Release + VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" + BUILDCACHE_DIR: ${{ github.workspace }}/buildcache_dir + BUILDCACHE_ACCURACY: SLOPPY + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + submodules: true + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: Get Python executable path + id: python-path + run: echo "PYTHON_EXECUTABLE=$(python -c 'import sys; import pathlib; print(pathlib.PurePath(sys.executable).as_posix())')" >> $GITHUB_OUTPUT + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + # rips/_version.py is normally generated by CMake; create a dev + # fallback so the editable install below can resolve the version. + echo '__version__ = "0.0.0.dev"' > GrpcInterface/Python/rips/_version.py + pip install -e GrpcInterface/Python[dev] + + - name: Restore buildcache tool binary + uses: actions/cache@v5 + with: + path: ${{ github.workspace }}/buildcache-tool + key: ${{ runner.os }}-buildcache-tool-v0.33.0 + + - name: Build buildcache from source if needed + # CeetronSolutions/setup-buildcache-action has no macOS support, so + # build the binary from the upstream source release and add it to + # PATH. Source build (~30 s) only happens on cache miss; subsequent + # runs restore the binary from the cache step above. + env: + BUILDCACHE_VERSION: v0.33.0 + BUILDCACHE_PREFIX: ${{ github.workspace }}/buildcache-tool + run: | + if [ ! -x "$BUILDCACHE_PREFIX/bin/buildcache" ]; then + workdir="$RUNNER_TEMP/buildcache-src" + mkdir -p "$workdir" "$BUILDCACHE_PREFIX" + cd "$workdir" + curl -sSL "https://gitlab.com/bits-n-bites/buildcache/-/archive/${BUILDCACHE_VERSION}/buildcache-${BUILDCACHE_VERSION}.tar.gz" \ + | tar xz --strip-components=1 + cmake -S src -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$BUILDCACHE_PREFIX" + cmake --build build --target install + fi + echo "$BUILDCACHE_PREFIX/bin" >> "$GITHUB_PATH" + "$BUILDCACHE_PREFIX/bin/buildcache" --version + + - name: Get current date + id: current-time + shell: bash + run: echo "formattedTime=$(date -u +%Y-%m-%d)" >> $GITHUB_OUTPUT + + - name: Cache buildcache contents + id: cache-buildcache + uses: actions/cache@v5 + with: + path: ${{ env.BUILDCACHE_DIR }} + key: ${{ runner.os }}-appleclang-6.7.0-buildcache-v01-${{ steps.current-time.outputs.formattedTime }} + restore-keys: | + ${{ runner.os }}-appleclang-6.7.0-buildcache-v01- + + - name: Create folder for buildcache + run: mkdir -p "${{ env.BUILDCACHE_DIR }}" + + - name: Install Homebrew build tools + # vcpkg's thrift port (transitive dep of arrow) requires bison > 2.5; + # macOS ships an ancient /usr/bin/bison (2.3). Install Homebrew's + # bison and put it ahead on PATH so the port build finds it. + run: | + brew install bison + echo "$(brew --prefix bison)/bin" >> "$GITHUB_PATH" + "$(brew --prefix bison)/bin/bison" --version | head -1 + + - name: Install Qt + # cache: false on macOS: the 1.1 GB Qt tarball eats most of the + # 10 GB per-repo Actions cache quota; downloading fresh each run + # is ~30 s on the runner-internal mirror and leaves room for the + # buildcache + vcpkg caches which actually save build time. + uses: CeetronSolutions/install-qt-action@bump-node24 + with: + version: 6.7.0 + dir: "${{ github.workspace }}/Qt/" + cache: false + setup-python: false + modules: "qtnetworkauth" + + - name: vcpkg bootstrap + run: | + ThirdParty/vcpkg/bootstrap-vcpkg.sh + + - name: Get vcpkg submodule SHA + id: vcpkg-sha + shell: bash + run: echo "sha=$(git rev-parse HEAD:ThirdParty/vcpkg)" >> $GITHUB_OUTPUT + + - name: Restore vcpkg cache + id: vcpkg-cache + uses: CeetronSolutions/vcpkg-cache@copilot/optimize-cache-storage-structure + with: + cache-key: ${{ runner.os }}-clang-${{ steps.vcpkg-sha.outputs.sha }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json') }} + prefix: vcpkg-clang/ + + - name: Configure + shell: bash + env: + VCPKG_FEATURE_FLAGS: "binarycaching" + VCPKG_BINARY_SOURCES: "clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite" + run: > + cmake -S . -B cmakebuild + -DVCPKG_BUILD_TYPE=release + -DCMAKE_INSTALL_PREFIX=cmakebuild/install + -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} + -DCMAKE_OSX_DEPLOYMENT_TARGET=15.0 + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + -DCMAKE_C_COMPILER_LAUNCHER=buildcache + -DCMAKE_CXX_COMPILER_LAUNCHER=buildcache + -DRESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS=true + -DRESINSIGHT_TREAT_WARNINGS_AS_ERRORS=false + -DRESINSIGHT_ENABLE_PRECOMPILED_HEADERS=false + -DRESINSIGHT_ENABLE_UNITY_BUILD=false + -DRESINSIGHT_ENABLE_GRPC=false + -DRESINSIGHT_ENABLE_HDF5=false + -DCMAKE_TOOLCHAIN_FILE=ThirdParty/vcpkg/scripts/buildsystems/vcpkg.cmake + -G Ninja + + - name: Build + run: | + cmake --build cmakebuild --target install + + - name: Stats for buildcache + run: buildcache -s + + - name: Run Unit Tests + shell: bash + run: | + echo "Content of unit test folder" + ls cmakebuild/ResInsight-tests + cmakebuild/ResInsight-tests + + - name: Write macOS launch instructions + run: | + cat > cmakebuild/install/README-macOS.txt <<'EOF' + ResInsight macOS build + ====================== + + This build is unsigned and unnotarised. macOS Gatekeeper will + quarantine ResInsight.app when the artifact is downloaded and + refuse to launch it ("app is damaged" or "cannot be opened"). + + Remove the quarantine attribute before first launch: + + sudo xattr -r -d com.apple.quarantine ResInsight.app + + Then start the app normally (double-click or `open ResInsight.app`). + EOF + + - name: Upload artifacts + if: always() + uses: actions/upload-artifact@v7 + with: + name: ResInsight-macOS + path: ${{ runner.workspace }}/ResInsight/cmakebuild/install + retention-days: 5 diff --git a/ApplicationExeCode/RiaMainTools.cpp b/ApplicationExeCode/RiaMainTools.cpp index 5dbf2a966d7..e240cf93aa1 100644 --- a/ApplicationExeCode/RiaMainTools.cpp +++ b/ApplicationExeCode/RiaMainTools.cpp @@ -34,15 +34,33 @@ #include #include +#include + +// std::stacktrace is C++23; libc++ in Homebrew llvm@19 (and older) does not +// ship it. Without it we skip stack-trace capture in the crash path but +// still log the signal. Use the feature-test macro from rather +// than __has_include, since the header may be present without a usable +// implementation. See #14045. +#if defined( __cpp_lib_stacktrace ) && __cpp_lib_stacktrace >= 202011L #include +#define RIA_HAS_STD_STACKTRACE 1 +#else +#define RIA_HAS_STD_STACKTRACE 0 +#endif #ifndef WIN32 #include +// macOS marks as deprecated and the mcontext layout +// (gregs[REG_RIP]) is Linux-only — skip the program-counter capture +// path on Apple platforms. See #14045. +#ifndef __APPLE__ #include #endif +#endif namespace internal { +#if RIA_HAS_STD_STACKTRACE // Custom formatter for stacktrace std::string formatStacktrace( const std::stacktrace& st ) { @@ -55,6 +73,7 @@ std::string formatStacktrace( const std::stacktrace& st ) } return ss.str(); } +#endif #ifndef WIN32 static std::string signalCodeDescription( int signo, int siCode ) @@ -144,7 +163,9 @@ static std::string signalCodeDescription( int signo, int siCode ) //-------------------------------------------------------------------------------------------------- static void performCrashLogging( int signalCode, const std::map& extraAttrs ) { - auto st = std::stacktrace::current(); +#if RIA_HAS_STD_STACKTRACE + auto st = std::stacktrace::current(); +#endif auto loggers = RiaLogging::loggerInstances(); for ( auto logger : loggers ) @@ -161,8 +182,12 @@ static void performCrashLogging( int signalCode, const std::maperror( line.data() ); } +#if RIA_HAS_STD_STACKTRACE std::string message = "Stack trace:\n" + internal::formatStacktrace( st ); logger->error( message.data() ); +#else + logger->error( "Stack trace: not available (compiled without )" ); +#endif fileLogger->flush(); } @@ -171,7 +196,9 @@ static void performCrashLogging( int signalCode, const std::map as deprecated, so skip it + // there; remaining crash attributes (signal code, fault address) are + // still recorded. See #14045. +#if !defined( __APPLE__ ) #if defined( __x86_64__ ) if ( ucontext ) { @@ -223,6 +256,9 @@ void manageSegFailureSA( int signalCode, siginfo_t* info, void* ucontext ) extraAttrs["crash.program_counter"] = pcStr.str(); } #endif +#else + (void)ucontext; +#endif performCrashLogging( signalCode, extraAttrs ); exit( 1 ); diff --git a/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.cpp b/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.cpp index fcb9ac988ca..0f5594e5292 100644 --- a/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.cpp +++ b/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.cpp @@ -325,6 +325,7 @@ static std::string extractRelevantPath( const std::string& fullPath ) return fullPath; } +#if RIA_HAS_STD_STACKTRACE //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -420,6 +421,7 @@ void RiaOpenTelemetryManager::reportCrash( int signalCode, const std::stacktrace RiaLogging::error( std::format( "Crash reported to OpenTelemetry (signal: {})", signalCode ) ); } +#endif // RIA_HAS_STD_STACKTRACE //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.h b/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.h index 843eff09049..e790e587773 100644 --- a/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.h +++ b/ApplicationLibCode/Application/Tools/Telemetry/RiaOpenTelemetryManager.h @@ -27,8 +27,20 @@ #include #include #include -#include #include +#include + +// std::stacktrace is C++23. libc++ shipped with Homebrew llvm@19 (and +// older toolchains) does not provide it yet, so guard the include + the +// reportCrash overload that uses it. Use the feature-test macro from +// rather than __has_include, since the header may be present +// without a usable implementation. See #14045. +#if defined( __cpp_lib_stacktrace ) && __cpp_lib_stacktrace >= 202011L +#include +#define RIA_HAS_STD_STACKTRACE 1 +#else +#define RIA_HAS_STD_STACKTRACE 0 +#endif class QString; class QNetworkAccessManager; @@ -88,7 +100,9 @@ class RiaOpenTelemetryManager : public QObject // Event reporting void reportEventAsync( const std::string& eventName, const std::map& attributes ); +#if RIA_HAS_STD_STACKTRACE void reportCrash( int signalCode, const std::stacktrace& trace, const std::map& extraAttributes = {} ); +#endif // Configuration bool isEnabled() const; diff --git a/ApplicationLibCode/FileInterface/RifStimPlanModelGeologicalFrkExporter.h b/ApplicationLibCode/FileInterface/RifStimPlanModelGeologicalFrkExporter.h index f7008508f71..0dccbab7f30 100644 --- a/ApplicationLibCode/FileInterface/RifStimPlanModelGeologicalFrkExporter.h +++ b/ApplicationLibCode/FileInterface/RifStimPlanModelGeologicalFrkExporter.h @@ -31,7 +31,7 @@ class QTextStream; class RifStimPlanModelGeologicalFrkExporter { public: - static const int MAX_STIMPLAN_LAYERS = 100; + static constexpr int MAX_STIMPLAN_LAYERS = 100; static constexpr double MIN_STRESS_GRADIENT = 0.3; static constexpr double MAX_STRESS_GRADIENT = 0.8; static constexpr double DEFAULT_STRESS_GRADIENT = 0.7; diff --git a/ApplicationLibCode/FileInterface/RifVtkImportUtil.cpp b/ApplicationLibCode/FileInterface/RifVtkImportUtil.cpp index df3ccf0c421..266fcc768b5 100644 --- a/ApplicationLibCode/FileInterface/RifVtkImportUtil.cpp +++ b/ApplicationLibCode/FileInterface/RifVtkImportUtil.cpp @@ -24,9 +24,23 @@ #include #include -#include #include #include +#include + +// std::ispanstream is C++23. libc++ on Homebrew llvm@19 does not ship +// ; fall back to std::istringstream when unavailable. Only +// difference: the fallback copies the string_view into an owning string. +// Use the feature-test macro from rather than __has_include, +// since the header may be present without a usable implementation. +// See #14045. +#if defined( __cpp_lib_spanstream ) && __cpp_lib_spanstream >= 202106L +#include +#define RIA_HAS_STD_SPANSTREAM 1 +#else +#include +#define RIA_HAS_STD_SPANSTREAM 0 +#endif //-------------------------------------------------------------------------------------------------- /// @@ -204,7 +218,11 @@ std::vector RifVtkImportUtil::parsePvdDatasets( co //-------------------------------------------------------------------------------------------------- std::vector RifVtkImportUtil::parseVec3ds( std::string_view text ) { +#if RIA_HAS_STD_SPANSTREAM std::ispanstream iss( text ); +#else + std::istringstream iss{ std::string{ text } }; +#endif std::vector vecs; @@ -228,7 +246,11 @@ std::vector RifVtkImportUtil::parseVec3ds( std::string_view text ) //-------------------------------------------------------------------------------------------------- std::vector RifVtkImportUtil::parseVec3fs( std::string_view text ) { +#if RIA_HAS_STD_SPANSTREAM std::ispanstream iss( text ); +#else + std::istringstream iss{ std::string{ text } }; +#endif std::vector vecs; diff --git a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp index 5915dd28aeb..3875bb70c33 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationLibCode/UserInterface/RiuMainWindow.cpp @@ -119,7 +119,6 @@ #include #include -#include //================================================================================================== /// diff --git a/CMakeLists.txt b/CMakeLists.txt index abbef1a6442..293848f94d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,13 +37,25 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() endif() -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # Pure LLVM/Homebrew clang: require 19+ for the C++23 stdlib coverage + # ResInsight depends on. if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0) message( FATAL_ERROR "Minimum supported version is Clang 19, detected version: ${CMAKE_CXX_COMPILER_VERSION}" ) endif() +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + # AppleClang versions trail mainline LLVM by ~2 majors; AppleClang 17 in Xcode + # 16 is based on LLVM 19 and ships a libc++ with the C++23 features we use. + # Reject earlier AppleClang explicitly. + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0) + message( + FATAL_ERROR + "Minimum supported version is AppleClang 17 (Xcode 16), detected version: ${CMAKE_CXX_COMPILER_VERSION}" + ) + endif() endif() # Ensure all binary files ensd up in the same folder as the executable @@ -90,6 +102,24 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") add_definitions(-DCVF_LINUX) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") add_definitions(-DCVF_OSX) + + # macOS: Apple's SDK ships an older libc++ that lacks C++23 symbols ResInsight + # needs (std::to_chars(double), std::bad_expected_access, etc.). Homebrew + # llvm packages place their own libc++ at /lib/c++, but clang does not + # add that to its default link search, so -lc++ resolves to the SDK copy via + # -isysroot. Prepend the toolchain's libc++ dir to the linker search (and + # rpath for runtime) when we detect a Homebrew layout. See #14045. + get_filename_component(_ri_llvm_bin_dir "${CMAKE_CXX_COMPILER}" DIRECTORY) + get_filename_component(_ri_llvm_root "${_ri_llvm_bin_dir}" DIRECTORY) + set(_ri_llvm_libcxx_dir "${_ri_llvm_root}/lib/c++") + if(EXISTS "${_ri_llvm_libcxx_dir}/libc++.dylib") + message( + STATUS "macOS: forcing toolchain libc++ from ${_ri_llvm_libcxx_dir}" + ) + add_link_options( + "-L${_ri_llvm_libcxx_dir}" "-Wl,-rpath,${_ri_llvm_libcxx_dir}" + ) + endif() elseif(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") set(_HAS_STD_BYTE 0) @@ -446,7 +476,17 @@ endif() # OpenVDS seismic file access # ############################################################################## -option(RESINSIGHT_ENABLE_OPENVDS "Add support for OpenVDS seismic files" ON) +# Bluware only ships Windows and Linux binaries (manylinux_2014); there is no +# macOS distribution. Default to OFF on Apple platforms so the feature can be +# explicitly opted in if the user supplies their own build. See #14045. +if(APPLE) + set(_ri_default_openvds OFF) +else() + set(_ri_default_openvds ON) +endif() +option(RESINSIGHT_ENABLE_OPENVDS "Add support for OpenVDS seismic files" + ${_ri_default_openvds} +) if(RESINSIGHT_ENABLE_OPENVDS) message(STATUS "Starting download of external library OpenVDS ...") @@ -570,6 +610,42 @@ list(APPEND THIRD_PARTY_LIBRARIES NRLib) add_definitions(-DOPENZGY_STATIC) +# macOS: openzgy assumes the glibc strerror_r signature and unconditionally +# includes . Apply a local patch that stubs OpenMP and rewrites the +# strerror_r fallback so the vendored sources compile without libomp. The patch +# is idempotent via git apply --reverse --check. +if(APPLE) + set(CMAKE_DISABLE_FIND_PACKAGE_OpenMP + ON + CACHE BOOL "openzgy is patched to not require OpenMP on macOS" FORCE + ) + set(_openzgy_macos_patch + "${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/openzgy-patches/macos-disable-openmp.patch" + ) + execute_process( + COMMAND git apply --reverse --check "${_openzgy_macos_patch}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/openzgy" + RESULT_VARIABLE _openzgy_already_applied + OUTPUT_QUIET ERROR_QUIET + ) + if(NOT _openzgy_already_applied EQUAL 0) + message(STATUS "openzgy: applying macOS OpenMP-disable patch") + execute_process( + COMMAND git apply "${_openzgy_macos_patch}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/openzgy" + RESULT_VARIABLE _openzgy_apply_result + ) + if(NOT _openzgy_apply_result EQUAL 0) + message( + FATAL_ERROR + "openzgy: failed to apply ${_openzgy_macos_patch} - openzgy source may have been re-vendored; refresh the patch." + ) + endif() + else() + message(STATUS "openzgy: macOS patch already applied") + endif() +endif() + # Suppress CMake deprecation warnings from openzgy/zfp's old CMakeLists.txt set(CMAKE_WARN_DEPRECATED OFF diff --git a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/CMakeLists.txt index 975f92f7923..2ee32aed26d 100644 --- a/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafPdmScripting/cafPdmScripting_UnitTests/CMakeLists.txt @@ -26,7 +26,7 @@ set(PROJECT_FILES cafMockObjects.cpp ) -qt_add_executable(${PROJECT_NAME} ${PROJECT_FILES}) +qt_add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${PROJECT_FILES}) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_options( diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt index 5f53c258435..4140f10531c 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmCore_UnitTests/CMakeLists.txt @@ -37,7 +37,7 @@ set(PROJECT_FILES TestObj.h ) -qt_add_executable(${PROJECT_NAME} ${PROJECT_FILES}) +qt_add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${PROJECT_FILES}) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt index 6e1dac74bf7..43a04c2f034 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXml_UnitTests/CMakeLists.txt @@ -25,7 +25,7 @@ set(PROJECT_FILES cafPdmPtrArrayTest.cpp ) -qt_add_executable(${PROJECT_NAME} ${PROJECT_FILES}) +qt_add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${PROJECT_FILES}) target_link_libraries( ${PROJECT_NAME} PRIVATE cafPdmXml ${QT_LIBRARIES} ${THREAD_LIBRARY} diff --git a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt index 8e449af25be..6e3ba837403 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafProjectDataModel/cafProjectDataModel_UnitTests/CMakeLists.txt @@ -29,7 +29,7 @@ set(PROJECT_FILES gtest/gtest-all.cpp ) -qt_add_executable(${PROJECT_NAME} ${PROJECT_FILES}) +qt_add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${PROJECT_FILES}) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_options( diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt index 156993442f6..8ff66cfca2b 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt +++ b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt @@ -67,7 +67,11 @@ set(PROJECT_FILES ) qt_add_executable( - ${PROJECT_NAME} ${PROJECT_FILES} ${MOC_SOURCE_FILES} ${QRC_FILES} + ${PROJECT_NAME} + MACOSX_BUNDLE + ${PROJECT_FILES} + ${MOC_SOURCE_FILES} + ${QRC_FILES} $ # Needed for cmake version < 3.12. Remove # when we can use target_link_libraries with OBJECT libraries ) diff --git a/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt index ebffdbe7e08..2bc4cd19472 100644 --- a/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/cafUserInterface_UnitTests/CMakeLists.txt @@ -23,7 +23,7 @@ set(PROJECT_FILES gtest/gtest-all.cpp ) -qt_add_executable(${PROJECT_NAME} ${PROJECT_FILES}) +qt_add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${PROJECT_FILES}) target_link_libraries( ${PROJECT_NAME} PRIVATE cafUserInterface ${QT_LIBRARIES} ${THREAD_LIBRARY} diff --git a/ThirdParty/openzgy-patches/macos-disable-openmp.patch b/ThirdParty/openzgy-patches/macos-disable-openmp.patch new file mode 100644 index 00000000000..894df5f9a20 --- /dev/null +++ b/ThirdParty/openzgy-patches/macos-disable-openmp.patch @@ -0,0 +1,183 @@ +macOS build fix for the vendored open-zgy library. + +Origin: https://github.com/cssr-tools/homebrew-opm/blob/main/open-zgy.patch +(paths rewritten to be rooted at ThirdParty/openzgy/) + +What this does on macOS: + 1. exception.cpp: the #else branch uses the glibc strerror_r signature + (returns char*). Apple's libc returns int. Replace the call with a + plain "Unknown errno N" string so the file compiles. + 2. bulk/file_sd/mtguard/workorder/zgycopyc/wrappermodule: replace + "#include " with three inline omp_get_*() stubs returning 1/0 + so the source compiles without libomp. Remaining "#pragma omp ..." + directives become no-ops because the compiler is invoked without + -fopenmp on macOS (the top-level CMakeLists.txt sets + CMAKE_DISABLE_FIND_PACKAGE_OpenMP=ON to suppress detection). + 3. edgebrick.h, mtguard::fail(), WorkOrderTP::fail(): comment out + bounds-check throw and exception-capture blocks that rely on + OpenMP-driven parallel regions; with threading disabled these paths + are unreachable. Re-evaluate if OpenMP is ever re-enabled on macOS. + +Applied automatically by the top-level CMakeLists.txt when APPLE, before +add_subdirectory(ThirdParty/openzgy). Kept outside the openzgy submodule +so the main repo can carry the fix without bumping the submodule pointer. + +diff --git a/open-zgy/native/src/exception.cpp b/open-zgy/native/src/exception.cpp +index bb6717c..666fa4e 100644 +--- a/open-zgy/native/src/exception.cpp ++++ b/open-zgy/native/src/exception.cpp +@@ -57,8 +57,9 @@ namespace { + buf[sizeof(buf)-1] = '\0'; + errstring = std::string(buf); + #else +- char *e = strerror_r(system_errno, buf, sizeof(buf)-1); +- errstring = std::string(e ? e : ""); ++ // char *e = strerror_r(system_errno, buf, sizeof(buf)-1); ++ // errstring = std::string(e ? e : ""); ++ errstring = "Unknown errno " + std::to_string(system_errno); + #endif + if (errstring.empty()) // should never happen; strerror should do it. + errstring = "Unknown errno " + std::to_string(system_errno); +diff --git a/open-zgy/native/src/impl/bulk.cpp b/open-zgy/native/src/impl/bulk.cpp +index d716501..72d8bcf 100644 +--- a/open-zgy/native/src/impl/bulk.cpp ++++ b/open-zgy/native/src/impl/bulk.cpp +@@ -146,7 +146,9 @@ + #include + #include + #include +-#include ++inline int omp_get_max_threads() { return 1; } ++inline int omp_get_num_threads() { return 1; } ++inline int omp_get_thread_num() { return 0; } + #include + + namespace InternalZGY { +diff --git a/open-zgy/native/src/impl/edgebrick.h b/open-zgy/native/src/impl/edgebrick.h +index 97fc62d..b106d91 100644 +--- a/open-zgy/native/src/impl/edgebrick.h ++++ b/open-zgy/native/src/impl/edgebrick.h +@@ -68,9 +68,9 @@ public: + , roi_(roi) + , pos_{ (atend ? size[0] : 0), 0, 0 } + { +- for (int dim = 0; dim < 3; ++dim) +- if (roi[dim] < 0 || size[dim] < 0 || roi[dim] > size[dim]) +- throw OpenZGY::Errors::ZgyInternalError("Bad size in BrickIterator"); ++ // for (int dim = 0; dim < 3; ++dim) ++ // if (roi[dim] < 0 || size[dim] < 0 || roi[dim] > size[dim]) ++ // throw OpenZGY::Errors::ZgyInternalError("Bad size in BrickIterator"); + } + + reference operator*() const { return *data_ptr_; } +diff --git a/open-zgy/native/src/impl/file_sd.cpp b/open-zgy/native/src/impl/file_sd.cpp +index 08e82d8..a55f604 100644 +--- a/open-zgy/native/src/impl/file_sd.cpp ++++ b/open-zgy/native/src/impl/file_sd.cpp +@@ -41,7 +41,9 @@ + #include + #include + #include +-#include ++inline int omp_get_max_threads() { return 1; } ++inline int omp_get_num_threads() { return 1; } ++inline int omp_get_thread_num() { return 0; } + + // It would have been nice to have similar include paths in Linux and Windows + // but that is a cosmetic issue only and it is only a problem in this file. +diff --git a/open-zgy/native/src/impl/mtguard.cpp b/open-zgy/native/src/impl/mtguard.cpp +index dcf1b01..e1a5a91 100644 +--- a/open-zgy/native/src/impl/mtguard.cpp ++++ b/open-zgy/native/src/impl/mtguard.cpp +@@ -17,7 +17,9 @@ + + #include + #include +-#include ++inline int omp_get_max_threads() { return 1; } ++inline int omp_get_num_threads() { return 1; } ++inline int omp_get_thread_num() { return 0; } + + namespace { + /** +@@ -176,11 +178,11 @@ MTGuard::finished() { + */ + void + MTGuard::fail() { +- if (_errors.fetch_add(1) == 0) { +- _first_ex = std::current_exception(); +- if (!_first_ex) +- _first_ex = std::make_exception_ptr(std::runtime_error("fail() with no current exception.")); +- } ++ // if (_errors.fetch_add(1) == 0) { ++ // _first_ex = std::current_exception(); ++ // if (!_first_ex) ++ // _first_ex = std::make_exception_ptr(std::runtime_error("fail() with no current exception.")); ++ // } + } + + MTGuardWithProgress::MTGuardWithProgress(const progress_fn fn, std::int64_t total) +diff --git a/open-zgy/native/src/impl/workorder.cpp b/open-zgy/native/src/impl/workorder.cpp +index 3e42f93..a6d5745 100644 +--- a/open-zgy/native/src/impl/workorder.cpp ++++ b/open-zgy/native/src/impl/workorder.cpp +@@ -21,7 +21,9 @@ + #include + #include + #include +-#include ++inline int omp_get_max_threads() { return 1; } ++inline int omp_get_num_threads() { return 1; } ++inline int omp_get_thread_num() { return 0; } + #include + #include + #include +@@ -654,12 +656,12 @@ WorkOrderTP::~WorkOrderTP() + */ + void + WorkOrderTP::fail() { +- if (errors_.fetch_add(1) == 0) { +- first_ex_ = std::current_exception(); +- if (!first_ex_) +- first_ex_ = std::make_exception_ptr +- (std::runtime_error("fail() with no current exception.")); +- } ++ // if (errors_.fetch_add(1) == 0) { ++ // first_ex_ = std::current_exception(); ++ // if (!first_ex_) ++ // first_ex_ = std::make_exception_ptr ++ // (std::runtime_error("fail() with no current exception.")); ++ // } + } + + void +diff --git a/open-zgy/native/src/tools/zgycopyc.cpp b/open-zgy/native/src/tools/zgycopyc.cpp +index 0be5de2..18b9580 100644 +--- a/open-zgy/native/src/tools/zgycopyc.cpp ++++ b/open-zgy/native/src/tools/zgycopyc.cpp +@@ -42,7 +42,9 @@ + #include + #include + #include +-#include ++inline int omp_get_max_threads() { return 1; } ++inline int omp_get_num_threads() { return 1; } ++inline int omp_get_thread_num() { return 0; } + #include + #include + #include +diff --git a/open-zgy/wrapper/wrappermodule.cpp b/open-zgy/wrapper/wrappermodule.cpp +index d152332..d4540bf 100644 +--- a/open-zgy/wrapper/wrappermodule.cpp ++++ b/open-zgy/wrapper/wrappermodule.cpp +@@ -51,7 +51,9 @@ + + #include + #include +-#include ++inline int omp_get_max_threads() { return 1; } ++inline int omp_get_num_threads() { return 1; } ++inline int omp_get_thread_num() { return 0; } + #include + #include + #include diff --git a/ThirdParty/vcpkg-overlay-triplets/arm64-osx.cmake b/ThirdParty/vcpkg-overlay-triplets/arm64-osx.cmake new file mode 100644 index 00000000000..26391483704 --- /dev/null +++ b/ThirdParty/vcpkg-overlay-triplets/arm64-osx.cmake @@ -0,0 +1,27 @@ +# Overlay of vcpkg's default arm64-osx triplet. See x64-osx.cmake for the +# rationale (sysroot detection); the only difference here is the target +# architecture. Tracked in #14045. + +set(VCPKG_TARGET_ARCHITECTURE arm64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_ARCHITECTURES arm64) + +if(NOT DEFINED VCPKG_OSX_SYSROOT OR VCPKG_OSX_SYSROOT STREQUAL "") + execute_process( + COMMAND xcrun --show-sdk-path + OUTPUT_VARIABLE _xcrun_sdk_path + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + RESULT_VARIABLE _xcrun_result + ) + if(_xcrun_result EQUAL 0 AND _xcrun_sdk_path) + set(VCPKG_OSX_SYSROOT "${_xcrun_sdk_path}") + endif() +endif() + +# CMake 4.x removed compatibility with cmake_minimum_required(VERSION < 3.5). +# See x64-osx.cmake for the same workaround. +list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS "-DCMAKE_POLICY_VERSION_MINIMUM=3.5") diff --git a/ThirdParty/vcpkg-overlay-triplets/x64-osx.cmake b/ThirdParty/vcpkg-overlay-triplets/x64-osx.cmake new file mode 100644 index 00000000000..891866034aa --- /dev/null +++ b/ThirdParty/vcpkg-overlay-triplets/x64-osx.cmake @@ -0,0 +1,40 @@ +# Overlay of vcpkg's default x64-osx triplet. +# +# Why this exists: +# CMake on macOS does not always populate CMAKE_OSX_SYSROOT (notably when +# only Xcode Command Line Tools are installed, no full Xcode). vcpkg's +# per-port build then injects "-isysroot ${CMAKE_OSX_SYSROOT}" verbatim, +# yielding a literal "-isysroot " with no path. Subsequent flags such as +# "-g" get consumed as the sysroot argument, and openssl (a transitive +# dep of arrow) fails with "fatal error: 'sys/types.h' file not found". +# +# Detecting the SDK path via `xcrun --show-sdk-path` and exporting it as +# VCPKG_OSX_SYSROOT pins the value vcpkg ships to every child build. +# +# Tracked in #14045. + +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_ARCHITECTURES x86_64) + +if(NOT DEFINED VCPKG_OSX_SYSROOT OR VCPKG_OSX_SYSROOT STREQUAL "") + execute_process( + COMMAND xcrun --show-sdk-path + OUTPUT_VARIABLE _xcrun_sdk_path + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + RESULT_VARIABLE _xcrun_result + ) + if(_xcrun_result EQUAL 0 AND _xcrun_sdk_path) + set(VCPKG_OSX_SYSROOT "${_xcrun_sdk_path}") + endif() +endif() + +# CMake 4.x removed compatibility with cmake_minimum_required(VERSION < 3.5). +# Many vcpkg ports still ship CMakeLists with older minimums (libevent, +# protobuf, grpc, several boost shims). Inject the policy-min so each +# port's vcpkg_cmake_configure call accepts the legacy minimum. +list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS "-DCMAKE_POLICY_VERSION_MINIMUM=3.5") diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index f4f551afb01..14325d83324 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -10,5 +10,8 @@ "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", "name": "microsoft" } + ], + "overlay-triplets": [ + "ThirdParty/vcpkg-overlay-triplets" ] } diff --git a/vcpkg.json b/vcpkg.json index 5d20c255691..64718c0e46b 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -6,7 +6,10 @@ "boost-test", "clipper2", "eigen3", - "grpc", + { + "name": "grpc", + "platform": "!osx" + }, "type-lite", "fast-float", "spdlog",