Use macos-15-large (Intel) for DAQP test #8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test CasADi | |
| on: | |
| push: | |
| workflow_dispatch: | |
| jobs: | |
| test-matlab-macos-arm64: | |
| runs-on: macos-14 | |
| env: | |
| MW_CRASH_MODE: native | |
| steps: | |
| - uses: actions/checkout@v4.1.1 | |
| - name: Clone CasADi repo | |
| run: git clone --depth 1 https://github.com/casadi/casadi.git casadi_src | |
| - name: Download CasADi nightly | |
| run: | | |
| wget https://github.com/casadi/casadi/releases/download/nightly-relwithdebinfo-debug/casadi-relwithdebinfo-debug-osx-arm64-matlab2018b.zip -O casadi.zip | |
| - name: Unpack | |
| run: unzip casadi.zip -d casadi | |
| - name: Set up MATLAB | |
| uses: matlab-actions/setup-matlab@v2 | |
| with: | |
| release: R2025a | |
| - name: Run sysid_patched with AMD ordering (workaround for METIS bug) | |
| uses: matlab-actions/run-command@v2 | |
| continue-on-error: true | |
| env: | |
| MW_CRASH_MODE: native | |
| with: | |
| command: addpath('${{ github.workspace }}/casadi'); addpath('${{ github.workspace }}'); sysid_patched | |
| - name: Wait for crash report generation | |
| if: always() | |
| run: | | |
| echo "Waiting for macOS to generate crash report..." | |
| sleep 15 | |
| - name: Collect crash info | |
| if: always() | |
| run: | | |
| echo "=== Core dumps ===" | |
| ls -la /cores/ 2>/dev/null || echo "No /cores directory or empty" | |
| find /cores -name "core.*" 2>/dev/null | head -5 | while read f; do | |
| echo "=== Core dump: $f ===" | |
| ls -la "$f" | |
| done | |
| echo "" | |
| echo "=== MATLAB crash dump in home directory ===" | |
| find ~ -maxdepth 1 -name "matlab_crash_dump*" -mmin -30 2>/dev/null | while read f; do | |
| echo "=== $f ===" | |
| cat "$f" 2>/dev/null | head -1000 | |
| done | |
| echo "" | |
| echo "=== System crash reports - .ips files ===" | |
| find /Library/Logs/DiagnosticReports ~/Library/Logs/DiagnosticReports -name "*.ips" -mmin -30 2>/dev/null | while read f; do | |
| echo "=== $f ===" | |
| cat "$f" 2>/dev/null | |
| done | |
| echo "" | |
| echo "=== System crash reports - .crash files ===" | |
| find /Library/Logs/DiagnosticReports ~/Library/Logs/DiagnosticReports -name "*.crash" -mmin -30 2>/dev/null | while read f; do | |
| echo "=== $f ===" | |
| cat "$f" 2>/dev/null | |
| done | |
| echo "" | |
| echo "=== List all diagnostic reports ===" | |
| ls -la /Library/Logs/DiagnosticReports/ 2>/dev/null | tail -30 | |
| ls -la ~/Library/Logs/DiagnosticReports/ 2>/dev/null | tail -30 | |
| echo "" | |
| echo "=== Check for MATLAB-specific crash reports ===" | |
| find /Library/Logs/DiagnosticReports ~/Library/Logs/DiagnosticReports -name "*MATLAB*" -o -name "*matlab*" 2>/dev/null | head -20 | |
| - name: Symbolicate crash dump | |
| if: always() | |
| run: | | |
| python3 << 'EOF' | |
| import re | |
| import subprocess | |
| import os | |
| from pathlib import Path | |
| # Find the crash dump | |
| crash_files = list(Path.home().glob("matlab_crash_dump*")) | |
| if not crash_files: | |
| print("No crash dump found") | |
| exit(0) | |
| crash_file = max(crash_files, key=lambda f: f.stat().st_mtime) | |
| print(f"=== Symbolicating {crash_file} ===\n") | |
| content = crash_file.read_text() | |
| # Pattern for stack frames like: | |
| # [ 12] 0x000000012b17d4d0 /path/to/lib.dylib+00201936 __func+00000108 | |
| pattern = r'\[\s*(\d+)\]\s+(0x[0-9a-fA-F]+)\s+(/[^\s]+\.dylib)\+(\d+)\s+(\S+)' | |
| casadi_dir = Path("${{ github.workspace }}/casadi") | |
| print("=== Symbolicated Stack Trace ===\n") | |
| for match in re.finditer(pattern, content): | |
| frame_num = match.group(1) | |
| runtime_addr = match.group(2) | |
| lib_path = match.group(3) | |
| offset = int(match.group(4)) | |
| func_name = match.group(5) | |
| # Only symbolicate our libraries | |
| if "/casadi/" not in lib_path: | |
| print(f"[{frame_num:>3}] {func_name} (system library)") | |
| continue | |
| # Find dSYM - try versioned name first, then unversioned | |
| lib_name = Path(lib_path).name | |
| dsym_path = casadi_dir / f"{lib_name}.dSYM" / "Contents" / "Resources" / "DWARF" / lib_name | |
| if not dsym_path.exists(): | |
| # Try stripping version number: libfoo.2.dylib -> libfoo.dylib | |
| unversioned = re.sub(r'\.\d+\.dylib$', '.dylib', lib_name) | |
| if unversioned != lib_name: | |
| dsym_path = casadi_dir / f"{unversioned}.dSYM" / "Contents" / "Resources" / "DWARF" / unversioned | |
| if not dsym_path.exists(): | |
| print(f"[{frame_num:>3}] {func_name} (no dSYM for {lib_name})") | |
| continue | |
| # Calculate load address | |
| runtime_int = int(runtime_addr, 16) | |
| load_addr = hex(runtime_int - offset) | |
| # Use atos to symbolicate | |
| try: | |
| result = subprocess.run( | |
| ["atos", "-o", str(dsym_path), "-l", load_addr, runtime_addr], | |
| capture_output=True, text=True, timeout=10 | |
| ) | |
| symbolicated = result.stdout.strip() | |
| if symbolicated and "atos cannot" not in symbolicated: | |
| print(f"[{frame_num:>3}] {symbolicated}") | |
| else: | |
| print(f"[{frame_num:>3}] {func_name} @ {lib_name}+{offset}") | |
| except Exception as e: | |
| print(f"[{frame_num:>3}] {func_name} @ {lib_name}+{offset} (atos error: {e})") | |
| print("\n=== End Symbolicated Stack Trace ===") | |
| EOF |