diff --git a/.CI/SetupHomebrewDeps.sh b/.CI/SetupHomebrewDeps.sh new file mode 100755 index 00000000000..0119eaa7c67 --- /dev/null +++ b/.CI/SetupHomebrewDeps.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash + +set -e + +# Prefix for where to find the ARM64 library +arm64_homebrew_dir="/opt/homebrew" +# Prefix for where to find the x86 library +x86_64_homebrew_dir="/opt/homebrew-x86_64" + # Directory where we place the finished universal library +universal_lib_dir="/opt/universal-lib" + +# args: path-to-library (in homebrew dir) +c2-make-universal-dylib() { + local _input_lib="$1" + if [ -z "${_input_lib}" ]; then + echo "usage: $0 [lib-path-relative-to-homebrew] (e.g. $0 lib/libboost_random-mt.dylib)" + exit 1 + fi + + if [ ! -w "${universal_lib_dir}" ]; then + echo "error: The current user does not have write permission in the universal lib directory (${universal_lib_dir})" + exit 1 + fi + + local _input_lib_filename="$(basename "${_input_lib}")" + + local _arm64_lib="${arm64_homebrew_dir}/${_input_lib}" + local _x86_64_lib="${x86_64_homebrew_dir}/${_input_lib}" + local _override_lib=$(realpath "${arm64_homebrew_dir}/${_input_lib}") + + local _universal_lib="${universal_lib_dir}/${_input_lib_filename}" + + if [ ! -f "${_arm64_lib}" ]; then + echo "error: The ARM64 library '${_input_lib}' cannot be found at '${_arm64_lib}'" + exit 1 + fi + + if [ ! -f "${_x86_64_lib}" ]; then + echo "error: The x86_64 library '${_input_lib}' cannot be found at '${_x86_64_lib}'" + exit 1 + fi + + # Create the combined library + if ! lipo "${_arm64_lib}" "${_x86_64_lib}" -create -output "${_universal_lib}"; then + echo "error: Something went wrong creating the combined library" + echo "Some errors can be solved by re-linking the original libraries (e.g. brew link --overwrite boost)" + exit 1 + fi + + echo "Created the combined library at '${_universal_lib}" + + # Override + rm -v "${_override_lib}" + ln -v -s "${_universal_lib}" "${_override_lib}" +} + +sudo mkdir "$x86_64_homebrew_dir" +sudo mkdir "$universal_lib_dir" + +sudo chown -R $USER "$universal_lib_dir" + +echo "Installing x86_64 brew" +sudo curl -L https://github.com/Homebrew/brew/tarball/master | sudo tar xz --strip 1 -C "$x86_64_homebrew_dir" +sudo chown -R $USER "$x86_64_homebrew_dir" + +echo "Installing ARM dependencies" +brew install "$@" + +echo "Installing x86_64 dependencies" +for dep in "$@" +do + arch -x86_64 "$x86_64_homebrew_dir/bin/brew" fetch --force --bottle-tag=x86_64_monterey "$dep" + arch -x86_64 "$x86_64_homebrew_dir/bin/brew" install $(arch -x86_64 "$x86_64_homebrew_dir/bin/brew" --cache --bottle-tag=x86_64_monterey "$dep") +done + +echo "Relinking boost libraries" +c2-make-universal-dylib lib/libboost_random-mt.dylib + +echo "Relinking OpenSSL 3 libcrypto" +c2-make-universal-dylib lib/libcrypto.dylib +echo "Relinking OpenSSL 3 libssl" +c2-make-universal-dylib lib/libssl.dylib diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8f14f35951..aecc10f45c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,14 +110,14 @@ jobs: path: build/Chatterino-${{ matrix.os }}-x86_64.deb build: - name: "Build ${{ matrix.os }}${{ matrix.arch && format(' ({0})', matrix.arch) || ''}}, Qt ${{ matrix.qt-version }} (LTO:${{ matrix.force-lto }}, crashpad:${{ matrix.skip-crashpad && 'off' || 'on' }})" + name: "Build ${{ matrix.os }}, Qt ${{ matrix.qt-version }} (LTO:${{ matrix.force-lto }}, crashpad:${{ matrix.skip-crashpad && 'off' || 'on' }})" runs-on: ${{ matrix.os }} strategy: matrix: include: # Windows - os: windows-latest - qt-version: 6.7.1 + qt-version: 6.7.3 force-lto: false plugins: true skip-artifact: false @@ -125,15 +125,6 @@ jobs: # macOS (ARM) - os: macos-latest qt-version: 6.7.1 - arch: arm64 - force-lto: false - plugins: true - skip-artifact: false - skip-crashpad: false - # macOS (x86) - - os: macos-13 - qt-version: 6.7.1 - arch: x86_64 force-lto: false plugins: true skip-artifact: false @@ -289,7 +280,10 @@ jobs: - name: Install dependencies (MacOS) if: startsWith(matrix.os, 'macos') run: | - brew install boost openssl rapidjson p7zip create-dmg cmake tree + # binary dependencies + ./.CI/SetupHomebrewDeps.sh boost openssl@3 + # build and header-only dependencies + brew install rapidjson p7zip create-dmg cmake tree shell: bash - name: Build (MacOS) @@ -300,13 +294,12 @@ jobs: cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 \ - -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl \ -DUSE_PRECOMPILED_HEADERS=OFF \ -DCHATTERINO_LTO="$C2_ENABLE_LTO" \ -DCHATTERINO_PLUGINS="$C2_PLUGINS" \ -DBUILD_WITH_QT6="$C2_BUILD_WITH_QT6" \ -DCHATTERINO_NO_AVIF_PLUGIN=On \ - -DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ .. make -j"$(sysctl -n hw.logicalcpu)" shell: bash @@ -314,7 +307,7 @@ jobs: - name: Package (MacOS) if: startsWith(matrix.os, 'macos') env: - OUTPUT_DMG_PATH: chatterino-macos-Qt-${{ matrix.qt-version}}-${{ matrix.arch }}.dmg + OUTPUT_DMG_PATH: chatterino-macos-Qt-${{ matrix.qt-version}}-universal.dmg run: | ls -la pwd @@ -327,6 +320,27 @@ jobs: curl -SsfLo kimg.zip "https://github.com/nerixyz/kimageformats-binaries/releases/download/cont/kimageformats-macos-13-${{ matrix.qt-version}}.zip" ./../.CI/MacDeploy.sh + + # Copy dynamic library dependencies into the Frameworks directory + cp /opt/universal-lib/libcrypto.dylib chatterino.app/Contents/Frameworks/libcrypto.3.dylib + cp /opt/universal-lib/libssl.dylib chatterino.app/Contents/Frameworks/libssl.3.dylib + + # Fix the library IDs to match their new location + install_name_tool -id @executable_path/../Frameworks/libssl.3.dylib chatterino.app/Contents/Frameworks/libssl.3.dylib + install_name_tool -id @executable_path/../Frameworks/libcrypto.3.dylib chatterino.app/Contents/Frameworks/libcrypto.3.dylib + + # Fix the search path for libcrypto in libssl + otool -L chatterino.app/Contents/Frameworks/libssl.3.dylib \ + | grep libcrypto.3.dylib \ + | cut -d" " -f1 \ + | cut -f2 \ + | while read input_crypto_dylib; do \ + install_name_tool -change \ + "$input_crypto_dylib" \ + @executable_path/../Frameworks/libcrypto.3.dylib \ + chatterino.app/Contents/Frameworks/libssl.3.dylib; \ + done + ./../.CI/CreateDMG.sh shell: bash @@ -334,8 +348,9 @@ jobs: if: startsWith(matrix.os, 'macos') uses: actions/upload-artifact@v4 with: - name: chatterino-macos-Qt-${{ matrix.qt-version }}-${{ matrix.arch }}.dmg - path: build/chatterino-macos-Qt-${{ matrix.qt-version }}-${{ matrix.arch }}.dmg + name: chatterino-macos-Qt-${{ matrix.qt-version }}-universal.dmg + path: build/chatterino-macos-Qt-${{ matrix.qt-version }}-universal.dmg + create-release: needs: [build-ubuntu-docker, build] runs-on: ubuntu-latest @@ -348,15 +363,15 @@ jobs: # Windows - uses: actions/download-artifact@v4 - name: Windows Qt6.7.1 + name: Windows Qt6.7.3 with: - name: chatterino-windows-x86-64-Qt-6.7.1.zip + name: chatterino-windows-x86-64-Qt-6.7.3.zip path: release-artifacts/ - uses: actions/download-artifact@v4 - name: Windows Qt6.7.1 symbols + name: Windows Qt6.7.3 symbols with: - name: chatterino-windows-x86-64-Qt-6.7.1-symbols.pdb.7z + name: chatterino-windows-x86-64-Qt-6.7.3-symbols.pdb.7z path: release-artifacts/ # Linux @@ -380,23 +395,16 @@ jobs: # macOS - uses: actions/download-artifact@v4 - name: macOS x86_64 Qt6.7.1 x86 dmg - with: - name: chatterino-macos-Qt-6.7.1-x86_64.dmg - path: release-artifacts/ - - - uses: actions/download-artifact@v4 - name: macOS x86_64 Qt6.7.1 ARM dmg + name: macOS Qt6.7.1 dmg with: - name: chatterino-macos-Qt-6.7.1-arm64.dmg + name: chatterino-macos-Qt-6.7.1-universal.dmg path: release-artifacts/ - name: Rename artifacts run: | ls -l # Rename the macos build to indicate that it's for macOS 12.0 users - mv chatterino-macos-Qt-6.7.1-x86_64.dmg Chatterino-macOS-12.0-x86_64.dmg - mv chatterino-macos-Qt-6.7.1-arm64.dmg Chatterino-macOS-12.0-arm64.dmg + mv chatterino-macos-Qt-6.7.1-universal.dmg Chatterino-macOS-12.0-universal.dmg working-directory: release-artifacts shell: bash diff --git a/.github/workflows/create-installer.yml b/.github/workflows/create-installer.yml index 2b79ee151ed..12df9f50259 100644 --- a/.github/workflows/create-installer.yml +++ b/.github/workflows/create-installer.yml @@ -20,7 +20,7 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} strategy: matrix: - qt-version: ["6.7.1"] + qt-version: ["6.7.3"] steps: - uses: actions/checkout@v4 with: @@ -148,10 +148,9 @@ jobs: mv Chatterino-x86_64-Qt-6.7.2.AppImage Chatterino-x86_64-Qt6.AppImage - mv chatterino-windows-x86-64-Qt-6.7.1-symbols.pdb.7z Chatterino-Windows-debug-symbols.pdb.7z + mv chatterino-windows-x86-64-Qt-6.7.3-symbols.pdb.7z Chatterino-Windows-debug-symbols.pdb.7z - mv chatterino-macos-Qt-6.7.1-x86_64.dmg Chatterino-x86_64.dmg - mv chatterino-macos-Qt-6.7.1-arm64.dmg Chatterino-arm64.dmg + mv chatterino-macos-Qt-6.7.1-universal.dmg Chatterino.dmg - name: Hash files working-directory: build diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0451c605fda..03a88ade61a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -98,3 +98,4 @@ jobs: plugin: gcov fail_ci_if_error: true verbose: true + if: false diff --git a/CHANGELOG.c7.md b/CHANGELOG.c7.md index d64964a74f4..f9287c48714 100644 --- a/CHANGELOG.c7.md +++ b/CHANGELOG.c7.md @@ -6,3 +6,4 @@ - Dev(macOS): Changed CFBundleIdentifier from `com.chatterino` to `app.7tv.chatterino7` (fec0dbdf558b1e6e358971a256f5540d34bb6a8d) - Dev: Updated Conan version used in CI to 2.4 (330d05d50ffd296b34744dbcc97290534e8cf704) - Dev(Windows): Updated `libavif` to 1.0.4, `boost` to 1.85, and `openssl` to 3.2.2 (330d05d50ffd296b34744dbcc97290534e8cf704) +- Dev(macOS): A single universal app is now released for macOS (#274)