Skip to content

Commit 846b939

Browse files
authored
Merge pull request #5 from fbraz3/macos-build
Macos build
2 parents 8124925 + 6b0d59a commit 846b939

5 files changed

Lines changed: 568 additions & 82 deletions

File tree

.github/workflows/build-macos.yml

Lines changed: 138 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,49 @@ jobs:
5353
restore-keys: |
5454
brew-macos-${{ runner.os }}-
5555
56+
- name: Setup vcpkg
57+
uses: lukka/run-vcpkg@v11
58+
with:
59+
vcpkgGitCommitId: '533a5fda5c0646d1771345fb572e759283444d5f'
60+
5661
- name: Install Dependencies
5762
run: |
5863
echo "Installing macOS build dependencies..."
59-
brew install cmake ninja meson
60-
cmake --version
61-
ninja --version
64+
65+
# Update Homebrew to ensure fresh formulas
66+
brew update
67+
68+
# Ensure xcode-select is properly configured (needed for clang/clang++)
69+
xcode-select --install 2>/dev/null || echo "xcode-select already installed"
70+
xcode-select -p || (echo "❌ Xcode command-line tools not installed"; exit 1)
71+
72+
# Build tools
73+
brew install cmake ninja meson pkg-config
74+
75+
# FFmpeg (required by GameEngineDevice for video playback via pkg-config)
76+
brew install ffmpeg
77+
78+
# Freetype + Fontconfig (required by font rendering)
79+
brew install freetype fontconfig
80+
81+
# GLM (required by CompatLib for math, SAGE_USE_GLM)
82+
brew install glm
83+
84+
# glslang (required by DXVK Meson build to compile GLSL shaders to SPIR-V)
85+
brew install glslang
86+
87+
# OpenAL Soft (required by audio layer; provides <AL/al.h> — macOS system OpenAL framework uses <OpenAL/al.h> which is incompatible)
88+
brew install openal-soft
89+
90+
# Verify all tools are available
91+
cmake --version | head -1
92+
ninja --version | head -1
93+
meson --version | head -1
94+
pkg-config --version | head -1
95+
clang --version | head -1
96+
pkg-config --modversion libavcodec 2>/dev/null && echo "✅ FFmpeg: libavcodec available" || echo "❌ FFmpeg: libavcodec NOT found"
97+
find /opt/homebrew -name "glmConfig.cmake" 2>/dev/null | head -1 && echo "✅ GLM cmake config found" || echo "❌ GLM cmake config NOT found"
98+
6299
echo "✅ Build tools installed"
63100
64101
- name: Install Vulkan SDK
@@ -101,44 +138,91 @@ jobs:
101138
# Extract and install if valid ZIP
102139
if [ -f "$VULKAN_ZIP" ] && [ "$(stat -f%z "$VULKAN_ZIP" 2>/dev/null || echo 0)" -gt 100000000 ]; then
103140
echo "Extracting Vulkan SDK ZIP..."
104-
mkdir -p /tmp/vulkan-extract
105-
unzip -q "$VULKAN_ZIP" -d /tmp/vulkan-extract
106141
107-
# Find the .app installer bundle
108-
VULKAN_APP=$(find /tmp/vulkan-extract -name "*.app" -type d 2>/dev/null | head -1)
109-
if [ -z "$VULKAN_APP" ]; then
110-
echo "❌ No .app installer found in extracted ZIP"
111-
ls -la /tmp/vulkan-extract/
112-
VULKAN_APP=""
142+
# Verify ZIP integrity before extraction
143+
echo "Validating ZIP file integrity..."
144+
if ! unzip -t "$VULKAN_ZIP" > /dev/null 2>&1; then
145+
echo "❌ ZIP file is corrupted"
146+
unzip -t "$VULKAN_ZIP" || true
147+
rm -f "$VULKAN_ZIP"
148+
VULKAN_SDK=""
113149
else
114-
echo "Found installer: $VULKAN_APP"
115-
INSTALLER="$VULKAN_APP/Contents/MacOS/InstallVulkan"
150+
echo "✅ ZIP file is valid"
151+
152+
# List ZIP contents for debugging
153+
echo "ZIP contents:"
154+
unzip -l "$VULKAN_ZIP" | head -20
155+
156+
# Extract with verbose output (not quiet)
157+
mkdir -p /tmp/vulkan-extract
158+
unzip -o "$VULKAN_ZIP" -d /tmp/vulkan-extract
159+
160+
# List extracted contents
161+
echo "Extracted structure:"
162+
find /tmp/vulkan-extract -type f -o -type d | head -30
116163
117-
if [ ! -f "$INSTALLER" ]; then
118-
echo "❌ Installer not found at $INSTALLER"
119-
ls -la "$VULKAN_APP/Contents/MacOS/"
120-
VULKAN_APP=""
164+
# Strategy 1: Look for .app bundle (primary)
165+
VULKAN_APP=$(find /tmp/vulkan-extract -name "*.app" -type d 2>/dev/null | head -1)
166+
if [ -n "$VULKAN_APP" ]; then
167+
INSTALLER="$VULKAN_APP/Contents/MacOS/vulkansdk-macOS-1.4.341.1"
168+
if [ -f "$INSTALLER" ]; then
169+
echo "Found .app bundle installer: $INSTALLER"
170+
VULKAN_EXECUTABLE="$INSTALLER"
171+
else
172+
echo "⚠️ .app bundle found but executable not at expected path"
173+
ls -la "$VULKAN_APP/Contents/MacOS/" || true
174+
VULKAN_EXECUTABLE=""
175+
fi
121176
else
177+
echo "⚠️ No .app bundle found"
178+
fi
179+
180+
# Strategy 2: Look for direct executable if no .app found
181+
if [ -z "$VULKAN_EXECUTABLE" ]; then
182+
VULKAN_EXECUTABLE=$(find /tmp/vulkan-extract -name "vulkansdk-macOS-*" -type f -executable 2>/dev/null | head -1)
183+
if [ -n "$VULKAN_EXECUTABLE" ]; then
184+
echo "Found direct executable: $VULKAN_EXECUTABLE"
185+
else
186+
# Try non-executable variant
187+
VULKAN_EXECUTABLE=$(find /tmp/vulkan-extract -name "vulkansdk-macOS-*" -type f 2>/dev/null | head -1)
188+
if [ -n "$VULKAN_EXECUTABLE" ]; then
189+
echo "Found executable (making executable): $VULKAN_EXECUTABLE"
190+
chmod +x "$VULKAN_EXECUTABLE"
191+
fi
192+
fi
193+
fi
194+
195+
# Execute installer if found
196+
if [ -n "$VULKAN_EXECUTABLE" ] && [ -f "$VULKAN_EXECUTABLE" ]; then
122197
INSTALL_TARGET="$HOME/VulkanSDK/1.4.341.1"
123198
echo "Running Vulkan SDK installer to $INSTALL_TARGET..."
124-
"$INSTALLER" \
199+
"$VULKAN_EXECUTABLE" \
125200
--root "$INSTALL_TARGET" \
126201
--accept-licenses \
127202
--default-answer \
128203
--confirm-command install
129-
fi
130-
131-
INSTALL_STATUS=$?
132-
if [ $INSTALL_STATUS -eq 0 ]; then
133-
VULKAN_SDK="$INSTALL_TARGET"
134-
echo "✅ Vulkan SDK installed to $VULKAN_SDK"
204+
INSTALL_STATUS=$?
205+
206+
if [ $INSTALL_STATUS -eq 0 ]; then
207+
# Normalize to platform subdirectory (CMake FindVulkan expects VULKAN_SDK/lib, not VULKAN_SDK/macOS/lib)
208+
if [ -d "$INSTALL_TARGET/macOS" ]; then
209+
VULKAN_SDK="$INSTALL_TARGET/macOS"
210+
else
211+
VULKAN_SDK="$INSTALL_TARGET"
212+
fi
213+
echo "✅ Vulkan SDK installed to $INSTALL_TARGET"
214+
echo "✅ Normalized VULKAN_SDK to: $VULKAN_SDK"
215+
else
216+
echo "❌ Installer failed with status $INSTALL_STATUS"
217+
VULKAN_SDK=""
218+
fi
135219
else
136-
echo "❌ Installer failed with status $INSTALL_STATUS"
220+
echo "❌ No installer found"
137221
VULKAN_SDK=""
138222
fi
223+
224+
rm -rf /tmp/vulkan-extract "$VULKAN_ZIP"
139225
fi
140-
141-
rm -rf /tmp/vulkan-extract "$VULKAN_ZIP"
142226
else
143227
echo "⚠️ Vulkan SDK versioned download/validation failed; trying Homebrew fallback"
144228
fi
@@ -159,8 +243,17 @@ jobs:
159243
160244
# Set environment variables for downstream steps
161245
if [ -z "$VULKAN_SDK" ] || [ ! -d "$VULKAN_SDK" ]; then
162-
# Last resort: search for any installed SDK
163-
VULKAN_SDK="$(find $HOME/VulkanSDK -maxdepth 1 -type d 2>/dev/null | head -1)"
246+
# Last resort: search for any installed SDK, prefer macOS subdir
247+
for candidate in $(find $HOME/VulkanSDK -maxdepth 2 -type d -name "macOS" 2>/dev/null); do
248+
VULKAN_SDK="$candidate"
249+
break
250+
done
251+
fi
252+
253+
# Normalize: if VULKAN_SDK points to version root (has macOS subdir), use macOS subdir
254+
if [ -d "$VULKAN_SDK/macOS" ] && [ -f "$VULKAN_SDK/macOS/lib/libvulkan.dylib" ]; then
255+
VULKAN_SDK="$VULKAN_SDK/macOS"
256+
echo "Normalized VULKAN_SDK to platform subdirectory"
164257
fi
165258
166259
if [ -z "$VULKAN_SDK" ] || [ ! -d "$VULKAN_SDK" ]; then
@@ -175,17 +268,23 @@ jobs:
175268
if [ -f "$VULKAN_SDK/lib/libMoltenVK.dylib" ]; then
176269
echo "✅ MoltenVK found at $VULKAN_SDK/lib/libMoltenVK.dylib"
177270
else
178-
echo "⚠️ MoltenVK not found at expected location; build may still work if system Vulkan is available"
271+
echo "⚠️ MoltenVK not found at $VULKAN_SDK/lib/libMoltenVK.dylib"
179272
echo "Checking for alternate locations..."
180-
find "$VULKAN_SDK" -name "libMoltenVK*" 2>/dev/null | head -5 || echo "(none found)"
273+
find "$(dirname $VULKAN_SDK)" -name "libMoltenVK*" 2>/dev/null | head -5 || echo "(none found)"
181274
fi
182275
183276
- name: Configure CMake (macOS)
184277
env:
185278
VULKAN_SDK: ${{ env.VULKAN_SDK }}
279+
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
280+
VCPKG_DEFAULT_TRIPLET: arm64-osx
281+
CC: clang
282+
CXX: clang++
186283
run: |
187284
mkdir -p logs
188285
echo "VULKAN_SDK=$VULKAN_SDK"
286+
echo "CC=$CC"
287+
echo "CXX=$CXX"
189288
cmake --preset ${{ inputs.preset }} 2>&1 | tee logs/configure_macos.log
190289
CONFIG_STATUS=${PIPESTATUS[0]}
191290
if [ $CONFIG_STATUS -eq 0 ]; then echo "✅ CMake configuration complete"; else echo "❌ CMake configuration failed"; exit 1; fi
@@ -272,10 +371,15 @@ jobs:
272371
[ -f "$f" ] && cp -v "$f" "${RUNTIME_DIR}/lib/" || true
273372
done
274373
275-
# MoltenVK dylib from Vulkan SDK
276-
if [ -f "${{ env.VULKAN_SDK }}/lib/libMoltenVK.dylib" ]; then
277-
echo " Copying MoltenVK..."
374+
# MoltenVK dylib from Vulkan SDK (check both primary and fallback paths)
375+
if [ -f "${{ env.VULKAN_SDK }}/macOS/lib/libMoltenVK.dylib" ]; then
376+
echo " Copying MoltenVK from macOS/lib..."
377+
cp -v "${{ env.VULKAN_SDK }}/macOS/lib/libMoltenVK.dylib" "${RUNTIME_DIR}/lib/" || true
378+
elif [ -f "${{ env.VULKAN_SDK }}/lib/libMoltenVK.dylib" ]; then
379+
echo " Copying MoltenVK from lib..."
278380
cp -v "${{ env.VULKAN_SDK }}/lib/libMoltenVK.dylib" "${RUNTIME_DIR}/lib/" || true
381+
else
382+
echo " ⚠️ MoltenVK dylib not found in Vulkan SDK"
279383
fi
280384
281385
echo " Copying run.sh wrapper from scripts..."

cmake/dx8.cmake

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -81,75 +81,61 @@ elseif(APPLE AND SAGE_USE_MOLTENVK)
8181
set(DXVK_D3D8_LIB "${DXVK_BUILD_DIR}/src/d3d8/libdxvk_d3d8.0.dylib")
8282
set(DXVK_D3D9_LIB "${DXVK_BUILD_DIR}/src/d3d9/libdxvk_d3d9.0.dylib")
8383

84-
# Detect Vulkan SDK location for Meson configuration
85-
# GeneralsX @build BenderAI 03/03/2026: Handle cases where VULKAN_SDK is not installed
84+
# Detect Vulkan SDK location for Meson configuration.
85+
# VULKAN_SDK must point to the platform subdir (e.g. ~/VulkanSDK/1.4.x/macOS)
86+
# where lib/libvulkan.dylib and lib/libMoltenVK.dylib live.
87+
# GeneralsX @build BenderAI 03/03/2026: Normalize env path to macOS platform subdir
8688
set(VULKAN_SDK_ENV "$ENV{VULKAN_SDK}")
87-
if(NOT VULKAN_SDK_ENV)
88-
# Try home directory for manually installed SDK (installer puts it in $HOME/VulkanSDK/VERSION/)
89-
file(GLOB VULKAN_HOME_DIRS "$ENV{HOME}/VulkanSDK/*")
89+
90+
# If VULKAN_SDK points to the version root (has macOS/ subdir), normalize it
91+
if(VULKAN_SDK_ENV AND EXISTS "${VULKAN_SDK_ENV}/macOS/lib/libMoltenVK.dylib")
92+
set(VULKAN_SDK_ENV "${VULKAN_SDK_ENV}/macOS")
93+
message(STATUS "DXVK macOS build: Normalized VULKAN_SDK to platform subdir: ${VULKAN_SDK_ENV}")
94+
endif()
95+
96+
if(NOT VULKAN_SDK_ENV OR NOT EXISTS "${VULKAN_SDK_ENV}/lib/libMoltenVK.dylib")
97+
# Try home directory: look for ~/VulkanSDK/*/macOS
98+
file(GLOB VULKAN_HOME_DIRS "$ENV{HOME}/VulkanSDK/*/macOS")
9099
if(VULKAN_HOME_DIRS)
91-
# Find the latest version directory
92100
list(SORT VULKAN_HOME_DIRS)
93101
list(REVERSE VULKAN_HOME_DIRS)
94102
list(GET VULKAN_HOME_DIRS 0 POTENTIAL_SDK)
95103
if(EXISTS "${POTENTIAL_SDK}/lib/libMoltenVK.dylib")
96104
set(VULKAN_SDK_ENV "${POTENTIAL_SDK}")
97105
endif()
98106
endif()
99-
100-
# Try common Homebrew locations if home directory search failed
101-
if(NOT VULKAN_SDK_ENV)
102-
if(EXISTS "/usr/local/Caskroom/vulkan-sdk")
103-
set(VULKAN_SDK_ENV "/usr/local/Caskroom/vulkan-sdk/latest/VulkanSDK")
104-
elseif(EXISTS "/opt/homebrew/Caskroom/vulkan-sdk")
105-
set(VULKAN_SDK_ENV "/opt/homebrew/Caskroom/vulkan-sdk/latest/VulkanSDK")
107+
endif()
108+
109+
if(NOT VULKAN_SDK_ENV OR NOT EXISTS "${VULKAN_SDK_ENV}/lib/libMoltenVK.dylib")
110+
# Try common Homebrew locations
111+
foreach(BREW_PATH "/usr/local/Caskroom/vulkan-sdk/latest/VulkanSDK/macOS" "/opt/homebrew/Caskroom/vulkan-sdk/latest/VulkanSDK/macOS")
112+
if(EXISTS "${BREW_PATH}/lib/libMoltenVK.dylib")
113+
set(VULKAN_SDK_ENV "${BREW_PATH}")
114+
break()
106115
endif()
107-
endif()
116+
endforeach()
108117
endif()
109118

110119
if(VULKAN_SDK_ENV AND EXISTS "${VULKAN_SDK_ENV}/lib/libMoltenVK.dylib")
111120
message(STATUS "DXVK macOS build: Using Vulkan SDK at ${VULKAN_SDK_ENV}")
112121
set(VULKAN_SDK_ENV_VAR "VULKAN_SDK=${VULKAN_SDK_ENV}")
113122
else()
114-
message(WARNING "DXVK macOS build: Vulkan SDK not found; Meson will search in system paths")
123+
message(WARNING "DXVK macOS build: Vulkan SDK / MoltenVK not found; Meson will search system paths")
124+
if(VULKAN_SDK_ENV)
125+
message(STATUS " VULKAN_SDK checked: ${VULKAN_SDK_ENV}")
126+
endif()
115127
set(VULKAN_SDK_ENV_VAR "")
116128
endif()
117129

118130
ExternalProject_Add(dxvk_macos_build
119131
GIT_REPOSITORY https://github.com/doitsujin/dxvk.git
120-
GIT_TAG ad253b8a7e20b7cf16fce7d1c505928a434eac29 # v2.6 pinned commit SHA
132+
GIT_TAG ad253b8a7e20b7cf16fce7d1c505928a434eac29
121133
SOURCE_DIR ${DXVK_SOURCE_DIR}
122134
BINARY_DIR ${DXVK_BUILD_DIR}
123-
# Apply macOS patches before configuring
124-
PATCH_COMMAND
125-
${CMAKE_COMMAND} -E echo "Applying macOS patches to DXVK..." &&
126-
${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/dxvk-macos-patches.py ${DXVK_SOURCE_DIR}
127-
# Configure with Meson using SDL3 windowing system.
128-
# Force arm64 compilation despite Rosetta2 emulation:
129-
# 1. Pass -mcpu=apple-m1 -arch arm64 to Clang
130-
# 2. Use --native-file to tell Meson the build machine is aarch64
131-
# 3. Pass VULKAN_SDK to Meson if detected
132-
CONFIGURE_COMMAND
133-
${CMAKE_COMMAND} -E env
134-
CC=clang CXX=clang++
135-
"CFLAGS=-arch ${DXVK_HOST_ARCH} -mcpu=apple-m1"
136-
"CXXFLAGS=-arch ${DXVK_HOST_ARCH} -mcpu=apple-m1"
137-
"LDFLAGS=-arch ${DXVK_HOST_ARCH}"
138-
${VULKAN_SDK_ENV_VAR}
139-
${MESON_EXECUTABLE} setup ${DXVK_BUILD_DIR} ${DXVK_SOURCE_DIR}
140-
--native-file ${CMAKE_SOURCE_DIR}/cmake/meson-arm64-native.ini
141-
-Ddxvk_native_wsi=sdl3
142-
--buildtype=release
143-
--reconfigure
144-
# Build d3d9 first (d3d8 links against it at runtime via @rpath),
145-
# then d3d8. Both dylibs must be present in the runtime directory.
146-
BUILD_COMMAND
147-
${NINJA_EXECUTABLE} -C ${DXVK_BUILD_DIR}
148-
src/d3d9/libdxvk_d3d9.0.dylib
149-
src/d3d8/libdxvk_d3d8.0.dylib
150-
# DXVK install is not needed; we deploy the dylibs manually
135+
PATCH_COMMAND /bin/bash -lc "${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/dxvk-macos-patches.py ${DXVK_SOURCE_DIR}"
136+
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CC=clang CXX=clang++ "CFLAGS=-arch ${DXVK_HOST_ARCH} -mcpu=apple-m1" "CXXFLAGS=-arch ${DXVK_HOST_ARCH} -mcpu=apple-m1" "LDFLAGS=-arch ${DXVK_HOST_ARCH}" ${VULKAN_SDK_ENV_VAR} ${MESON_EXECUTABLE} setup ${DXVK_BUILD_DIR} ${DXVK_SOURCE_DIR} --native-file ${CMAKE_SOURCE_DIR}/cmake/meson-arm64-native.ini -Ddxvk_native_wsi=sdl3 --buildtype=release --reconfigure
137+
BUILD_COMMAND ${NINJA_EXECUTABLE} -C ${DXVK_BUILD_DIR} src/d3d9/libdxvk_d3d9.0.dylib src/d3d8/libdxvk_d3d8.0.dylib
151138
INSTALL_COMMAND ""
152-
# Only re-patch/reconfigure when the git tag changes
153139
UPDATE_DISCONNECTED TRUE
154140
)
155141

docs/DEV_BLOG/2026-02-DIARY.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
---
44

5+
## 2026-02-28 (SESSION 77): macOS CI — vcpkg restored to fix gli dependency
6+
7+
**Objective**: Fix CI failure on `gli CONFIG REQUIRED``gli` is not on Homebrew and was previously provided by vcpkg.
8+
9+
**Root Cause**: In session 72, `macos-vulkan` preset was changed from `inherits: "default-vcpkg"` to `inherits: "default"` to remove the broken `$env{VCPKG_ROOT}` reference (VCPKG_ROOT was unset in CI). This removed the vcpkg toolchain file entirely, which broke resolution of `gli`, `glm`, `freetype`, `fontconfig` — all defined in `vcpkg.json`. Locally they still worked because `VCPKG_ROOT=/Users/felipebraz/vcpkg` was already set in the shell env.
10+
11+
**Fix Applied**:
12+
1. **`CMakePresets.json`**: Restored `macos-vulkan` to `inherits: "default-vcpkg"` (reverts session 72 change).
13+
2. **`build-macos.yml`**: Added `lukka/run-vcpkg@v11` step after brew cache, bootstrapping vcpkg at baseline commit `533a5fda5` (matches `vcpkg.json` builtin-baseline).
14+
3. **`build-macos.yml`**: Configure CMake step now exports `VCPKG_ROOT` and `VCPKG_DEFAULT_TRIPLET=arm64-osx` so CMake preset resolves the toolchain file correctly.
15+
16+
**Key Insight**: The project already had a `vcpkg.json` manifest with `gli`, `glm`, `zlib`, `freetype`, `fontconfig`. The correct fix was never to remove vcpkg — it was to provide `VCPKG_ROOT` to the CI environment. The `lukka/run-vcpkg` action handles this cleanly with built-in caching.
17+
18+
**State**: Commit `87dce18a5` pushed to `macos-build`. CI run triggered.
19+
20+
---
21+
522
## 2026-02-27 (SESSION 68.6): GitHub Actions — macOS Workflow Audit & Improvements
623

724
**Objective**: Apply lessons learned from Linux workflow to harden macOS workflow before merging to `main`.

0 commit comments

Comments
 (0)