Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 204 additions & 0 deletions .github/workflows/ResInsightMac.yml
Original file line number Diff line number Diff line change
@@ -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-<date>,
# 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
38 changes: 37 additions & 1 deletion ApplicationExeCode/RiaMainTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,33 @@

#include <map>
#include <sstream>
#include <version>

// 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 <version> 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 <stacktrace>
#define RIA_HAS_STD_STACKTRACE 1
#else
#define RIA_HAS_STD_STACKTRACE 0
#endif

#ifndef WIN32
#include <signal.h>
// macOS marks <ucontext.h> 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 <ucontext.h>
#endif
#endif

namespace internal
{
#if RIA_HAS_STD_STACKTRACE
// Custom formatter for stacktrace
std::string formatStacktrace( const std::stacktrace& st )
{
Expand All @@ -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 )
Expand Down Expand Up @@ -144,7 +163,9 @@ static std::string signalCodeDescription( int signo, int siCode )
//--------------------------------------------------------------------------------------------------
static void performCrashLogging( int signalCode, const std::map<std::string, std::string>& 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 )
Expand All @@ -161,8 +182,12 @@ static void performCrashLogging( int signalCode, const std::map<std::string, std
fileLogger->error( 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 <stacktrace>)" );
#endif

fileLogger->flush();
}
Expand All @@ -171,7 +196,9 @@ static void performCrashLogging( int signalCode, const std::map<std::string, std
auto& otelManager = RiaOpenTelemetryManager::instance();
if ( otelManager.isEnabled() )
{
#if RIA_HAS_STD_STACKTRACE
otelManager.reportCrash( signalCode, st, extraAttrs );
#endif
}
}

Expand Down Expand Up @@ -206,6 +233,12 @@ void manageSegFailureSA( int signalCode, siginfo_t* info, void* ucontext )
}
}

// Program-counter capture relies on the Linux ucontext layout
// (gregs[REG_RIP] for x86_64, mcontext.pc for aarch64). macOS exposes
// a different layout and marks <ucontext.h> 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 )
{
Expand All @@ -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 );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ static std::string extractRelevantPath( const std::string& fullPath )
return fullPath;
}

#if RIA_HAS_STD_STACKTRACE
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -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

//--------------------------------------------------------------------------------------------------
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,20 @@
#include <memory>
#include <mutex>
#include <queue>
#include <stacktrace>
#include <string>
#include <version>

// 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
// <version> 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 <stacktrace>
#define RIA_HAS_STD_STACKTRACE 1
#else
#define RIA_HAS_STD_STACKTRACE 0
#endif

class QString;
class QNetworkAccessManager;
Expand Down Expand Up @@ -88,7 +100,9 @@ class RiaOpenTelemetryManager : public QObject

// Event reporting
void reportEventAsync( const std::string& eventName, const std::map<std::string, std::string>& attributes );
#if RIA_HAS_STD_STACKTRACE
void reportCrash( int signalCode, const std::stacktrace& trace, const std::map<std::string, std::string>& extraAttributes = {} );
#endif

// Configuration
bool isEnabled() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading