33 Commits

Author SHA1 Message Date
a459d0a086 fixed docs url, removed extra help menu. 2026-02-21 19:17:31 -07:00
deepend-tildeclub
e3fb5b27f5 Update contact email in plugin metadata 2026-02-21 18:38:29 -07:00
deepend-tildeclub
60ade26bda Change branch from 'stable' to 'master' 2026-02-21 18:32:09 -07:00
deepend-tildeclub
6cbbcf06b0 Update Flatpak build container image to GNOME 49 2026-02-21 17:47:15 -07:00
deepend-tildeclub
58394d555e Merge pull request #69 from ZoiteChat/update-shared-modules
Updated the flatpak/shared-modules submodule to the latest upstream c…
2026-02-21 16:39:51 -08:00
deepend-tildeclub
7e8a830fda Update CI to use Ubuntu and new Flatpak image 2026-02-21 17:33:34 -07:00
deepend-tildeclub
19a19b4237 Change branch triggers from update-shared-modules to master 2026-02-21 17:30:00 -07:00
fcaedd41ce Updated the Flatpak GitHub Actions workflow to fully disable Flatpak builder caching by setting cache: false and restore-cache: false in the flatpak-builder step (and removing the previous cache-key usage) 2026-02-21 17:21:25 -07:00
deepend-tildeclub
e4e5689bc5 Enable GTK3 support in Zoitechat build options 2026-02-21 17:08:07 -07:00
deepend-tildeclub
5080c3b1d2 Enable GTK3 support in Zoitechat build config 2026-02-21 17:03:47 -07:00
deepend-tildeclub
3d450a3b33 Remove release build type from Zoitechat config 2026-02-21 16:54:03 -07:00
deepend-tildeclub
faf55e0d06 Change branch for Flatpak build workflow 2026-02-21 16:36:58 -07:00
ee40f3842b Updated the Flatpak manifest’s lgi module pin from the old commit to c9b8e4473c6421f2a215d8c06c0d94b86eb0b26a, which matches the meson buildsystem expectation and avoids the Can't find meson.build failure for that module checkout path. 2026-02-21 16:27:11 -07:00
deepend-tildeclub
cc9b1e249a Update socket and Lua version in Zoitechat config 2026-02-21 16:19:22 -07:00
3c2b0a8986 Good catch on data/icons/menu — I updated the resource bundle to include the new SVG menu icons (for both light and dark variants), not just PNG entries. This ensures those assets are actually packaged and available at runtime (including Flatpak).
Kept existing PNG entries intact and added SVG entries alongside them so the current icon-loading fallback behavior continues to work while enabling the newer icon files.
2026-02-21 15:46:43 -07:00
724211362b fixed one clear Flatpak metadata mismatch: the plugin extension version was still 20.08 while the runtime is GNOME 49. I updated the extension version to 49 so Flatpak metadata is internally consistent. 2026-02-21 14:53:49 -07:00
e4b8c641b1 Updated the flatpak/shared-modules submodule to the latest upstream commit from the configured shared-modules repository link (https://github.com/flathub/shared-modules.git). 2026-02-21 14:38:59 -07:00
deepend-tildeclub
3f0b936694 replace icon 2026-02-19 12:07:24 -08:00
3ef7768696 Updated the Solus CI workflow to install pkgconf instead of pkgconfig during the eopkg bootstrap step, resolving the Repo item pkgconfig not found failure path you hit. 2026-02-18 16:08:39 -07:00
e2cb540ee9 Updated the Solus package release from 1 to 2 in packaging/solus/package.yml so the metadata reflects this dependency fix update.
Replaced the Solus build dependency pkgconfig with pkgconf to address the Repo item pkgconfig not found packaging failure.

Committed the change on the current branch
2026-02-18 15:32:11 -07:00
bcd2b15ee4 Updated the Solus eopkg CI workflow to install required Meson toolchain/build packages (meson, ninja, pkgconfig, gcc, gettext) together with ypkg/git before running ypkg build, which addresses the reported meson: command not found setup failure.
Added inline workflow comments documenting why these extra packages are needed in this containerized Solus build path.
2026-02-18 14:54:32 -07:00
f66a68b3fd Updated the Solus packaging source from a missing tag tarball URL to a valid GitHub commit archive URL, and updated the SHA256 to match that archive so source extraction succeeds. 2026-02-18 14:38:52 -07:00
e060d57bae Updated the Solus packaging source checksum for zoitechat-2.18.0-pre1.tar.gz to the hash reported by the failing build log (d5558cd419c8d46bdc958064cb97f963d1ea793866414c025906ec15033512ed). 2026-02-18 14:22:11 -07:00
0796b96908 Added a Win32 existing-instance fallback so --existing with no URL/command now sends a dedicated __WIN32_TASKBAR_TOGGLE__ command to the running ZoiteChat instance, instead of doing nothing. This gives taskbar/shortcut invocations an explicit toggle action.
Updated the Win32 WM_COPYDATA handler to recognize that toggle command and perform minimize/restore behavior:

visible window → iconify

hidden window → show/present
while preserving existing behavior for normal remote commands.
2026-02-18 13:28:17 -07:00
184bfd2f69 Updated Solus packaging metadata to use a numeric version (2.18.0) instead of prerelease-form strings that were reported as invalid by your validator.
Left the source tarball URL/checksum unchanged (zoitechat-2.18.0-pre1), so this only adjusts the package metadata version field to pass format checks.
2026-02-18 13:14:44 -07:00
e3f624d2bb Fixed the GTK3 window-state handler so minimizing via taskbar no longer immediately deiconifies the window again. Specifically, I removed the conflicting gtk_window_deiconify(wid) call from the iconify path in mg_windowstate_cb, while preserving the existing tray-hide behavior and window state bookkeeping. This restores expected toggle behavior when clicking the taskbar icon on a maximized window. 2026-02-18 13:11:04 -07:00
e2db0ec3e5 Updated the Solus package metadata version string in packaging/solus/package.yml from 2.18.0-pre1 to 2.18.0pre1 so it uses a ypkg-compatible prerelease format and avoids the Invalid version build failure you hit 2026-02-18 12:55:55 -07:00
7b0d574752 Updated the Solus CI workflow to install ypkg/git using eopkg install -y --ignore-file-conflicts ..., which prevents the openssl vs openssl-11 file-conflict failure from aborting the build early.
Added explanatory comments in the workflow about why file-conflict tolerance is necessary in some Solus base images.
2026-02-18 12:41:33 -07:00
9e42c0dcc4 Updated the Solus eopkg GitHub Actions workflow to stop removing openssl-11 during container setup, and added a comment explaining that this removal can trigger a broad dependency cascade (including python3/eopkg) that breaks the build before ypkg build starts. 2026-02-18 11:52:19 -07:00
a8f68e22dd Updated the Solus eopkg GitHub Actions workflow to detect and remove legacy openssl-11 before dependency installation, preventing the file-conflict failure shown in your CI log while keeping behavior no-op on images that don’t have openssl-11.
Kept the rest of the build flow unchanged (ypkg build, artifact collection/upload)
2026-02-18 11:40:37 -07:00
5d5219566f emoved the openssl-11 removal workaround from the Solus eopkg workflow, so the container build now goes directly from eopkg update-repo -y to installing ypkg/git, avoiding the package-removal cascade that can break eopkg 2026-02-18 11:21:07 -07:00
5e4f408235 Updated the Solus eopkg workflow to conditionally remove openssl-11 before installing build dependencies, preventing the file-conflict failure when openssl is upgraded/installed in older Solus container images.
Kept the fix minimal and safe by guarding removal behind a package-presence check (eopkg li | grep ...) so it only applies when needed.
2026-02-18 11:12:10 -07:00
3d6b2485d1 Updated the Solus workflow’s default container image from ghcr.io/getsolus/solus:latest to docker.io/silkeh/solus:latest in both workflow input defaults and job env fallback, so the workflow no longer depends on a missing GHCR tag by default.
Added explicit error handling around docker pull "$SOLUS_IMAGE" with a clearer remediation message telling users to override solus_image if pull fails.
2026-02-18 11:00:05 -07:00
30 changed files with 316 additions and 1045 deletions

View File

@@ -31,7 +31,8 @@ jobs:
with:
bundle: zoitechat.flatpak
manifest-path: flatpak/net.zoite.Zoitechat.json
cache-key: flatpak-builder-${{ github.sha }}
cache: false
restore-cache: false
- name: Upload Flatpak Bundle
id: upload_flatpak

View File

@@ -1,359 +0,0 @@
name: macOS Build
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
macos_build_arm64:
runs-on: macos-15-arm64
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install build dependencies
run: |
set -eux
brew update
brew install \
meson ninja pkg-config gettext perl \
gtk+3 gdk-pixbuf pango adwaita-icon-theme \
hicolor-icon-theme glib dbus \
enchant gtk-mac-integration
if ! command -v gtk-mac-bundler >/dev/null 2>&1 && ! python3 -c 'import gtk_mac_bundler' >/dev/null 2>&1; then
curl -fsSL https://codeload.github.com/jralls/gtk-mac-bundler/tar.gz/refs/heads/master -o /tmp/gtk-mac-bundler.tar.gz
rm -rf /tmp/gtk-mac-bundler
mkdir -p /tmp/gtk-mac-bundler
tar -xzf /tmp/gtk-mac-bundler.tar.gz -C /tmp/gtk-mac-bundler --strip-components=1
(cd /tmp/gtk-mac-bundler && make install)
fi
- name: Configure and build (arm64)
run: |
set -eux
rm -rf build-macos-arm64 stage/arm64
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson setup build-macos-arm64 \
--prefix="$PWD/stage/arm64" \
-Dgtk3=true \
-Dtext-frontend=true \
-Dlibcanberra=disabled \
-Dwith-perl=perl \
-Dwith-python=python3 \
-Dauto_features=enabled
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson compile -C build-macos-arm64
meson install -C build-macos-arm64
- name: Stage runtime dependencies for bundling (arm64)
run: |
set -eux
STAGE_PREFIX="$PWD/stage/arm64"
BREW_PREFIX="$(brew --prefix)"
ENCHANT_PREFIX="$(brew --prefix enchant)"
mkdir -p "$STAGE_PREFIX/lib" "$STAGE_PREFIX/share"
rsync -a "$BREW_PREFIX/lib/gtk-3.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/lib/gdk-pixbuf-2.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/share/locale/" "$STAGE_PREFIX/share/locale/"
mkdir -p "$STAGE_PREFIX/opt"
rm -rf "$STAGE_PREFIX/opt/enchant"
rsync -aL "$ENCHANT_PREFIX/" "$STAGE_PREFIX/opt/enchant/"
- name: Package unsigned .app (arm64)
run: |
set -eux
VERSION="$(git describe --tags --always)"
export VERSION
(
cd osx
BUNDLE_PREFIX="$PWD/../stage/arm64/" \
ENCHANT_PREFIX="$PWD/../stage/arm64/opt/enchant" \
TARGET_ARCHES="arm64" \
./makebundle.sh
)
mv osx/ZoiteChat-*.app.zip ./ZoiteChat-arm64.app.zip
- name: Upload arm64 macOS app artifact
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-arm64
path: ZoiteChat-arm64.app.zip
if-no-files-found: error
retention-days: 14
macos_build_x86_64:
runs-on: macos-15-intel
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install build dependencies
run: |
set -eux
brew update
brew install \
meson ninja pkg-config gettext perl \
gtk+3 gdk-pixbuf pango adwaita-icon-theme \
hicolor-icon-theme glib dbus \
enchant gtk-mac-integration
if ! command -v gtk-mac-bundler >/dev/null 2>&1 && ! python3 -c 'import gtk_mac_bundler' >/dev/null 2>&1; then
curl -fsSL https://codeload.github.com/jralls/gtk-mac-bundler/tar.gz/refs/heads/master -o /tmp/gtk-mac-bundler.tar.gz
rm -rf /tmp/gtk-mac-bundler
mkdir -p /tmp/gtk-mac-bundler
tar -xzf /tmp/gtk-mac-bundler.tar.gz -C /tmp/gtk-mac-bundler --strip-components=1
(cd /tmp/gtk-mac-bundler && make install)
fi
- name: Configure and build (x86_64)
run: |
set -eux
rm -rf build-macos-x86_64 stage/x86_64
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson setup build-macos-x86_64 \
--prefix="$PWD/stage/x86_64" \
-Dgtk3=true \
-Dtext-frontend=true \
-Dlibcanberra=disabled \
-Ddarwin-arch-sanity-check=true \
-Dwith-perl=perl \
-Dwith-python=python3 \
-Dauto_features=enabled
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson compile -C build-macos-x86_64
meson install -C build-macos-x86_64
- name: Stage runtime dependencies for bundling (x86_64)
run: |
set -eux
STAGE_PREFIX="$PWD/stage/x86_64"
BREW_PREFIX="$(brew --prefix)"
ENCHANT_PREFIX="$(brew --prefix enchant)"
mkdir -p "$STAGE_PREFIX/lib" "$STAGE_PREFIX/share"
rsync -a "$BREW_PREFIX/lib/gtk-3.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/lib/gdk-pixbuf-2.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/share/locale/" "$STAGE_PREFIX/share/locale/"
mkdir -p "$STAGE_PREFIX/opt"
rm -rf "$STAGE_PREFIX/opt/enchant"
rsync -aL "$ENCHANT_PREFIX/" "$STAGE_PREFIX/opt/enchant/"
- name: Package unsigned .app (x86_64)
run: |
set -eux
VERSION="$(git describe --tags --always)"
export VERSION
(
cd osx
BUNDLE_PREFIX="$PWD/../stage/x86_64/" \
ENCHANT_PREFIX="$PWD/../stage/x86_64/opt/enchant" \
TARGET_ARCHES="x86_64" \
./makebundle.sh
)
mv osx/ZoiteChat-*.app.zip ./ZoiteChat-x86_64.app.zip
- name: Upload x86_64 macOS app artifact
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-x86_64
path: ZoiteChat-x86_64.app.zip
if-no-files-found: error
retention-days: 14
macos_assemble_universal_unsigned:
needs:
- macos_build_arm64
- macos_build_x86_64
runs-on: macos-latest
steps:
- name: Download arm64 app artifact
uses: actions/download-artifact@v4
with:
name: zoitechat-macos-arm64
path: dist/arm64
- name: Download x86_64 app artifact
uses: actions/download-artifact@v4
with:
name: zoitechat-macos-x86_64
path: dist/x86_64
- name: Merge app bundles into universal
run: |
set -eux
unzip -q dist/arm64/ZoiteChat-arm64.app.zip -d dist/arm64
unzip -q dist/x86_64/ZoiteChat-x86_64.app.zip -d dist/x86_64
ARM_APP="$(find dist/arm64 -maxdepth 2 -name 'ZoiteChat.app' -type d | head -n 1)"
X86_APP="$(find dist/x86_64 -maxdepth 2 -name 'ZoiteChat.app' -type d | head -n 1)"
UNIVERSAL_APP="dist/universal/ZoiteChat.app"
rm -rf "$UNIVERSAL_APP"
mkdir -p dist/universal
cp -a "$ARM_APP" "$UNIVERSAL_APP"
while IFS= read -r relpath; do
arm_file="$ARM_APP/$relpath"
x86_file="$X86_APP/$relpath"
out_file="$UNIVERSAL_APP/$relpath"
if [ -f "$x86_file" ] && file -b "$arm_file" | grep -q 'Mach-O'; then
mkdir -p "$(dirname "$out_file")"
lipo -create "$arm_file" "$x86_file" -output "$out_file"
fi
done < <(cd "$ARM_APP" && find . -type f | sed 's|^./||')
while IFS= read -r macho_path; do
archs="$(lipo -archs "$macho_path")"
echo "$macho_path -> $archs"
echo " $archs " | grep -q ' arm64 '
echo " $archs " | grep -q ' x86_64 '
done < <(find "$UNIVERSAL_APP" -type f -exec sh -c 'file -b "$1" | grep -q "Mach-O" && printf "%s\n" "$1"' _ {} \;)
VERSION="$(git -C "$GITHUB_WORKSPACE" describe --tags --always)"
ditto -c -k --sequesterRsrc --keepParent "$UNIVERSAL_APP" "dist/ZoiteChat-$VERSION.app.zip"
- name: Upload unsigned macOS app artifact
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-unsigned
path: dist/ZoiteChat-*.app.zip
if-no-files-found: error
retention-days: 14
macos_release_signed:
needs: macos_assemble_universal_unsigned
runs-on: macos-latest
if: >-
github.event_name == 'push' &&
github.ref == 'refs/heads/master'
steps:
- name: Check signing secrets availability
id: signing_secrets
env:
APPLE_DEVELOPER_ID_APPLICATION: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION }}
APPLE_DEVELOPER_ID_CERT_P12: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12 }}
APPLE_DEVELOPER_ID_CERT_P12_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12_PASSWORD }}
APPLE_NOTARY_API_KEY: ${{ secrets.APPLE_NOTARY_API_KEY }}
APPLE_NOTARY_API_KEY_ID: ${{ secrets.APPLE_NOTARY_API_KEY_ID }}
APPLE_NOTARY_ISSUER_ID: ${{ secrets.APPLE_NOTARY_ISSUER_ID }}
run: |
set -eu
required_secrets=(
APPLE_DEVELOPER_ID_APPLICATION
APPLE_DEVELOPER_ID_CERT_P12
APPLE_DEVELOPER_ID_CERT_P12_PASSWORD
APPLE_NOTARY_API_KEY
APPLE_NOTARY_API_KEY_ID
APPLE_NOTARY_ISSUER_ID
)
missing=0
for key in "${required_secrets[@]}"; do
if [ -z "${!key:-}" ]; then
echo "Missing secret: $key"
missing=1
fi
done
if [ "$missing" -eq 1 ]; then
echo "ready=false" >> "$GITHUB_OUTPUT"
else
echo "ready=true" >> "$GITHUB_OUTPUT"
fi
- name: Skip signing because required secrets are missing
if: steps.signing_secrets.outputs.ready != 'true'
run: echo "Signing and notarization skipped due to missing required secrets."
- name: Download unsigned app artifact
if: steps.signing_secrets.outputs.ready == 'true'
uses: actions/download-artifact@v4
with:
name: zoitechat-macos-unsigned
path: dist
- name: Import Developer ID certificate
if: steps.signing_secrets.outputs.ready == 'true'
env:
CERT_P12_BASE64: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12 }}
CERT_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12_PASSWORD }}
run: |
set -eux
echo "$CERT_P12_BASE64" | base64 --decode > certificate.p12
security create-keychain -p "" build.keychain
security set-keychain-settings -lut 21600 build.keychain
security unlock-keychain -p "" build.keychain
security import certificate.p12 -k build.keychain -P "$CERT_PASSWORD" -A -T /usr/bin/codesign
security list-keychains -d user -s build.keychain $(security list-keychains -d user | tr -d '"')
security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
- name: Codesign app bundle
if: steps.signing_secrets.outputs.ready == 'true'
env:
CODESIGN_IDENTITY: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION }}
run: |
set -eux
unzip -q dist/ZoiteChat-*.app.zip -d dist
APP_PATH="$(find dist -maxdepth 1 -name 'ZoiteChat.app' -type d | head -n 1)"
codesign --force --deep --options runtime --timestamp \
--sign "$CODESIGN_IDENTITY" "$APP_PATH"
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
spctl --assess --type execute --verbose "$APP_PATH"
- name: Notarize and staple
if: steps.signing_secrets.outputs.ready == 'true'
env:
NOTARY_API_KEY_BASE64: ${{ secrets.APPLE_NOTARY_API_KEY }}
NOTARY_KEY_ID: ${{ secrets.APPLE_NOTARY_API_KEY_ID }}
NOTARY_ISSUER_ID: ${{ secrets.APPLE_NOTARY_ISSUER_ID }}
run: |
set -eux
APP_PATH="$(find dist -maxdepth 1 -name 'ZoiteChat.app' -type d | head -n 1)"
NOTARY_ZIP="dist/ZoiteChat-notarize.zip"
SIGNED_ZIP="dist/ZoiteChat-signed.app.zip"
echo "$NOTARY_API_KEY_BASE64" | base64 --decode > AuthKey_${NOTARY_KEY_ID}.p8
ditto -c -k --keepParent "$APP_PATH" "$NOTARY_ZIP"
xcrun notarytool submit "$NOTARY_ZIP" \
--key "AuthKey_${NOTARY_KEY_ID}.p8" \
--key-id "$NOTARY_KEY_ID" \
--issuer "$NOTARY_ISSUER_ID" \
--wait
xcrun stapler staple "$APP_PATH"
xcrun stapler validate "$APP_PATH"
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$SIGNED_ZIP"
- name: Upload signed macOS app artifact
if: steps.signing_secrets.outputs.ready == 'true'
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-signed
path: dist/ZoiteChat-signed.app.zip
if-no-files-found: error
retention-days: 30

118
.github/workflows/openbsd-build.yml vendored Normal file
View File

@@ -0,0 +1,118 @@
name: OpenBSD Build
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
openbsd_package:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Build OpenBSD package
uses: vmactions/openbsd-vm@v1
with:
release: '7.5'
usesh: true
sync: rsync
run: |
set -eux
rdate -n pool.ntp.org
export PKG_PATH="https://ftp.openbsd.org/pub/OpenBSD/7.5/packages/$(uname -m)/"
pkg_add -U \
git \
meson ninja pkgconf gmake \
gettext-tools \
glib2 gtk+3 dbus-glib libcanberra \
luajit mono libgdiplus openssl
work="$(mktemp -d /tmp/zoitechat.XXXXXX)"
trap 'rm -rf "$work"' EXIT
rsync -a --delete "$GITHUB_WORKSPACE"/ "$work/src/"
cd "$work/src"
rm -rf build
meson setup build \
--prefix=/usr/local \
-Dtext-frontend=true \
-Dgtk3=true \
-Dplugin=false \
-Dauto_features=enabled
ninja -C build
staging="$work/staging"
rm -rf "$staging"
mkdir -p "$staging"
# Staged install
DESTDIR="$staging" meson install -C build --no-rebuild
# If these exist, something ignored DESTDIR (install scripts are leaking)
ls -l /usr/local/bin/zoitechat /usr/local/bin/thememan 2>/dev/null || true
sync
sleep 1
sync
# Freeze staged tree so pkg_create doesn't see moving targets
snap="$work/staging-snap"
rm -rf "$snap"
mkdir -p "$snap"
(cd "$staging" && pax -rw -pe . "$snap")
version="$(meson introspect --projectinfo build | sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
pkg_name="zoitechat-${version}"
pkg_file="${pkg_name}.tgz"
plist="$work/openbsd-plist"
desc="$work/DESCR"
cat >"$desc" <<'EOF'
ZoiteChat is an IRC client (HexChat-derived) with a GTK UI and optional tools.
EOF
{
echo "@cwd /usr/local"
# Files + symlinks
find "$snap/usr/local" \( -type f -o -type l \) -print \
| LC_ALL=C sort \
| sed "s#^$snap/usr/local/##"
# Directories (reverse so children removed first)
find "$snap/usr/local" -mindepth 1 -type d -print \
| LC_ALL=C sort -r \
| sed "s#^$snap/usr/local/##" \
| sed 's#^#@dir #'
} > "$plist"
# OpenBSD pkg_create: COMMENT is set via -D COMMENT=... (mandatory), no -c flag exists.
# Create the .tgz in $work so we can copy it back out.
cd "$work"
pkg_create \
-B "$snap" \
-p /usr/local \
-f "$plist" \
-d "$desc" \
-D "COMMENT=ZoiteChat IRC client" \
-D "FULLPKGPATH=net/zoitechat" \
"$pkg_file"
mkdir -p "$GITHUB_WORKSPACE/artifacts"
cp "$work/$pkg_file" "$GITHUB_WORKSPACE/artifacts/"
- name: Upload OpenBSD package
uses: actions/upload-artifact@v4
with:
name: openbsd-package
path: artifacts/*.tgz

View File

@@ -10,7 +10,7 @@ on:
solus_image:
description: "Solus container image"
required: false
default: "ghcr.io/getsolus/solus:latest"
default: "docker.io/silkeh/solus:latest"
push:
branches:
- main
@@ -24,7 +24,7 @@ jobs:
build-eopkg:
runs-on: ubuntu-latest
env:
SOLUS_IMAGE: ${{ inputs.solus_image || 'ghcr.io/getsolus/solus:latest' }}
SOLUS_IMAGE: ${{ inputs.solus_image || 'docker.io/silkeh/solus:latest' }}
PACKAGE_YML: ${{ inputs.package_yml || 'packaging/solus/package.yml' }}
steps:
- name: Checkout
@@ -48,7 +48,11 @@ jobs:
exit 1
fi
docker pull "$SOLUS_IMAGE"
if ! docker pull "$SOLUS_IMAGE"; then
echo "Failed to pull SOLUS_IMAGE=$SOLUS_IMAGE" >&2
echo "Set workflow input 'solus_image' to a valid image that provides eopkg/ypkg." >&2
exit 1
fi
docker run --rm \
-v "$PWD":/workspace \
@@ -58,7 +62,19 @@ jobs:
sh -lc '
set -euo pipefail
eopkg update-repo -y
eopkg install -y ypkg git
# Do not remove openssl-11 here: it can trigger a very large
# dependency cascade (including python3/eopkg itself), which
# breaks the build environment before package build starts.
# Some Solus base images still contain openssl-11 files that
# conflict with openssl 3.x when the package set is refreshed.
# Allowing file-conflict resolution keeps the CI image usable
# long enough to install ypkg and complete the package build.
# The base image does not guarantee Meson toolchain packages,
# while our package.yml setup phase calls meson directly.
# Install the essential build tools up front to avoid
# `/tmp/ypkg-setup*: meson: command not found` failures.
eopkg install -y --ignore-file-conflicts \
ypkg git meson ninja pkgconf gcc gettext
ypkg build "$PACKAGE_YML"
mkdir -p /workspace/artifacts
find . -maxdepth 3 -name "*.eopkg" -type f -exec cp -v {} /workspace/artifacts/ \;

View File

@@ -7,5 +7,5 @@
<url type="homepage">https://zoitechat.zoite.net/</url>
<project_license>@LICENSE@</project_license>
<metadata_license>CC0-1.0</metadata_license>
<update_contact>tingping_AT_fedoraproject.org</update_contact>
</component>
<update_contact>deepend_AT_zoite.net</update_contact>
</component>

View File

@@ -14,7 +14,7 @@
</description>
<url type="homepage">http://zoitechat.zoite.net</url>
<url type="bugtracker">https://github.com/zoitechat/zoitechat</url>
<url type="help">https://zoitechat.zoite.net/docs</url>
<url type="help">https://docs.zoitechat.zoite.net/en/latest/</url>
<screenshots>
<screenshot type="default">
<image>https://zoitechat.zoite.net/assets/ZoiteChat.png</image>

View File

@@ -22,61 +22,117 @@
<file alias="tree_util.png" preprocess="to-pixdata">icons/tree_util.png</file>
<file alias="menu/light/new.png" preprocess="to-pixdata">icons/menu/light/new.png</file>
<file alias="menu/light/new.svg">icons/menu/light/new.svg</file>
<file alias="menu/light/network-list.png" preprocess="to-pixdata">icons/menu/light/network-list.png</file>
<file alias="menu/light/network-list.svg">icons/menu/light/network-list.svg</file>
<file alias="menu/light/load-plugin.png" preprocess="to-pixdata">icons/menu/light/load-plugin.png</file>
<file alias="menu/light/load-plugin.svg">icons/menu/light/load-plugin.svg</file>
<file alias="menu/light/detach.png" preprocess="to-pixdata">icons/menu/light/detach.png</file>
<file alias="menu/light/detach.svg">icons/menu/light/detach.svg</file>
<file alias="menu/light/close.png" preprocess="to-pixdata">icons/menu/light/close.png</file>
<file alias="menu/light/close.svg">icons/menu/light/close.svg</file>
<file alias="menu/light/quit.png" preprocess="to-pixdata">icons/menu/light/quit.png</file>
<file alias="menu/light/quit.svg">icons/menu/light/quit.svg</file>
<file alias="menu/light/disconnect.png" preprocess="to-pixdata">icons/menu/light/disconnect.png</file>
<file alias="menu/light/disconnect.svg">icons/menu/light/disconnect.svg</file>
<file alias="menu/light/connect.png" preprocess="to-pixdata">icons/menu/light/connect.png</file>
<file alias="menu/light/connect.svg">icons/menu/light/connect.svg</file>
<file alias="menu/light/join.png" preprocess="to-pixdata">icons/menu/light/join.png</file>
<file alias="menu/light/join.svg">icons/menu/light/join.svg</file>
<file alias="menu/light/chanlist.png" preprocess="to-pixdata">icons/menu/light/chanlist.png</file>
<file alias="menu/light/chanlist.svg">icons/menu/light/chanlist.svg</file>
<file alias="menu/light/preferences.png" preprocess="to-pixdata">icons/menu/light/preferences.png</file>
<file alias="menu/light/preferences.svg">icons/menu/light/preferences.svg</file>
<file alias="menu/light/clear.png" preprocess="to-pixdata">icons/menu/light/clear.png</file>
<file alias="menu/light/clear.svg">icons/menu/light/clear.svg</file>
<file alias="menu/light/copy.png" preprocess="to-pixdata">icons/menu/light/copy.png</file>
<file alias="menu/light/copy.svg">icons/menu/light/copy.svg</file>
<file alias="menu/light/delete.png" preprocess="to-pixdata">icons/menu/light/delete.png</file>
<file alias="menu/light/delete.svg">icons/menu/light/delete.svg</file>
<file alias="menu/light/add.png" preprocess="to-pixdata">icons/menu/light/add.png</file>
<file alias="menu/light/add.svg">icons/menu/light/add.svg</file>
<file alias="menu/light/remove.png" preprocess="to-pixdata">icons/menu/light/remove.png</file>
<file alias="menu/light/remove.svg">icons/menu/light/remove.svg</file>
<file alias="menu/light/spell-check.png" preprocess="to-pixdata">icons/menu/light/spell-check.png</file>
<file alias="menu/light/spell-check.svg">icons/menu/light/spell-check.svg</file>
<file alias="menu/light/save.png" preprocess="to-pixdata">icons/menu/light/save.png</file>
<file alias="menu/light/save.svg">icons/menu/light/save.svg</file>
<file alias="menu/light/save-as.png" preprocess="to-pixdata">icons/menu/light/save-as.png</file>
<file alias="menu/light/save-as.svg">icons/menu/light/save-as.svg</file>
<file alias="menu/light/refresh.png" preprocess="to-pixdata">icons/menu/light/refresh.png</file>
<file alias="menu/light/refresh.svg">icons/menu/light/refresh.svg</file>
<file alias="menu/light/search.png" preprocess="to-pixdata">icons/menu/light/search.png</file>
<file alias="menu/light/search.svg">icons/menu/light/search.svg</file>
<file alias="menu/light/find.png" preprocess="to-pixdata">icons/menu/light/find.png</file>
<file alias="menu/light/find.svg">icons/menu/light/find.svg</file>
<file alias="menu/light/previous.png" preprocess="to-pixdata">icons/menu/light/previous.png</file>
<file alias="menu/light/previous.svg">icons/menu/light/previous.svg</file>
<file alias="menu/light/next.png" preprocess="to-pixdata">icons/menu/light/next.png</file>
<file alias="menu/light/next.svg">icons/menu/light/next.svg</file>
<file alias="menu/light/help.png" preprocess="to-pixdata">icons/menu/light/help.png</file>
<file alias="menu/light/help.svg">icons/menu/light/help.svg</file>
<file alias="menu/light/about.png" preprocess="to-pixdata">icons/menu/light/about.png</file>
<file alias="menu/light/about.svg">icons/menu/light/about.svg</file>
<file alias="menu/light/update.png" preprocess="to-pixdata">icons/menu/light/update.png</file>
<file alias="menu/light/update.svg">icons/menu/light/update.svg</file>
<file alias="menu/light/emoji.png" preprocess="to-pixdata">icons/menu/light/emoji.png</file>
<file alias="menu/light/emoji.svg">icons/menu/light/emoji.svg</file>
<file alias="menu/dark/new.png" preprocess="to-pixdata">icons/menu/dark/new.png</file>
<file alias="menu/dark/new.svg">icons/menu/dark/new.svg</file>
<file alias="menu/dark/network-list.png" preprocess="to-pixdata">icons/menu/dark/network-list.png</file>
<file alias="menu/dark/network-list.svg">icons/menu/dark/network-list.svg</file>
<file alias="menu/dark/load-plugin.png" preprocess="to-pixdata">icons/menu/dark/load-plugin.png</file>
<file alias="menu/dark/load-plugin.svg">icons/menu/dark/load-plugin.svg</file>
<file alias="menu/dark/detach.png" preprocess="to-pixdata">icons/menu/dark/detach.png</file>
<file alias="menu/dark/detach.svg">icons/menu/dark/detach.svg</file>
<file alias="menu/dark/close.png" preprocess="to-pixdata">icons/menu/dark/close.png</file>
<file alias="menu/dark/close.svg">icons/menu/dark/close.svg</file>
<file alias="menu/dark/quit.png" preprocess="to-pixdata">icons/menu/dark/quit.png</file>
<file alias="menu/dark/quit.svg">icons/menu/dark/quit.svg</file>
<file alias="menu/dark/disconnect.png" preprocess="to-pixdata">icons/menu/dark/disconnect.png</file>
<file alias="menu/dark/disconnect.svg">icons/menu/dark/disconnect.svg</file>
<file alias="menu/dark/connect.png" preprocess="to-pixdata">icons/menu/dark/connect.png</file>
<file alias="menu/dark/connect.svg">icons/menu/dark/connect.svg</file>
<file alias="menu/dark/join.png" preprocess="to-pixdata">icons/menu/dark/join.png</file>
<file alias="menu/dark/join.svg">icons/menu/dark/join.svg</file>
<file alias="menu/dark/chanlist.png" preprocess="to-pixdata">icons/menu/dark/chanlist.png</file>
<file alias="menu/dark/chanlist.svg">icons/menu/dark/chanlist.svg</file>
<file alias="menu/dark/preferences.png" preprocess="to-pixdata">icons/menu/dark/preferences.png</file>
<file alias="menu/dark/preferences.svg">icons/menu/dark/preferences.svg</file>
<file alias="menu/dark/clear.png" preprocess="to-pixdata">icons/menu/dark/clear.png</file>
<file alias="menu/dark/clear.svg">icons/menu/dark/clear.svg</file>
<file alias="menu/dark/copy.png" preprocess="to-pixdata">icons/menu/dark/copy.png</file>
<file alias="menu/dark/copy.svg">icons/menu/dark/copy.svg</file>
<file alias="menu/dark/delete.png" preprocess="to-pixdata">icons/menu/dark/delete.png</file>
<file alias="menu/dark/delete.svg">icons/menu/dark/delete.svg</file>
<file alias="menu/dark/add.png" preprocess="to-pixdata">icons/menu/dark/add.png</file>
<file alias="menu/dark/add.svg">icons/menu/dark/add.svg</file>
<file alias="menu/dark/remove.png" preprocess="to-pixdata">icons/menu/dark/remove.png</file>
<file alias="menu/dark/remove.svg">icons/menu/dark/remove.svg</file>
<file alias="menu/dark/spell-check.png" preprocess="to-pixdata">icons/menu/dark/spell-check.png</file>
<file alias="menu/dark/spell-check.svg">icons/menu/dark/spell-check.svg</file>
<file alias="menu/dark/save.png" preprocess="to-pixdata">icons/menu/dark/save.png</file>
<file alias="menu/dark/save.svg">icons/menu/dark/save.svg</file>
<file alias="menu/dark/save-as.png" preprocess="to-pixdata">icons/menu/dark/save-as.png</file>
<file alias="menu/dark/save-as.svg">icons/menu/dark/save-as.svg</file>
<file alias="menu/dark/refresh.png" preprocess="to-pixdata">icons/menu/dark/refresh.png</file>
<file alias="menu/dark/refresh.svg">icons/menu/dark/refresh.svg</file>
<file alias="menu/dark/search.png" preprocess="to-pixdata">icons/menu/dark/search.png</file>
<file alias="menu/dark/search.svg">icons/menu/dark/search.svg</file>
<file alias="menu/dark/find.png" preprocess="to-pixdata">icons/menu/dark/find.png</file>
<file alias="menu/dark/find.svg">icons/menu/dark/find.svg</file>
<file alias="menu/dark/previous.png" preprocess="to-pixdata">icons/menu/dark/previous.png</file>
<file alias="menu/dark/previous.svg">icons/menu/dark/previous.svg</file>
<file alias="menu/dark/next.png" preprocess="to-pixdata">icons/menu/dark/next.png</file>
<file alias="menu/dark/next.svg">icons/menu/dark/next.svg</file>
<file alias="menu/dark/help.png" preprocess="to-pixdata">icons/menu/dark/help.png</file>
<file alias="menu/dark/help.svg">icons/menu/dark/help.svg</file>
<file alias="menu/dark/about.png" preprocess="to-pixdata">icons/menu/dark/about.png</file>
<file alias="menu/dark/about.svg">icons/menu/dark/about.svg</file>
<file alias="menu/dark/update.png" preprocess="to-pixdata">icons/menu/dark/update.png</file>
<file alias="menu/dark/update.svg">icons/menu/dark/update.svg</file>
<file alias="menu/dark/emoji.png" preprocess="to-pixdata">icons/menu/dark/emoji.png</file>
<file alias="menu/dark/emoji.svg">icons/menu/dark/emoji.svg</file>
</gresource>
</gresources>

View File

@@ -1,6 +1,6 @@
{
"app-id": "net.zoite.Zoitechat",
"branch": "stable",
"branch": "master",
"runtime": "org.gnome.Platform",
"runtime-version": "49",
"sdk": "org.gnome.Sdk",
@@ -11,6 +11,10 @@
"--share=network",
"--socket=pulseaudio",
"--filesystem=xdg-download",
"--filesystem=xdg-data/themes:ro",
"--filesystem=xdg-data/icons:ro",
"--filesystem=~/.themes:ro",
"--filesystem=~/.icons:ro",
"--talk-name=org.freedesktop.Notifications",
@@ -18,7 +22,7 @@
],
"add-extensions": {
"net.zoite.Zoitechat.Plugin": {
"version": "20.08",
"version": "49",
"directory": "extensions",
"add-ld-path": "lib",
"merge-dirs": "lib/zoitechat/plugins",
@@ -29,7 +33,7 @@
},
"modules": [
"shared-modules/dbus-glib/dbus-glib.json",
"shared-modules/lua5.3/lua-5.3.5.json",
"shared-modules/lua5.4/lua-5.4.json",
"shared-modules/libcanberra/libcanberra.json",
"shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json",
"python3-cffi.json",
@@ -40,7 +44,7 @@
{
"type": "git",
"url": "https://github.com/pavouk/lgi.git",
"commit": "95418635aa8151a516d43166227ea2b9d4c4403f"
"commit": "c9b8e4473c6421f2a215d8c06c0d94b86eb0b26a"
}
]
},
@@ -48,7 +52,6 @@
"name": "zoitechat",
"buildsystem": "meson",
"config-opts": [
"--buildtype=release",
"-Dgtk3=true",
"-Ddbus-service-use-appid=true",
"-Dwith-perl=false",
@@ -56,7 +59,7 @@
"-Dwith-lua=lua"
],
"build-options": {
"cflags": "-Wno-error=missing-include-dirs"
"cflags": "-Dgtk3=true -Wno-error=missing-include-dirs"
},
"cleanup": [
"/share/man"

View File

@@ -10,7 +10,6 @@ project('zoitechat', 'c',
i18n = import('i18n')
gnome = import('gnome')
fs = import('fs')
cc = meson.get_compiler('c')
@@ -19,14 +18,7 @@ libgmodule_dep = dependency('gmodule-2.0')
libcanberra_dep = dependency('libcanberra', version: '>= 0.22',
required: get_option('libcanberra'))
dbus_required = get_option('dbus')
if host_machine.system() == 'darwin'
if dbus_required.enabled()
warning('dbus-glib is not available on macOS; disabling DBus support')
endif
dbus_required = false
endif
dbus_glib_dep = dependency('dbus-glib-1', required: dbus_required)
dbus_glib_dep = dependency('dbus-glib-1', required: get_option('dbus'))
global_deps = []
if cc.get_id() == 'msvc'
@@ -36,82 +28,6 @@ else
required: get_option('tls'))
endif
darwin_arch_sanity_check = get_option('darwin-arch-sanity-check')
if host_machine.system() == 'darwin' and darwin_arch_sanity_check
darwin_arch_sanity_check_env = run_command('sh', '-c', 'printf %s "$ZOITECHAT_DARWIN_ARCH_SANITY_CHECK"', check: false).stdout().strip().to_lower()
if ['0', 'false', 'no', 'off'].contains(darwin_arch_sanity_check_env)
darwin_arch_sanity_check = false
endif
endif
if host_machine.system() == 'darwin' and darwin_arch_sanity_check
cflags_env = run_command('sh', '-c', 'printf %s "$CFLAGS"', check: false).stdout().strip()
ldflags_env = run_command('sh', '-c', 'printf %s "$LDFLAGS"', check: false).stdout().strip()
c_args_opt = ' ' + ' '.join(get_option('c_args')) + ' '
c_link_args_opt = ' ' + ' '.join(get_option('c_link_args')) + ' '
all_cflags = cflags_env + ' ' + c_args_opt
all_ldflags = ldflags_env + ' ' + c_link_args_opt
pkgconfig_glib = run_command('pkg-config', '--libs-only-L', 'glib-2.0', check: false)
targeting_x86_64 = all_cflags.contains('-arch x86_64') or all_ldflags.contains('-arch x86_64')
targeting_arm64 = all_cflags.contains('-arch arm64') or all_ldflags.contains('-arch arm64')
targeting_universal = targeting_x86_64 and targeting_arm64
using_arm_homebrew = pkgconfig_glib.returncode() == 0 and pkgconfig_glib.stdout().contains('/opt/homebrew/')
if targeting_x86_64 and not targeting_universal and using_arm_homebrew
error('Detected x86_64 build flags (-arch x86_64) while pkg-config resolves glib from /opt/homebrew (arm64). ' +
'Use arm64 build flags with /opt/homebrew, use a universal build (-arch arm64 -arch x86_64) with universal dependencies, or run an x86_64/Rosetta environment with an x86_64 dependency stack (typically /usr/local). ' +
'To bypass this safety check, configure with -Ddarwin-arch-sanity-check=false or set ZOITECHAT_DARWIN_ARCH_SANITY_CHECK=0.')
endif
if targeting_x86_64
# When building x86_64-only or universal binaries on Apple Silicon,
# pkg-config can still resolve arm64-only Homebrew libraries.
# Detect this at configure time and fail fast with a clear message.
macos_link_deps = [
['gio-2.0', 'libgio-2.0.dylib'],
['gobject-2.0', 'libgobject-2.0.dylib'],
['glib-2.0', 'libglib-2.0.dylib'],
['gmodule-2.0', 'libgmodule-2.0.dylib'],
['openssl', 'libssl.dylib'],
['openssl', 'libcrypto.dylib'],
['libintl', 'libintl.dylib'],
]
foreach dep_spec : macos_link_deps
dep_pkg = dep_spec[0]
dep_lib = dep_spec[1]
dep_libdir_cmd = run_command('pkg-config', '--libs-only-L', dep_pkg, check: false)
if dep_libdir_cmd.returncode() != 0
continue
endif
foreach dep_libdir_arg : dep_libdir_cmd.stdout().strip().split()
if not dep_libdir_arg.startswith('-L')
continue
endif
dep_lib_path = join_paths(dep_libdir_arg.substring(2), dep_lib)
if not fs.exists(dep_lib_path)
continue
endif
dep_archs = run_command('lipo', '-archs', dep_lib_path, check: false)
if dep_archs.returncode() != 0
continue
endif
if not dep_archs.stdout().contains('x86_64')
error('Detected x86_64 build flags, but dependency ' + dep_lib_path +
' does not contain x86_64 architecture (archs: ' + dep_archs.stdout().strip() + '). ' +
'Use dependencies that include x86_64 (or universal) slices, or build only arm64. ' +
'To bypass this safety check, configure with -Ddarwin-arch-sanity-check=false or set ZOITECHAT_DARWIN_ARCH_SANITY_CHECK=0.')
endif
endforeach
endforeach
endif
endif
config_h = configuration_data()
config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
config_h.set_quoted('PACKAGE_NAME', meson.project_name())

View File

@@ -22,9 +22,6 @@ option('dbus', type: 'feature', value: 'auto',
option('libcanberra', type: 'feature', value: 'auto',
description: 'Support for sound alerts, Unix only'
)
option('darwin-arch-sanity-check', type: 'boolean', value: true,
description: 'Fail fast when macOS build flags and Homebrew dependency architectures are mixed'
)
# Install options
option('dbus-service-use-appid', type: 'boolean', value: false,

View File

@@ -3,24 +3,16 @@
import os
import sys
import subprocess
import shutil
prefix = os.environ.get('MESON_INSTALL_PREFIX', '/usr/local')
datadir = os.path.join(prefix, 'share')
# Packaging tools define DESTDIR and this isn't needed for them
if 'DESTDIR' not in os.environ:
def run_if_available(command, *args):
if shutil.which(command) is None:
print(f'Skipping {command}: command not found')
return
subprocess.call([command, *args])
print('Updating icon cache...')
run_if_available('gtk-update-icon-cache', '-qtf',
os.path.join(datadir, 'icons', 'hicolor'))
subprocess.call(['gtk-update-icon-cache', '-qtf',
os.path.join(datadir, 'icons', 'hicolor')])
print('Updating desktop database...')
run_if_available('update-desktop-database', '-q',
os.path.join(datadir, 'applications'))
subprocess.call(['update-desktop-database', '-q',
os.path.join(datadir, 'applications')])

View File

@@ -1,207 +0,0 @@
# Debugging ZoiteChat on macOS (Xcode + CLI)
If the unsigned `.app` launches but does nothing (or immediately exits), use the steps below to get actionable logs and a debugger session.
## 1) Build with debug symbols
ZoiteChat uses Meson. Build a debug configuration first so LLDB can show useful backtraces.
```bash
meson setup build-macos-debug --buildtype=debug
meson compile -C build-macos-debug
```
This project default is `debugoptimized`, but a full `debug` build is better while diagnosing crashes/startup issues.
## 2) Bundle the app and verify deployment target
Use the existing bundle script:
```bash
cd osx
./makebundle.sh
```
The generated `Info.plist` should keep:
- `LSMinimumSystemVersion = 11.0`
That is the projects explicit minimum runtime target for macOS 11+.
## 3) Sanity-check the Mach-O binary in the bundle
Confirm architecture(s), deployment target, and linked libraries:
```bash
file ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
otool -l ZoiteChat.app/Contents/MacOS/ZoiteChat-bin | rg -n "LC_BUILD_VERSION|minos|sdk"
otool -L ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
```
For widest compatibility, build universal (`arm64` + `x86_64`) or build separately per arch and test each on matching hosts.
## 4) Ad-hoc sign for local debugging
Unsigned GUI binaries can fail in unhelpful ways because of hardened runtime/quarantine/Gatekeeper interactions. For local debugging, ad-hoc sign the app:
```bash
xattr -dr com.apple.quarantine ZoiteChat.app
codesign --force --deep --sign - ZoiteChat.app
codesign --verify --deep --strict --verbose=2 ZoiteChat.app
```
## 5) Launch from Terminal first (before Xcode)
Direct launch exposes stdout/stderr and validates the launcher environment:
```bash
./ZoiteChat.app/Contents/MacOS/ZoiteChat
```
The launcher script sets GTK/Pango/GDK environment variables. If direct launch fails, capture that output first.
## 6) Debug with LLDB (reliable baseline)
Debug the real executable inside the bundle:
```bash
lldb -- ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
(lldb) run
(lldb) bt
```
If it exits instantly, set breakpoints on startup entry points (for example `main`) and re-run.
## 7) Debug with Xcode (if you prefer GUI)
Xcode works best when opening the executable directly instead of importing build scripts.
1. **File → Open…** and select `ZoiteChat.app/Contents/MacOS/ZoiteChat-bin`.
2. In **Product → Scheme → Edit Scheme…**
- Executable: `ZoiteChat-bin`
- Working directory: repo root (or `osx/`)
- Add environment variables equivalent to the launcher if needed.
3. Run under debugger.
If Xcode “runs” but no UI appears, compare its environment to `osx/launcher.sh` and copy missing GTK-related variables into the scheme.
## 8) Capture macOS crash diagnostics
Even if no dialog appears, macOS usually logs termination reasons:
```bash
log stream --style compact --predicate 'process == "ZoiteChat-bin"'
```
Also check:
- `~/Library/Logs/DiagnosticReports/`
## 9) Frequent root causes for “silent” startup failures
- Missing GTK runtime libraries in app bundle (`otool -L` shows unresolved paths).
- Incorrect `@rpath`/install names after bundling.
- Running under Rosetta mismatch (x86_64 binary with arm64-only deps or vice versa).
- Quarantine/signature issues on unsigned artifacts.
- Missing `GDK_PIXBUF_MODULE_FILE`, `GTK_IM_MODULE_FILE`, or schema paths.
### "Bad CPU type in executable"
This means the bundled `ZoiteChat-bin` architecture does not match the Mac you are running on.
- Intel Mac requires `x86_64`
- Apple Silicon requires `arm64` (or Rosetta + `x86_64`)
Check the binary quickly:
```bash
file ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
```
Build for Intel explicitly when needed:
```bash
export CFLAGS="-arch x86_64"
export LDFLAGS="-arch x86_64"
meson setup build-macos-intel --buildtype=debug
meson compile -C build-macos-intel
```
If your dependency stack supports it, build universal (`arm64` + `x86_64`) and verify with `lipo -info`.
### Linker says `found architecture 'arm64', required architecture 'x86_64'`
If you see warnings like this during `meson compile`:
```text
ld: warning: ignoring file '/opt/homebrew/.../libgio-2.0.dylib': found architecture 'arm64', required architecture 'x86_64'
Undefined symbols for architecture x86_64: ...
```
your compile target architecture and dependency architecture do not match.
On Apple Silicon, this usually means you are trying to build `x86_64` while linking against ARM Homebrew libraries from `/opt/homebrew`.
Quick checks:
```bash
echo "$CFLAGS" "$LDFLAGS"
pkg-config --libs glib-2.0
lipo -info "$(brew --prefix glib)/lib/libglib-2.0.dylib"
```
Use one of these consistent setups:
- Native Apple Silicon build (`arm64`) with `/opt/homebrew` dependencies.
- Intel build (`x86_64`) with an x86_64 dependency stack (typically Homebrew under `/usr/local` run under Rosetta).
Example x86_64 setup on Apple Silicon:
```bash
# Open a Rosetta shell first (or prefix commands with `arch -x86_64`)
arch -x86_64 /bin/bash -lc '
export PATH="/usr/local/bin:$PATH"
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig"
export CFLAGS="-arch x86_64"
export LDFLAGS="-arch x86_64"
meson setup build-macos-x86_64 --prefix="/usr/local"
meson compile -C build-macos-x86_64
'
```
If you do not specifically need Intel compatibility, remove any forced `-arch x86_64` flags and build native `arm64`.
Example with this repo's scripts:
```bash
PREFIX="$(brew --prefix)"
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson setup build-macos-arm64 --prefix="$PREFIX"
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson setup build-macos-x86_64 --prefix="$PREFIX"
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson compile -C build-macos-arm64
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson compile -C build-macos-x86_64
sudo meson install -C build-macos-arm64
cd osx
UNIVERSAL=1 \
UNIVERSAL_BINARIES="../build-macos-arm64/src/fe-gtk/zoitechat ../build-macos-x86_64/src/fe-gtk/zoitechat" \
./makebundle.sh
```
## 10) Recommended compatibility settings for macOS 11+
- Keep `LSMinimumSystemVersion` at `11.0`.
- Build on the oldest macOS SDK/toolchain that still supports your dependencies, or explicitly set:
```bash
export MACOSX_DEPLOYMENT_TARGET=11.0
```
- Verify with `otool -l` that `minos` is actually `11.0` in the final executable.
---
If you want, we can add an Xcode scheme file to this repo that mirrors `osx/launcher.sh` so “Run” in Xcode behaves exactly like launching the app bundle from Finder/Terminal.

View File

@@ -11,7 +11,7 @@
<key>CFBundleIconFile</key>
<string>zoitechat.icns</string>
<key>CFBundleIdentifier</key>
<string>net.zoite.Zoitechat</string>
<string>org.zoitechat</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
@@ -41,6 +41,6 @@
<key>NSHumanReadableCopyright</key>
<string></string>
<key>LSMinimumSystemVersion</key>
<string>11.0</string>
<string>10.4</string>
</dict>
</plist>

View File

@@ -1,13 +1,13 @@
#!/usr/bin/env bash
#!/bin/sh
if test "x$GTK_DEBUG_LAUNCHER" != x; then
set -x
fi
if test "x$GTK_DEBUG_GDB" != x; then
EXEC_PREFIX=(gdb --args)
EXEC="gdb --args"
else
EXEC_PREFIX=()
EXEC=exec
fi
name=`basename "$0"`
@@ -23,34 +23,24 @@ bundle_data="$bundle_res"/share
bundle_etc="$bundle_res"/etc
export PREFIX="$bundle_res"
# launcher-script: runtime environment for bundled GTK3 on macOS.
# Expected package prefixes when building the app bundle:
# Homebrew: /opt/homebrew (Apple Silicon) or /usr/local (Intel)
# MacPorts: /opt/local
# Required libraries include GTK3, Pango, GDK-Pixbuf and enchant.
# Keep DYLD path hacks to a minimum; install_name_tool should resolve most libs.
if test -n "${DYLD_LIBRARY_PATH:-}"; then
export DYLD_LIBRARY_PATH="$bundle_lib:$DYLD_LIBRARY_PATH"
fi
export DYLD_LIBRARY_PATH="$bundle_lib"
export XDG_CONFIG_DIRS="$bundle_etc"/xdg
export XDG_DATA_DIRS="$bundle_data"
export GTK_DATA_PREFIX="$bundle_res"
export GTK_EXE_PREFIX="$bundle_res"
export GTK_PATH="$bundle_res"
export GTK_IM_MODULE_FILE="$bundle_etc/gtk-3.0/gtk.immodules"
export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-3.0/gdk-pixbuf.loaders"
export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"
export PANGO_LIBDIR="$bundle_lib"
export PANGO_SYSCONFDIR="$bundle_etc"
export GSETTINGS_SCHEMA_DIR="$bundle_data/glib-2.0/schemas"
export OPENSSL_CONF="/System/Library/OpenSSL/openssl.cnf"
export ZOITECHAT_LIBDIR="$bundle_lib/zoitechat/plugins"
APP=zoitechat
APP=name
I18NDIR="$bundle_data/locale"
# Set the locale-related variables appropriately:
unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE
@@ -58,7 +48,7 @@ unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE
# Has a language ordering been set?
# If so, set LC_MESSAGES and LANG accordingly; otherwise skip it.
# First step uses sed to clean off the quotes and commas, to change - to _, and change the names for the chinese scripts from "Hans" to CN and "Hant" to TW.
APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages 2>/dev/null | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' `
APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' `
if test "$APPLELANGUAGES"; then
# A language ordering exists.
# Test, item per item, to see whether there is an corresponding locale.
@@ -89,26 +79,26 @@ fi
unset APPLELANGUAGES L
# If we didn't get a language from the language list, try the Collation preference, in case it's the only setting that exists.
APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null || true`
if test -z "${LANG:-}" -a -n "${APPLECOLLATION:-}"; then
APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder`
if test -z ${LANG} -a -n $APPLECOLLATION; then
if test -f "$I18NDIR/${APPLECOLLATION:0:2}/LC_MESSAGES/$APP.mo"; then
export LANG=${APPLECOLLATION:0:2}
fi
fi
if test -n "${APPLECOLLATION:-}"; then
if test ! -z $APPLECOLLATION; then
export LC_COLLATE=$APPLECOLLATION
fi
unset APPLECOLLATION
# Continue by attempting to find the Locale preference.
APPLELOCALE=`defaults read .GlobalPreferences AppleLocale 2>/dev/null || true`
APPLELOCALE=`defaults read .GlobalPreferences AppleLocale`
if test -f "$I18NDIR/${APPLELOCALE:0:5}/LC_MESSAGES/$APP.mo"; then
if test -z "${LANG:-}"; then
if test -z $LANG; then
export LANG="${APPLELOCALE:0:5}"
fi
elif test -z "${LANG:-}" -a -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then
elif test -z $LANG -a -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then
export LANG="${APPLELOCALE:0:2}"
fi
@@ -116,20 +106,20 @@ fi
#5-character locale to avoid the "Locale not supported by C library"
#warning from Gtk -- even though Gtk will translate with a
#two-character code.
if test -n "${LANG:-}"; then
if test -n $LANG; then
#If the language code matches the applelocale, then that's the message
#locale; otherwise, if it's longer than two characters, then it's
#probably a good message locale and we'll go with it.
if test "$LANG" = "${APPLELOCALE:0:5}" -o "$LANG" != "${LANG:0:2}"; then
if test $LANG == ${APPLELOCALE:0:5} -o $LANG != ${LANG:0:2}; then
export LC_MESSAGES=$LANG
#Next try if the Applelocale is longer than 2 chars and the language
#bit matches $LANG
elif test "$LANG" = "${APPLELOCALE:0:2}" -a "$APPLELOCALE" \> "${APPLELOCALE:0:2}"; then
elif test $LANG == ${APPLELOCALE:0:2} -a $APPLELOCALE > ${APPLELOCALE:0:2}; then
export LC_MESSAGES=${APPLELOCALE:0:5}
#Fail. Get a list of the locales in $PREFIX/share/locale that match
#our two letter language code and pick the first one, special casing
#english to set en_US
elif test "$LANG" = "en"; then
elif test $LANG == "en"; then
export LC_MESSAGES="en_US"
else
LOC=`find $PREFIX/share/locale -name $LANG???`
@@ -181,18 +171,4 @@ if /bin/expr "x$1" : '^x-psn_' > /dev/null; then
shift 1
fi
BIN_PATH="$bundle_contents/MacOS/$name-bin"
if test ${#EXEC_PREFIX[@]} -gt 0; then
"${EXEC_PREFIX[@]}" "$BIN_PATH" "$@" $EXTRA_ARGS
else
"$BIN_PATH" "$@" $EXTRA_ARGS
fi
status=$?
if test "$status" -eq 126; then
echo "error: $BIN_PATH could not execute on this Mac (possible architecture mismatch)." >&2
if command -v file >/dev/null 2>&1; then
file "$BIN_PATH" >&2 || true
fi
echo "hint: build ZoiteChat for this architecture (x86_64 on Intel, arm64 on Apple Silicon) or as a universal binary." >&2
fi
exit "$status"
$EXEC "$bundle_contents/MacOS/$name-bin" "$@" $EXTRA_ARGS

View File

@@ -1,210 +1,11 @@
#!/bin/sh
set -eu
rm -rf ZoiteChat.app
rm -f *.app.zip
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
cd "$SCRIPT_DIR"
BUNDLE_DEF="zoitechat.bundle"
APP_NAME="ZoiteChat.app"
HOST_ARCH="$(uname -m 2>/dev/null || echo unknown)"
if [ -z "${TARGET_ARCHES+x}" ]; then
TARGET_ARCHES="$HOST_ARCH"
fi
UNIVERSAL_BINARIES="${UNIVERSAL_BINARIES:-}"
UNIVERSAL_BUILD_DIRS="${UNIVERSAL_BUILD_DIRS:-../build-macos-arm64 ../build-macos-x86_64}"
if [ "${UNIVERSAL:-0}" = "1" ]; then
TARGET_ARCHES="arm64 x86_64"
fi
# Expected prefixes for macOS GTK dependencies:
# - Homebrew: /opt/homebrew (Apple Silicon) or /usr/local (Intel)
# - MacPorts: /opt/local
# Required runtime stack includes GTK3, Pango, GDK-Pixbuf and enchant.
if command -v gtk-mac-bundler >/dev/null 2>&1; then
BUNDLER_CMD="gtk-mac-bundler"
elif command -v python3 >/dev/null 2>&1 && python3 -c 'import gtk_mac_bundler' >/dev/null 2>&1; then
BUNDLER_CMD="python3 -m gtk_mac_bundler"
else
cat >&2 <<'MSG'
error: gtk-mac-bundler not found.
Install one of the following before running osx/makebundle.sh:
- executable: gtk-mac-bundler
- python module: gtk_mac_bundler (invoked via: python3 -m gtk_mac_bundler)
MSG
exit 1
fi
rm -rf "$APP_NAME"
rm -f ./*.app.zip
# Enchant packaging changed between releases/package managers:
# - some installs provide share/enchant
# - others provide share/enchant-2
# - some have no share-level config dir at all
# Keep the bundle definition in sync with what's actually available so
# gtk-mac-bundler doesn't fail on a missing source path.
# Resolve package-manager prefix dynamically so Intel (/usr/local) and
# Apple Silicon (/opt/homebrew) hosts both bundle correctly.
BUNDLE_PREFIX="${BUNDLE_PREFIX:-}"
if [ -z "$BUNDLE_PREFIX" ] && command -v brew >/dev/null 2>&1; then
BUNDLE_PREFIX="$(brew --prefix 2>/dev/null || true)"
fi
if [ -z "$BUNDLE_PREFIX" ]; then
BUNDLE_PREFIX="/usr/local"
fi
# Keep a caller-provided trailing slash so gtk-mac-bundler path concatenation
# does not produce malformed locale paths like ".../x86_64locale/...".
# CI explicitly sets BUNDLE_PREFIX with a trailing slash.
BUNDLE_PREFIX_XML="$BUNDLE_PREFIX"
ENCHANT_PREFIX_DEFAULT="${BUNDLE_PREFIX}/opt/enchant"
ENCHANT_PREFIX_PATH="${ENCHANT_PREFIX:-$ENCHANT_PREFIX_DEFAULT}"
perl -0pi -e 's|(<prefix\s+name="default">)[^<]+(</prefix>)|$1'"$BUNDLE_PREFIX_XML"'$2|s' "$BUNDLE_DEF"
perl -0pi -e 's|(<prefix\s+name="enchant">)[^<]+(</prefix>)|$1'"$ENCHANT_PREFIX_PATH"'$2|s' "$BUNDLE_DEF"
if command -v brew >/dev/null 2>&1; then
BREW_ENCHANT_PREFIX="$(brew --prefix enchant 2>/dev/null || true)"
if [ -n "$BREW_ENCHANT_PREFIX" ]; then
ENCHANT_PREFIX_PATH="$BREW_ENCHANT_PREFIX"
perl -0pi -e 's|(<prefix\s+name="enchant">)[^<]+(</prefix>)|$1'"$ENCHANT_PREFIX_PATH"'$2|s' "$BUNDLE_DEF"
fi
fi
if [ -n "$ENCHANT_PREFIX_PATH" ]; then
if [ -d "$ENCHANT_PREFIX_PATH/share/enchant" ]; then
perl -0pi -e 's|(<data>\s*)\$\{prefix:enchant\}/share/enchant(?:-2)?(\s*</data>)|$1\$\{prefix:enchant\}/share/enchant$2|s' "$BUNDLE_DEF"
elif [ -d "$ENCHANT_PREFIX_PATH/share/enchant-2" ]; then
perl -0pi -e 's|(<data>\s*)\$\{prefix:enchant\}/share/enchant(?:-2)?(\s*</data>)|$1\$\{prefix:enchant\}/share/enchant-2$2|s' "$BUNDLE_DEF"
else
perl -0pi -e 's|\n\s*<data>\s*\$\{prefix:enchant\}/share/enchant(?:-2)?\s*</data>\n|\n|s' "$BUNDLE_DEF"
fi
fi
# GTK module extension differs across package manager builds:
# - Homebrew commonly installs .dylib modules
# - Some environments still ship .so modules
# Detect what exists in the staged prefix and rewrite the bundle definition
# so gtk-mac-bundler does not fail on a missing glob.
GTK_MODULE_EXT="so"
if find "$BUNDLE_PREFIX/lib/gtk-3.0" -type f \( -path '*/immodules/*.dylib' -o -path '*/printbackends/*.dylib' \) -print -quit 2>/dev/null | grep -q . \
|| find "$BUNDLE_PREFIX/lib/gdk-pixbuf-2.0" -type f -path '*/loaders/*.dylib' -print -quit 2>/dev/null | grep -q .; then
GTK_MODULE_EXT="dylib"
fi
if [ "$GTK_MODULE_EXT" = "dylib" ]; then
perl -0pi -e 's|(/immodules/)\*\.so|$1*.dylib|g; s|(/printbackends/)\*\.so|$1*.dylib|g; s|(/loaders/)\*\.so|$1*.dylib|g' "$BUNDLE_DEF"
else
perl -0pi -e 's|(/immodules/)\*\.dylib|$1*.so|g; s|(/printbackends/)\*\.dylib|$1*.so|g; s|(/loaders/)\*\.dylib|$1*.so|g' "$BUNDLE_DEF"
fi
# Some staged builds omit GTK runtime module directories entirely
# (for example stripped-down CI artifacts). Remove bundle entries for
# missing globs so gtk-mac-bundler does not abort.
if ! find "$BUNDLE_PREFIX/lib/gtk-3.0" -type f -path "*/immodules/*.${GTK_MODULE_EXT}" -print -quit 2>/dev/null | grep -q .; then
perl -0pi -e 's#\n\s*<binary>\s*\$\{prefix\}/lib/\$\{gtkdir\}/\$\{pkg:\$\{gtk\}:gtk_binary_version\}/immodules/\*\.(?:so|dylib)\s*</binary>\n#\n#g' "$BUNDLE_DEF"
fi
if ! find "$BUNDLE_PREFIX/lib/gtk-3.0" -type f -path "*/printbackends/*.${GTK_MODULE_EXT}" -print -quit 2>/dev/null | grep -q .; then
perl -0pi -e 's#\n\s*<binary>\s*\$\{prefix\}/lib/\$\{gtkdir\}/\$\{pkg:\$\{gtk\}:gtk_binary_version\}/printbackends/\*\.(?:so|dylib)\s*</binary>\n#\n#g' "$BUNDLE_DEF"
fi
if ! find "$BUNDLE_PREFIX/lib/gdk-pixbuf-2.0" -type f -path "*/loaders/*.${GTK_MODULE_EXT}" -print -quit 2>/dev/null | grep -q .; then
perl -0pi -e 's#\n\s*<binary>\s*\$\{prefix\}/lib/gdk-pixbuf-2\.0/\$\{pkg:gdk-pixbuf-2\.0:gdk_pixbuf_binary_version\}/loaders/\*\.(?:so|dylib)\s*</binary>\n#\n#g' "$BUNDLE_DEF"
fi
# Keep Info.plist generation deterministic by always rendering from template
# using a single, explicit version source.
VERSION_STRING="${VERSION:-$(sed -n "s/^ version: '\([^']*\)',$/\1/p" ../meson.build | head -n1)}"
if [ -z "$VERSION_STRING" ]; then
echo "error: unable to determine VERSION_STRING for Info.plist" >&2
exit 1
fi
TMP_PLIST="Info.plist.tmp"
LC_ALL=C sed "s/@VERSION@/$VERSION_STRING/g" Info.plist.in > "$TMP_PLIST"
mv -f "$TMP_PLIST" Info.plist
# shellcheck disable=SC2086
$BUNDLER_CMD "$BUNDLE_DEF"
if [ ! -d "$APP_NAME" ]; then
echo "error: bundler finished but $APP_NAME was not created" >&2
exit 1
fi
BIN_PATH="$APP_NAME/Contents/MacOS/ZoiteChat-bin"
if [ "${UNIVERSAL:-0}" = "1" ] && [ -z "$UNIVERSAL_BINARIES" ]; then
for build_dir in $UNIVERSAL_BUILD_DIRS; do
candidate="$build_dir/src/fe-gtk/zoitechat"
if [ -f "$candidate" ]; then
UNIVERSAL_BINARIES="${UNIVERSAL_BINARIES:+$UNIVERSAL_BINARIES }$candidate"
fi
done
if [ -z "$UNIVERSAL_BINARIES" ]; then
cat >&2 <<'MSG'
error: UNIVERSAL=1 requested, but no source binaries were found.
Set UNIVERSAL_BINARIES to one or more architecture-specific zoitechat binaries,
or place builds at:
../build-macos-arm64/src/fe-gtk/zoitechat
../build-macos-x86_64/src/fe-gtk/zoitechat
MSG
exit 1
fi
fi
if [ -n "$UNIVERSAL_BINARIES" ]; then
if ! command -v lipo >/dev/null 2>&1; then
echo "error: UNIVERSAL_BINARIES requires lipo, but lipo is unavailable" >&2
exit 1
fi
for binary in $UNIVERSAL_BINARIES; do
if [ ! -f "$binary" ]; then
echo "error: universal source binary not found: $binary" >&2
exit 1
fi
done
echo "Creating universal ZoiteChat-bin from: $UNIVERSAL_BINARIES"
# shellcheck disable=SC2086
lipo -create $UNIVERSAL_BINARIES -output "$BIN_PATH"
fi
if command -v lipo >/dev/null 2>&1; then
BIN_ARCHS="$(lipo -archs "$BIN_PATH" 2>/dev/null || true)"
if [ -z "$BIN_ARCHS" ]; then
echo "error: unable to detect architectures for $BIN_PATH" >&2
exit 1
fi
for required_arch in $TARGET_ARCHES; do
if ! echo " $BIN_ARCHS " | grep -q " $required_arch "; then
cat >&2 <<MSG
error: bundled binary architecture mismatch.
required: $TARGET_ARCHES
actual: $BIN_ARCHS
hint: rebuild ZoiteChat-bin with matching architecture(s) before bundling.
MSG
exit 1
fi
done
fi
if command -v file >/dev/null 2>&1; then
echo "Bundled binary architecture:"
file "$BIN_PATH" || true
fi
python $HOME/.local/bin/gtk-mac-bundler zoitechat.bundle
echo "Compressing bundle"
ARCHIVE_VERSION="$(git describe --tags --always 2>/dev/null || true)"
if [ -z "$ARCHIVE_VERSION" ]; then
ARCHIVE_VERSION="$VERSION_STRING"
fi
zip -9rXq "./ZoiteChat-$ARCHIVE_VERSION.app.zip" "./$APP_NAME"
#hdiutil create -format UDBZ -srcdir ZoiteChat.app -quiet ZoiteChat-2.9.6.1-$(git rev-parse --short master).dmg
zip -9rXq ./ZoiteChat-$(git describe --tags).app.zip ./ZoiteChat.app

View File

@@ -2,16 +2,13 @@
<app-bundle>
<meta>
<!-- Expected prefixes:
Homebrew: /opt/homebrew (Apple Silicon) or /usr/local (Intel)
MacPorts: /opt/local -->
<prefix name="default">/usr/local</prefix>
<prefix name="enchant">/usr/local/opt/enchant</prefix>
<prefix name="enchant">/usr/local/opt/enchant-applespell</prefix>
<destination overwrite="yes">${project}</destination>
<run-install-name-tool>yes</run-install-name-tool>
<launcher-script>${project}/launcher.sh</launcher-script>
<gtk>gtk+-3.0</gtk>
<run-install-name-tool/>
<launcher-script>${project}/launcher.sh</launcher-script >
<gtk>gtk+-2.0</gtk>
</meta>
<plist>${project}/Info.plist</plist>
@@ -24,38 +21,46 @@
${prefix}/lib/zoitechat/plugins/*.so
</binary>
<!-- Enchant 2 runtime layout (Homebrew/MacPorts):
- core dylib in lib/
- provider modules in lib/enchant-2/ loaded via dlopen()
- config files in share/enchant/ -->
<binary>
${prefix:enchant}/lib/libenchant-2*.dylib
${prefix:enchant}/lib/libenchant.dylib
</binary>
<binary>
${prefix:enchant}/lib/enchant-2
${prefix:enchant}/lib/enchant/libenchant_applespell.so
</binary>
<data>
${prefix:enchant}/share/enchant
</data>
<!-- GTK3 runtime modules: ${prefix}/lib/${gtkdir} -->
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
${prefix}/lib/${gtkdir}/modules/*.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/libquartz.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/libxamarin.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/*.so
</binary>
<translations name="gtk30">
<binary>
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
</binary>
<data>
${prefix}/share/themes/Mac/gtk-2.0-key/gtkrc
</data>
<translations name="gtk20">
${prefix}/share/locale
</translations>
<translations name="zoitechat">
${prefix}/share/locale
</translations>
<data dest="${bundle}/Contents/Resources/etc/${gtkdir}/gtkrc">
${project}/gtkrc
</data>
<data dest="${bundle}/Contents/Resources">
${project}/zoitechat.icns
</data>

Binary file not shown.

View File

@@ -1,8 +1,8 @@
name : zoitechat
version : 2.18.0-pre1
release : 1
version : 2.18.0
release : 2
source :
- https://github.com/ZoiteChat/zoitechat/archive/refs/tags/zoitechat-2.18.0-pre1.tar.gz : 77d787cf00abd533326440eab01ca077c21cdfd2eb56807fc21d6fb70f34ada6
- https://github.com/ZoiteChat/zoitechat/archive/e060d57baee1be22bee1f9c3b047be3fa71c6d35.tar.gz : ed315a0b1c46e798912fd830d3845427972857c43ccaa16284969c6f542add38
homepage : https://zoitechat.zoite.net/
license : GPL-2.0-only
component : network.irc
@@ -20,7 +20,7 @@ builddeps :
- pkgconfig(iso-codes)
- meson
- ninja
- pkgconfig
- pkgconf
- gcc
- gettext
setup : |

View File

@@ -75,7 +75,7 @@ dh1080_init (void)
BN_set_word (g, 2);
#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
#ifndef HAVE_DH_SET0_PQG
g_dh->p = p;
g_dh->g = g;
#else
@@ -163,7 +163,7 @@ dh1080_generate_key (char **priv_key, char **pub_key)
return 0;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
#ifndef HAVE_DH_GET0_KEY
dh_pub_key = dh->pub_key;
dh_priv_key = dh->priv_key;
#else
@@ -190,6 +190,9 @@ dh1080_compute_key (const char *priv_key, const char *pub_key, char **secret_key
gsize pub_key_len;
BIGNUM *pk;
DH *dh;
#ifdef HAVE_DH_SET0_KEY
BIGNUM *temp_pub_key = BN_new();
#endif
g_assert (secret_key != NULL);
@@ -214,10 +217,10 @@ dh1080_compute_key (const char *priv_key, const char *pub_key, char **secret_key
priv_key_data = dh1080_decode_b64 (priv_key, &priv_key_len);
priv_key_num = BN_bin2bn(priv_key_data, priv_key_len, NULL);
#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
#ifndef HAVE_DH_SET0_KEY
dh->priv_key = priv_key_num;
#else
DH_set0_key (dh, NULL, priv_key_num);
DH_set0_key (dh, temp_pub_key, priv_key_num);
#endif
shared_len = DH_compute_key (shared_key, pk, dh);

View File

@@ -22,31 +22,7 @@ if get_option('with-fishlim')
subdir('fishlim')
endif
lua_option = get_option('with-lua')
if lua_option == 'auto' or lua_option == 'luajit'
lua_auto_dep = dependency('luajit', required: false)
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua-5.4', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua5.4', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua-5.3', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua5.3', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua', required: false)
endif
if lua_auto_dep.found()
subdir('lua')
else
warning('LuaJIT/Lua development files not found, disabling Lua plugin')
endif
elif lua_option != 'false'
if get_option('with-lua') != 'false'
subdir('lua')
endif

View File

@@ -27,10 +27,9 @@ endif
perl = find_program(get_option('with-perl'))
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ccopts'], check: false)
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ccopts'])
if ret.returncode() != 0
warning('Perl development files not found, disabling Perl plugin')
subdir_done()
error('perl: Failed to get cflags')
endif
foreach flag : ret.stdout().strip().split(' ')
if flag.startswith('-I') or flag.startswith('-D')
@@ -38,10 +37,9 @@ foreach flag : ret.stdout().strip().split(' ')
endif
endforeach
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ldopts'], check: false)
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ldopts'])
if ret.returncode() != 0
warning('Perl development files not found, disabling Perl plugin')
subdir_done()
error('perl: Failed to get ldflags')
endif
perl_ldflags = []
perl_rpath = ''
@@ -75,8 +73,7 @@ int main(void) {
return 0;
}
''', args: perl_cflags + perl_ldflags)
warning('Found perl is not suitable for plugin, disabling Perl plugin')
subdir_done()
error('found perl not suitable for plugin')
endif
perl_dep = declare_dependency(

View File

@@ -52,7 +52,3 @@ provide binary packages linked to the OpenSSL libraries, provided that
all other requirements of the GPL are met.
See file COPYING for details.
</sub>
## macOS debugging
If you are troubleshooting local macOS build/run/debug issues (including Xcode setup), see `osx/DEBUGGING.md`.

View File

@@ -103,7 +103,7 @@ zoitechat_common_dep = declare_dependency(
link_with: zoitechat_common,
include_directories: common_includes,
compile_args: common_cflags,
dependencies: common_deps,
dependencies: libgio_dep,
)
zoitechat_plugin_dep = declare_dependency(

View File

@@ -4109,7 +4109,7 @@ const struct commands xc_cmds[] = {
{"ME", cmd_me, 0, 0, 1,
N_("ME <action>, sends the action to the current channel (actions are written in the 3rd person, like /me jumps)")},
{"MENU", cmd_menu, 0, 0, 1, "MENU [-eX] [-i<ICONFILE>] [-k<mod>,<key>] [-m] [-pX] [-r<X,group>] [-tX] {ADD|DEL} <path> [command] [unselect command]\n"
" See http://zoitechat.zoite.net/docs/en/latest/plugins.html#controlling-the-gui for more details."},
" See https://docs.zoitechat.zoite.net/en/latest/en/latest/plugins.html#controlling-the-gui for more details."},
{"MHOP", cmd_mhop, 1, 1, 1,
N_("MHOP, Mass hop's all users in the current channel (needs chanop)")},
{"MKICK", cmd_mkick, 1, 1, 1,

View File

@@ -154,7 +154,6 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
X509 *peer_cert;
X509_PUBKEY *key;
X509_ALGOR *algor = NULL;
const ASN1_OBJECT *algor_obj = NULL;
EVP_PKEY *peer_pkey;
char notBefore[64];
char notAfter[64];
@@ -176,19 +175,11 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
if (!X509_PUBKEY_get0_param(NULL, NULL, 0, &algor, key))
return 1;
X509_ALGOR_get0 (&algor_obj, NULL, NULL, algor);
alg = OBJ_obj2nid (algor_obj);
#ifdef HAVE_X509_GET_SIGNATURE_NID
sign_alg = X509_get_signature_nid (peer_cert);
alg = OBJ_obj2nid (algor->algorithm);
#ifndef HAVE_X509_GET_SIGNATURE_NID
sign_alg = OBJ_obj2nid (peer_cert->sig_alg->algorithm);
#else
{
const X509_ALGOR *signature_algor = NULL;
const ASN1_OBJECT *signature_algor_obj = NULL;
X509_get0_signature (NULL, &signature_algor, peer_cert);
X509_ALGOR_get0 (&signature_algor_obj, NULL, NULL, signature_algor);
sign_alg = OBJ_obj2nid (signature_algor_obj);
}
sign_alg = X509_get_signature_nid (peer_cert);
#endif
ASN1_TIME_snprintf (notBefore, sizeof (notBefore),
X509_get_notBefore (peer_cert));
@@ -307,10 +298,7 @@ SSL *
_SSL_socket (SSL_CTX *ctx, int sd)
{
SSL *ssl;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
const SSL_METHOD *method;
#endif
if (!(ssl = SSL_new (ctx)))
/* FATAL */
@@ -318,12 +306,6 @@ _SSL_socket (SSL_CTX *ctx, int sd)
SSL_set_fd (ssl, sd);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (SSL_is_server (ssl))
SSL_set_accept_state (ssl);
else
SSL_set_connect_state (ssl);
#else
#ifndef HAVE_SSL_CTX_GET_SSL_METHOD
method = ctx->method;
#else
@@ -332,8 +314,7 @@ _SSL_socket (SSL_CTX *ctx, int sd)
if (method == SSLv23_client_method())
SSL_set_connect_state (ssl);
else
SSL_set_accept_state (ssl);
#endif
SSL_set_accept_state(ssl);
return (ssl);
}

View File

@@ -229,6 +229,10 @@ zoitechat_remote_win32 (void)
{
sent = zoitechat_send_command_to_existing (hwnd, arg_command) || sent;
}
else if (arg_existing)
{
sent = zoitechat_send_command_to_existing (hwnd, "__WIN32_TASKBAR_TOGGLE__") || sent;
}
if (arg_urls)
{

View File

@@ -663,14 +663,13 @@ fe_set_title (session *sess)
static gboolean
mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata)
{
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
prefs.hex_gui_tray_minimize && prefs.hex_gui_tray &&
gtkutil_tray_icon_supported (wid))
{
tray_toggle_visibility (TRUE);
gtk_window_deiconify (wid);
}
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
prefs.hex_gui_tray_minimize && prefs.hex_gui_tray &&
gtkutil_tray_icon_supported (wid))
{
tray_toggle_visibility (TRUE);
}
prefs.hex_gui_win_state = 0;
if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
@@ -3893,7 +3892,17 @@ mg_win32_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data)
if (command)
{
handle_command (current_sess, command, FALSE);
if (strcmp (command, "__WIN32_TASKBAR_TOGGLE__") == 0)
{
if (gtk_widget_get_visible (current_sess->gui->window))
fe_ctrl_gui (current_sess, FE_GUI_ICONIFY, 0);
else
fe_ctrl_gui (current_sess, FE_GUI_SHOW, 0);
}
else
{
handle_command (current_sess, command, FALSE);
}
g_free (command);
return GDK_FILTER_REMOVE;
}

View File

@@ -1815,7 +1815,7 @@ menu_ctcpguiopen (void)
static void
menu_docs (GtkWidget *wid, gpointer none)
{
fe_open_url ("http://zoitechat.zoite.net/docs");
fe_open_url ("https://docs.zoitechat.zoite.net/en/latest/");
}
/*static void
@@ -2014,7 +2014,6 @@ menu_about (GtkWidget *wid, gpointer sess)
#define ICON_FIND "zc-menu-find"
#define ICON_HELP "zc-menu-help"
#define ICON_ABOUT "zc-menu-about"
#define ICON_UPDATE "zc-menu-update"
static struct mymenu mymenu[] = {
{N_("_ZoiteChat"), 0, 0, M_NEWMENU, MENU_ID_ZOITECHAT, 0, 1},
@@ -2110,7 +2109,6 @@ static struct mymenu mymenu[] = {
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
{N_("_Contents"), menu_docs, ICON_HELP, M_MENUSTOCK, 0, 0, 1, GDK_KEY_F1},
{N_("_Update"), menu_docs, ICON_UPDATE, M_MENUSTOCK, 0, 0, 1},
{N_("_About"), menu_about, ICON_ABOUT, M_MENUSTOCK, 0, 0, 1},
{0, 0, 0, M_END, 0, 0, 0},

View File

@@ -85,14 +85,6 @@ if host_machine.system() == 'windows'
# sources: 'notifications/notification-winrt.cpp'
#)
elif host_machine.system() == 'darwin'
zoitechat_gtk_sources += 'notifications/notification-osx.m'
add_languages('objc')
gtk_mac_dep = dependency('gtk-mac-integration', required: true)
zoitechat_gtk_deps += gtk_mac_dep
zoitechat_gtk_cflags += '-DHAVE_GTK_MAC'
else
zoitechat_gtk_sources += 'notifications/notification-freedesktop.c'
endif