Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8e15608
configure: update wine_build string to include Mythic
zenfinityy Oct 28, 2025
3c55ea9
feat: initial build script revision
zenfinityy Oct 28, 2025
3a9a82e
feat: add dxvk w/ support for wine 9.0 to `externals/`
zenfinityy Oct 28, 2025
750b713
feat: add gptk 3.0b5 to externals
zenfinityy Oct 28, 2025
5986c36
fix: correct typo in build.yml step
zenfinityy Oct 28, 2025
d9c00d5
feat(build): add copy externals step
zenfinityy Oct 28, 2025
ea2f9bf
fix(build): remove unused package libusb
zenfinityy Oct 28, 2025
3534051
feat(build): add & copy engine properties file to artifact
zenfinityy Oct 28, 2025
f154f9e
fix(build): explicitly set mingw linker in env
zenfinityy Oct 28, 2025
f648c5f
fix(build): resolve wine_build `sed` premature escaping
zenfinityy Nov 1, 2025
6df9c3e
feat(build): ensure only one workflow runs per ref
zenfinityy Nov 1, 2025
6c8dc09
feat(build): allow winedbg
zenfinityy Nov 1, 2025
0bfe39c
fix(build): revert optimization level to -O2
zenfinityy Nov 1, 2025
12314ce
fix(build): add -std=gnu17 to `CROSSCFLAGS` for compatibility
zenfinityy Nov 1, 2025
ff5d28b
fix(build): update dependencies
zenfinityy Nov 1, 2025
03f8c50
fix(build): remove libinotify from dependencies and configuration
zenfinityy Nov 1, 2025
f4617df
fix(build): use `make install-lib` over `make install`
zenfinityy Nov 1, 2025
6dfb014
refactor(build): replace `cp` with `ditto` for copying dxvk binaries
zenfinityy Nov 1, 2025
4fb6f4d
fix(build): add `CPATH` and `LIBRARY_PATH` environment variables
zenfinityy Nov 1, 2025
7e0ee2e
refactor(build): rename step to clarify installation of dependencies
zenfinityy Nov 1, 2025
44097f2
fix(build): fix broken wine64 symlink
zenfinityy Nov 1, 2025
d25aceb
fix(build): downgrade mingw-w64 to v12.0.0_1
zenfinityy Nov 15, 2025
f4551af
i fear for my own stupidity.
zenfinityy Nov 15, 2025
bafb47e
feat(`gptk`): bump to 3.0
zenfinityy Dec 15, 2025
f5c73e1
feat(build): use macOS 12.3 SDK and Xcode 13 toolchain for workflow
zenfinityy Dec 20, 2025
043bada
fix(build): add missing `libpcap` dependency
zenfinityy Dec 21, 2025
2f30389
fix(build): remove `-ld_classic` from `LDFLAGS`
zenfinityy Dec 23, 2025
7d0d0f2
refactor(build): tidy up environment variables
zenfinityy Dec 23, 2025
7fc925f
feat!(build): bundle necessary dylibs
zenfinityy Dec 23, 2025
f5d20f2
fix: move dylib bundler back one directory
zenfinityy Dec 23, 2025
8e249f4
Update build.yml
zenfinityy Dec 23, 2025
17a0100
fix(build): replace wine64 symlink with executable wrapper
zenfinityy Dec 23, 2025
e6ca751
refactor(build): streamline dylib bundling process
zenfinityy Dec 23, 2025
68c22a7
feat(build): include wine mono
zenfinityy Dec 23, 2025
d25e59e
fix(build): update bad chmod command for wine64 executable wrapper
zenfinityy Dec 23, 2025
5bfa99a
chore(build): add comment to wine64 executable wrapper
zenfinityy Dec 23, 2025
89a58f8
chore(build): remove unneeded `-p` argument for relevant `mkdir`s
zenfinityy Dec 23, 2025
028f6eb
chore(build): tidy up comments
zenfinityy Dec 23, 2025
8b3230e
genius was calling. i declined
zenfinityy Dec 23, 2025
1569b5c
fix(dylib_bundler): rename path variable due to conflicts
zenfinityy Dec 24, 2025
de6a0e7
refactor(build): use all codes during engine artifact compression
zenfinityy Dec 24, 2025
70bba2a
feat(build): include wine gecko
zenfinityy Dec 24, 2025
c694ebc
fix(build): increase compression level for engine artifact
zenfinityy Dec 24, 2025
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
161 changes: 161 additions & 0 deletions .github/dylib_bundler.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#!/bin/zsh

# this is a script created for Mythic to bundle its dependencies' dylibs and copy them to the appropriate location.

set -e

# Output directory (can be overridden via environment variable)
ENGINE_DIR="${ENGINE_DIR:-Engine/wine}"
BREW_PREFIX=$(brew --prefix)

# List of GStreamer plugins to bundle, minus the 'libgst' prefix
GSTREAMER_PLUGINS=(
applemedia
asf
audioconvert
audioparsers
audioresample
avi
coreelements
debug
deinterlace
id3demux
isomp4
libav
opengl
playback
typefindfunctions
videoconvertscale
videofilter
videoparsersbad
wavparse
)

# list of keg-only formulae and their main dylib names
BUNDLE_LIBS=(
molten-vk:libMoltenVK
sdl2:libSDL2-2.0.0
freetype:libfreetype
gnutls:libgnutls
libpng:libpng16
libtiff:libtiff
libpcap:libpcap
jpeg:libjpeg
libffi:libffi
)

typeset -A seen_dylibs
typeset -a all_dylibs

get_lib_path() {
local formula="$1" libname="$2"
local prefix=$(brew --prefix "$formula" 2>/dev/null) || return 1
find "$prefix/lib" -maxdepth 1 -name "${libname}*.dylib" -type f 2>/dev/null | head -1
}

resolve_rpath() {
local name="${1#@rpath/}"

# Check main lib dir first
[[ -f "${BREW_PREFIX}/lib/${name}" ]] && { echo "${BREW_PREFIX}/lib/${name}"; return; }

# Search keg-only formula lib dirs
for entry in "${BUNDLE_LIBS[@]}"; do
local formula="${entry%%:*}"
local lib_path="$(brew --prefix "$formula" 2>/dev/null)/lib/${name}"
[[ -f "$lib_path" ]] && { echo "$lib_path"; return; }
done
}

normalize_path() {
python3 -c "import os; print(os.path.realpath('$1'))" 2>/dev/null || echo "$1"
}

find_dependencies() {
local dylib="$1"
local norm=$(normalize_path "$dylib")

[[ -n "${seen_dylibs[$norm]}" ]] && return
seen_dylibs[$norm]=1
all_dylibs+=("$dylib")

local -a queue=("$dylib")

while [[ ${#queue[@]} -gt 0 ]]; do
local current="${queue[1]}"
queue=("${queue[@]:1}")

for ref in $(otool -L "$current" 2>/dev/null | tail -n +2 | awk '/^\t/ {print $1}' | grep '\.dylib'); do
[[ "$ref" == /usr/lib/* || "$ref" == /System/* ]] && continue
[[ "$ref" == @loader_path/* || "$ref" == @executable_path/* ]] && continue

[[ "$ref" == @rpath/* ]] && { ref=$(resolve_rpath "$ref"); [[ -z "$ref" ]] && continue; }

norm=$(normalize_path "$ref")
[[ -z "${seen_dylibs[$norm]}" ]] && {
seen_dylibs[$norm]=1
all_dylibs+=("$ref")
queue+=("$ref")
}
done
done
}

fix_install_names() {
local file="$1" prefix="$2"
chmod u+w "$file"
install_name_tool -id "${prefix}$(basename "$file")" "$file" 2>/dev/null || true

otool -L "$file" | grep -v "$file" | awk '{print $1}' | while read -r lib_path; do
[[ "$lib_path" != /usr/lib* && "$lib_path" != /System/* ]] && \
install_name_tool -change "$lib_path" "${prefix}${lib_path##*/}" "$file" 2>/dev/null || true
done
codesign -fs- "$file" 2>/dev/null || true
}

copy_dylib() {
local lib="$1" dest_dir="${ENGINE_DIR}/lib" prefix="@loader_path/"

[[ "$lib" == *"/gstreamer-1.0/"* ]] && { dest_dir="${ENGINE_DIR}/lib/gstreamer-1.0"; prefix="@loader_path/../"; }

local dest="${dest_dir}/$(basename "$lib")"
mkdir -p "$dest_dir"
[[ -f "$dest" ]] && return 0

cp -L "$lib" "$dest"
fix_install_names "$dest" "$prefix"
}

main() {
local gst_prefix=$(brew --prefix gstreamer)

echo "=== Processing GStreamer plugins ==="
for plugin in "${GSTREAMER_PLUGINS[@]}"; do
local lib_path="${gst_prefix}/lib/gstreamer-1.0/libgst${plugin}.dylib"
[[ -f "$lib_path" ]] && find_dependencies "$lib_path" || echo "Warning: $plugin not found"
done

echo "=== Processing libraries ==="
for entry in "${BUNDLE_LIBS[@]}"; do
local formula="${entry%%:*}" libname="${entry#*:}"
local lib_path=$(get_lib_path "$formula" "$libname")
[[ -n "$lib_path" ]] && find_dependencies "$lib_path" || echo "Warning: $formula not found"
done

echo "=== Copying ${#all_dylibs[@]} dylibs ==="
for dylib in "${all_dylibs[@]}"; do copy_dylib "$dylib"; done

[[ -d "${gst_prefix}/lib/gstreamer-1.0/include" ]] && {
mkdir -p "${ENGINE_DIR}/lib/gstreamer-1.0"
cp -a "${gst_prefix}/lib/gstreamer-1.0/include" "${ENGINE_DIR}/lib/gstreamer-1.0/"
}

echo "=== Fixing Wine .so files ==="
for so in "${ENGINE_DIR}"/lib/wine/x86_64-unix/*.so(N); do
otool -L "$so" 2>/dev/null | grep -q "/usr/local\|/opt/homebrew" && fix_install_names "$so" "@rpath/"
done

echo "=== Done: ${#all_dylibs[@]} dylibs bundled ==="
}

main "$@"
203 changes: 203 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
name: Build Mythic Engine (wine-crossover 9.0)

on:
push:
pull_request:

env:
MACOSX_DEPLOYMENT_TARGET: 10.15
SDKROOT: /Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk
TOOLCHAINS: com.applex.dt.toolchain.Xcode13 # from gcenx
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'applex' to 'apple' in the toolchain identifier.

Suggested change
TOOLCHAINS: com.applex.dt.toolchain.Xcode13 # from gcenx
TOOLCHAINS: com.apple.dt.toolchain.Xcode13 # from gcenx

Copilot uses AI. Check for mistakes.

PATH: /usr/local/bin:/usr/local/opt/bison/bin:/usr/bin:/bin:/usr/sbin:/sbin

CPATH: /usr/local/include
LIBRARY_PATH: /usr/local/lib

# mingw-w64 cross-compilers
i386_CC: i686-w64-mingw32-gcc
x86_64_CC: x86_64-w64-mingw32-gcc
i386_LD: i686-w64-mingw32-ld
x86_64_LD: x86_64-w64-mingw32-ld

# compiler and linker flags
CFLAGS: -O2 -Wno-deprecated-declarations -Wno-unguarded-availability
CXXFLAGS: -O2 -Wno-deprecated-declarations -Wno-unguarded-availability
CROSSCFLAGS: -O2 -Wno-error=incompatible-pointer-types -Wno-error=int-conversion -Wno-deprecated-declarations
CPPFLAGS: -I/usr/local/opt/libpcap/include
LDFLAGS: -Wl,-headerpad_max_install_names -Wl,-rpath,@loader_path/../../ -Wl,-rpath,@loader_path/../../external -Wl,-rpath,/usr/local/lib -L/usr/local/opt/libpcap/lib

PKG_CONFIG_PATH: /usr/local/opt/libpcap/lib/pkgconfig

# wine configure overrides
ac_cv_lib_soname_MoltenVK: libMoltenVK.dylib
ac_cv_lib_soname_vulkan: ""

concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true

jobs:
build:
runs-on: macos-15-intel

steps:
- uses: actions/checkout@v5
with:
path: src

- name: download & add Xcode 13 toolchain
run: |
sudo mkdir -p /Library/Developer/Toolchains
curl -fL https://dl.getmythic.app/engine/toolchains/Xcode13.xctoolchain.tar.xz \
| sudo tar -xJ -C /Library/Developer/Toolchains

- name: download & add macOS 12.3 SDK
run: |
sudo mkdir -p /Library/Developer/CommandLineTools/SDKs
curl -fL https://github.com/Gcenx/macos-sdk/releases/download/12.3/MacOSX12.3.tar.bz2 \
| sudo tar -xj -C /Library/Developer/CommandLineTools/SDKs

# ensure that when updating dependencies, the dylib bundler script is also updated
- name: install build & runtime dependencies
run: |
brew install bison \
freetype \
pkg-config \
gettext \
gnutls \
gstreamer \
gst-plugins-base \
gst-plugins-good \
jpeg \
libpng \
libtiff \
libffi \
libpcap \
sdl2 \
molten-vk \
winetricks

# install mingw-w64 v12.0.0_1 from local formula w/ tap
# required, this version requires binutils 2.43.1 or older
brew tap-new local/mingw-w64
cp src/external/dependencies/mingw-w64.rb \
"$(brew --repo local/mingw-w64)/Formula/mingw-w64.rb"

brew install local/mingw-w64/mingw-w64

- name: create build directory
run: mkdir build

- name: configure wine
working-directory: build
run: |
../src/configure \
--prefix= \
--disable-tests \
--enable-archs=i386,x86_64 \
--with-mingw \
--without-alsa \
--without-capi \
--with-coreaudio \
--with-cups \
--without-dbus \
--without-fontconfig \
--with-freetype \
--with-gettext \
--without-gettextpo \
--without-gphoto \
--with-gnutls \
--without-gssapi \
--with-gstreamer \
--without-krb5 \
--without-netapi \
--with-opencl \
--with-opengl \
--without-oss \
--with-pcap \
--with-pthread \
--without-pulse \
--without-sane \
--with-sdl \
--without-udev \
--with-unwind \
--without-usb \
--without-v4l2 \
--with-vulkan \
--without-x

- name: build wine
working-directory: build
run: make -j$(sysctl -n hw.ncpu)

- name: create install directory
run: mkdir install

- name: install wine
working-directory: build
run: make install-lib DESTDIR=${{ github.workspace }}/install

- name: add wine64 as an executable wrapper for backward compatibility
working-directory: install/bin
run: |
cat > wine64 << 'EOF'
#!/usr/bin/env bash

# this is a wrapper created for Mythic to forward `wine64` calls to `wine`.
# for older versions of Mythic, which expected a wine64 binary to be present.

set -e
DIR="$(cd "$(dirname "$0")" && pwd)"
exec "$DIR/wine" "$@"
EOF

chmod +x wine64

- name: install wine mono
working-directory: install/share/wine
run: |
mkdir -p mono
curl -fL https://github.com/wine-mono/wine-mono/releases/download/wine-mono-8.1.0/wine-mono-8.1.0-x86.tar.xz \
| tar -xJ -C mono

- name: install wine gecko
working-directory: install/share/wine
run: |
mkdir -p gecko
curl -fL https://dl.winehq.org/wine/wine-gecko/2.47.4/wine-gecko-2.47.4-x86.tar.xz \
| tar -xJ -C gecko

- name: create Engine directory
run: mkdir Engine

- name: copy build artifacts
run: |
mkdir -p Engine/wine
ditto --rsrc install Engine/wine

- name: copy externals
run: |
# copy dxvk binaries
mkdir -p Engine/dxvk
ditto src/external/dxvk-* Engine/dxvk/

# copy gptk libraries
ditto src/external/gptk-*/redist/lib/ Engine/wine/lib/

- name: bundle dylib dependencies
run: |
chmod +x src/.github/dylib_bundler.zsh
ENGINE_DIR=Engine/wine src/.github/dylib_bundler.zsh

- name: copy engine properties file
run: cp -R src/Mythic/Properties.plist Engine/

- name: compress engine artifact
run: tar -cf Engine.tar.xz -C Engine --use-compress-program="xz -9 -T0" .

- name: upload engine artifact
uses: actions/upload-artifact@v5
with:
name: Engine
path: Engine.tar.xz
18 changes: 18 additions & 0 deletions Mythic/Properties.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>version</key>
<array/>
Comment on lines +5 to +6
Copy link

Copilot AI Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version key is mapped to an empty array, which appears to be a structural error. The version information is defined in subsequent keys (major, minor, patch), so this array likely serves no purpose or should be removed. If this is intentional metadata, it needs clarification through comments or better structure.

Suggested change
<key>version</key>
<array/>

Copilot uses AI. Check for mistakes.
<key>major</key>
<integer>3</integer>
<key>minor</key>
<integer>0</integer>
<key>patch</key>
<integer>0</integer>
<key>preRelease</key>
<string>alpha</string>
<key>build</key>
<string></string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -23020,7 +23020,7 @@ install-image: install-lib

as_fn_append wine_rules "
dlls/ntdll/unix/version.c: dummy
@version=\`(echo \"wine-\$(PACKAGE_VERSION)\") | sed -n -e '\$\$s/\(.*\)/const char wine_build[] = \"\\1 (CrossOver 24.0.7 FOSS)\";/p'\` && (echo \$\$version | cmp -s - \$@) || echo \$\$version >\$@ || (rm -f \$@ && exit 1)
@version=\`(echo \"wine-\$(PACKAGE_VERSION)\") | sed -n -e '\$\$s/\(.*\)/const char wine_build[] = \"\\1 (Mythic Engine, derived from CrossOver)\";/p'\` && (echo \$\$version | cmp -s - \$@) || echo \$\$version >\$@ || (rm -f \$@ && exit 1)
programs/winetest/build.rc: dummy
@build=\"STRINGTABLE { 1 \\\"\`GIT_DIR=${wine_srcdir}.git git rev-parse HEAD 2>/dev/null\`\\\" }\" && (echo \$\$build | cmp -s - \$@) || echo \$\$build >\$@ || (rm -f \$@ && exit 1)
programs/winetest/build.nfo:
Expand Down
Loading
Loading