Fix mac ci build; use aqtinstall

This commit is contained in:
Andrew Rabert committed 2025-12-23 19:15:30 -05:00
1 parent 9696de712c
commit b8c4e83e17
5 files changed
+117 -38

No files matched your search

+18 -8
View File
@@ -10,30 +10,40 @@ jobs:
fail-fast: false
matrix:
include:
- runner: macos-15-intel
homebrew_prefix: /usr/local
artifact: macos-intel
- runner: macos-15
homebrew_prefix: /opt/homebrew
artifact: macos-arm64
- runner: macos-15-intel
artifact: macos-intel
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: '6.10.1'
arch: clang_64
modules: 'qtwebengine qtwebchannel qtpositioning'
- name: Install dependencies
run: |
brew update
brew install ninja mpv qt@6 || true
brew install mpv
- name: Release build
run: |
cmake -B build -G Ninja -DQTROOT=${{ matrix.homebrew_prefix }}/opt/qt@6 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=output -DCHECK_FOR_UPDATES=ON -DUSE_STATIC_MPVQT=ON
cmake -B build -G Ninja \
-DQTROOT=$QT_ROOT_DIR \
-DCMAKE_PREFIX_PATH=$QT_ROOT_DIR \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=output \
-DCHECK_FOR_UPDATES=ON \
-DUSE_STATIC_MPVQT=ON
cmake --build build --target install
- name: Sign and create dmg
run: |
codesign --force --deep -s - "./build/output/Jellyfin Desktop.app/"
codesign --force --deep -s - "./output/Jellyfin Desktop.app/"
brew install create-dmg
create-dmg --volname "Jellyfin Desktop" --no-internet-enable "Jellyfin Desktop.dmg" "./build/output/Jellyfin Desktop.app"
create-dmg --volname "Jellyfin Desktop" --no-internet-enable "Jellyfin Desktop.dmg" "./output/Jellyfin Desktop.app"
- name: Archive production artifacts
uses: actions/upload-artifact@v4
with:
+1 -1
View File
@@ -1,5 +1,5 @@
if(APPLE)
set(SCRIPT CompleteBundleOSX)
set(SCRIPT CompleteBundleMac)
elseif(WIN32)
set(SCRIPT CompleteBundleWin)
endif(APPLE)
@@ -2,23 +2,27 @@ set(app "${CMAKE_INSTALL_PREFIX}/@EXE@")
set(framework_path "${app}/Contents/Frameworks")
set(weprocess "${framework_path}/QtWebEngineCore.framework/Versions/Current/Helpers/QtWebEngineProcess.app")
# Determine rpath based on architecture
cmake_host_system_information(RESULT arch QUERY OS_PLATFORM)
if(arch STREQUAL "arm64")
set(rpath_str "/opt/homebrew/lib")
else()
set(rpath_str "/usr/local/lib")
endif()
# Detect homebrew prefix
execute_process(
COMMAND brew --prefix
OUTPUT_VARIABLE brew_prefix
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(brew_lib "${brew_prefix}/lib")
set(brew_qt_lib "${brew_prefix}/opt/qt/lib")
set(args ${app})
list(APPEND args "-verbose=2")
list(APPEND args "-qmldir=@SOURCE_ROOT@/src/ui")
list(APPEND args "-libpath=@QTROOT@/lib")
list(APPEND args "-libpath=${brew_qt_lib}")
list(APPEND args "-libpath=${brew_lib}")
foreach(BIN ${BINS})
list(APPEND args "-executable=${app}/${BIN}")
endforeach(BIN ${BINS})
set(ENV{DYLD_LIBRARY_PATH} @QTROOT@/lib:@DEPENDENCY_ROOT@/lib)
set(ENV{DYLD_FRAMEWORK_PATH} @QTROOT@/lib:@DEPENDENCY_ROOT@/lib)
set(ENV{DYLD_LIBRARY_PATH} @QTROOT@/lib:${brew_qt_lib}:${brew_lib}:@DEPENDENCY_ROOT@/lib)
set(ENV{DYLD_FRAMEWORK_PATH} @QTROOT@/lib:${brew_qt_lib}:${brew_lib}:@DEPENDENCY_ROOT@/lib)
execute_process(
COMMAND ${CMAKE_COMMAND} -E remove "${app}/Contents/Resources/qt.conf"
@@ -50,6 +54,16 @@ function(fix_lib_dependencies lib framework_libs_var)
set(needs_fix TRUE)
endif()
# Fix flat Qt refs like @executable_path/../Frameworks/QtCore -> framework path
if(line MATCHES "^@executable_path/../Frameworks/(Qt[^/ ]+) ")
set(qt_name "${CMAKE_MATCH_1}")
string(REGEX REPLACE " \\(compatibility.*$" "" old_ref "${line}")
set(new_ref "@executable_path/../Frameworks/${qt_name}.framework/Versions/A/${qt_name}")
message(STATUS "Fixing flat Qt ref ${old_ref} -> ${new_ref}")
execute_process(COMMAND install_name_tool -change "${old_ref}" "${new_ref}" "${lib}" ERROR_QUIET)
continue()
endif()
if(needs_fix)
# Extract dependency path (remove compatibility version suffix)
string(REGEX REPLACE " \\(compatibility.*$" "" dependency_str "${line}")
@@ -59,13 +73,9 @@ function(fix_lib_dependencies lib framework_libs_var)
if(dependency_str MATCHES "^@rpath/(.+)")
set(dep_name "${CMAKE_MATCH_1}")
# Search multiple potential locations for @rpath dependencies
set(search_paths "${rpath_str}/${dep_name}")
set(search_paths "${brew_lib}/${dep_name}")
# Add Cellar paths - some libs (like libjxl_cms) aren't symlinked to main lib dir
if(arch STREQUAL "arm64")
file(GLOB cellar_candidates "/opt/homebrew/Cellar/*/*/lib/${dep_name}")
else()
file(GLOB cellar_candidates "/usr/local/Cellar/*/*/lib/${dep_name}")
endif()
file(GLOB cellar_candidates "${brew_prefix}/Cellar/*/*/lib/${dep_name}")
list(APPEND search_paths ${cellar_candidates})
set(resolved_path "")
@@ -83,12 +93,8 @@ function(fix_lib_dependencies lib framework_libs_var)
elseif(dependency_str MATCHES "^@loader_path/(.+)")
get_filename_component(dep_name "${CMAKE_MATCH_1}" NAME)
# Same search logic for @loader_path
set(search_paths "${rpath_str}/${dep_name}")
if(arch STREQUAL "arm64")
file(GLOB cellar_candidates "/opt/homebrew/Cellar/*/*/lib/${dep_name}")
else()
file(GLOB cellar_candidates "/usr/local/Cellar/*/*/lib/${dep_name}")
endif()
set(search_paths "${brew_lib}/${dep_name}")
file(GLOB cellar_candidates "${brew_prefix}/Cellar/*/*/lib/${dep_name}")
list(APPEND search_paths ${cellar_candidates})
set(resolved_path "")
@@ -107,6 +113,51 @@ function(fix_lib_dependencies lib framework_libs_var)
set(resolved_path "${dependency_str}")
endif()
# Check if this is a framework reference (e.g., Python.framework/Versions/3.x/Python)
if(dependency_str MATCHES "\\.framework/")
get_filename_component(bin_name "${dependency_str}" NAME)
# Qt frameworks: macdeployqt handles them, just fix refs to use framework path
if(bin_name MATCHES "^Qt")
# Extract framework-relative path (e.g., QtCore.framework/Versions/A/QtCore)
string(REGEX MATCH "[^/]+\\.framework/.*" fw_rel_path "${dependency_str}")
set(target "@executable_path/../Frameworks/${fw_rel_path}")
message(STATUS "Fixing Qt framework ${dependency_str} -> ${target}")
execute_process(COMMAND install_name_tool -change "${dependency_str}" "${target}" "${lib}" ERROR_QUIET)
continue()
endif()
# Non-Qt frameworks (e.g., Python): copy as flat file
set(target "@executable_path/../Frameworks/${bin_name}")
list(FIND framework_libs "${bin_name}" idx)
if(idx EQUAL -1)
# Resolve the framework binary path
string(REGEX REPLACE "^@rpath" "${brew_lib}" resolved_fw "${dependency_str}")
string(REGEX REPLACE "^@loader_path" "${brew_lib}" resolved_fw "${resolved_fw}")
if(EXISTS "${resolved_fw}")
get_filename_component(real_path "${resolved_fw}" REALPATH)
message(STATUS "Copying framework binary ${real_path} -> ${framework_path}/${bin_name}")
file(COPY "${real_path}" DESTINATION "${framework_path}")
get_filename_component(real_name "${real_path}" NAME)
if(NOT "${real_name}" STREQUAL "${bin_name}")
file(RENAME "${framework_path}/${real_name}" "${framework_path}/${bin_name}")
endif()
execute_process(COMMAND install_name_tool -id "${target}" "${framework_path}/${bin_name}" ERROR_QUIET)
list(APPEND framework_libs "${bin_name}")
set_property(GLOBAL APPEND PROPERTY LIBS_TO_FIX "${framework_path}/${bin_name}")
else()
message(WARNING "Could not find framework binary: ${resolved_fw}")
continue()
endif()
endif()
message(STATUS "Fixing ${dependency_str} -> ${target}")
execute_process(COMMAND install_name_tool -change "${dependency_str}" "${target}" "${lib}" ERROR_QUIET)
continue()
endif()
get_filename_component(dep_name "${resolved_path}" NAME)
set(target "@executable_path/../Frameworks/${dep_name}")
@@ -149,7 +200,11 @@ endforeach()
# Collect all libs to fix
file(GLOB_RECURSE all_dylibs "${app}/*.dylib")
file(GLOB_RECURSE all_sos "${app}/*.so")
set_property(GLOBAL PROPERTY LIBS_TO_FIX ${all_dylibs} ${all_sos})
# Framework binaries have no extension - scan them for deps like QtDBus
file(GLOB framework_bins "${framework_path}/*.framework/Versions/*/[A-Z]*")
list(FILTER framework_bins EXCLUDE REGEX "\\.(plist|h|json|tbd)$")
list(FILTER framework_bins EXCLUDE REGEX "/(Headers|Resources)/")
set_property(GLOBAL PROPERTY LIBS_TO_FIX ${all_dylibs} ${all_sos} ${framework_bins})
# Process libs iteratively (handles newly discovered deps)
set(max_iterations 100)
+15 -6
View File
@@ -122,18 +122,27 @@ ninja windows_package
## Building for MacOS
Install [Qt 6](https://www.qt.io/download-thank-you?hsLang=en), remember to check `Qt WebEngine`.
Then run the following commands (replace <QT_DIR> with your QT installation location):
Install Qt 6.10.1 using aqtinstall and mpv from Homebrew:
```bash
brew install mpv ninja qt
# Install dependencies
brew install aqtinstall mpv ninja
# Download Qt
aqt install-qt mac desktop 6.10.1 -m qtwebengine qtwebchannel qtpositioning
# Clone and build
git clone --recursive https://github.com/jellyfin/jellyfin-desktop.git
cd jellyfin-desktop
cmake -B build -G Ninja -DUSE_STATIC_MPVQT=ON
cmake --build build
export QTROOT=$(pwd)/6.10.1/macos
cmake -B build -G Ninja \
-DQTROOT=$QTROOT \
-DCMAKE_PREFIX_PATH=$QTROOT \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=output \
-DUSE_STATIC_MPVQT=ON
cmake --build build --target install
```
## Log File Location
+6 -1
View File
@@ -128,9 +128,14 @@ get_property(BUNDLED_FILES GLOBAL PROPERTY CONFIG_BUNDLED_FILES)
add_executable(${MAIN_TARGET} WIN32 MACOSX_BUNDLE ${MAIN_SRCS} ${BUNDLED_FILES} ${RESOURCE_FILES} ${XCODE_RESOURCES})
add_dependencies(${MAIN_TARGET} generate_resources)
std_target_properties(${MAIN_TARGET})
if(APPLE)
set(_install_rpath "@executable_path/../Frameworks")
else()
set(_install_rpath "${QTROOT}/lib")
endif()
set_target_properties(${MAIN_TARGET} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/bundle/osx/Info.plist.in
INSTALL_RPATH "${QTROOT}/lib"
INSTALL_RPATH "${_install_rpath}"
OUTPUT_NAME ${MAIN_NAME}
)
copy_resources(${MAIN_TARGET})