Enhance TDLib integration and macOS bundling process

- Updated build.rs to include a setup function for TDLib, ensuring the correct version is used based on the target OS.
- Added a new script, build-tdlib-from-source.sh, to facilitate building TDLib from source for macOS with the appropriate deployment target.
- Modified .gitignore to exclude the new tdlib-local and tdlib-build directories.
- Updated tauri.conf.json to streamline TDLib references and ensure compatibility with the new bundling process.
- Removed outdated bundling scripts to simplify the build workflow.
This commit is contained in:
Steven Enamakel
2026-02-05 20:32:23 +05:30
parent 9e678a08a6
commit d0fdcb43fc
8 changed files with 303 additions and 435 deletions
+4
View File
@@ -8,3 +8,7 @@
# TDLib and dependencies copied by build.rs for macOS bundling
/libraries/
# TDLib built from source (see scripts/build-tdlib-from-source.sh)
/tdlib-local/
/tdlib-build/
+8 -3
View File
@@ -91,11 +91,16 @@ android_logger = "0.14"
keyring = "3"
tauri-plugin-autostart = "2"
tauri-plugin-notification = "2"
# V8 JavaScript runtime (via deno_core - powers Deno)
# QuickJS JavaScript runtime (via quickjs-rs)
# Only available on desktop - prebuilt binaries don't exist for Android/iOS
rquickjs = { version = "0.11", features = ["futures", "macro", "loader", "parallel"] }
# TDLib Rust bindings (desktop only - downloads prebuilt TDLib library)
# TDLib Rust bindings (desktop only - downloads prebuilt TDLib for linking)
# On macOS, the bundled dylib is replaced with a source-built version (see build.rs)
# to ensure macOS 10.15 deployment target compatibility.
tdlib-rs = { version = "1.2", features = ["download-tdlib"] }
# Local LLM inference - desktop only (llama.cpp requires native C++ compilation)
# Disable default features (including openmp) to avoid cross-compilation issues
# on macOS where Homebrew installs ARM64-only OpenMP libraries
@@ -103,7 +108,7 @@ llama-cpp-2 = { version = "0.1", default-features = false }
encoding_rs = "0.8"
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.build-dependencies]
# TDLib build configuration
# TDLib build configuration (download-tdlib for all desktop platforms)
tdlib-rs = { version = "1.2", features = ["download-tdlib"] }
[features]
+116 -1
View File
@@ -1,4 +1,119 @@
use std::env;
fn main() {
setup_tdlib();
tauri_build::build();
}
#[cfg(not(any(target_os = "android", target_os = "ios")))]
fn setup_tdlib() {
// download-tdlib: downloads prebuilt TDLib and configures linker flags
tdlib_rs::build::build(None);
tauri_build::build()
// On macOS, replace the bundled dylib with our source-built version
// that targets macOS 10.15 (the prebuilt one targets macOS 14.0)
#[cfg(target_os = "macos")]
copy_local_tdlib_for_bundle();
}
#[cfg(any(target_os = "android", target_os = "ios"))]
fn setup_tdlib() {
// No TDLib on mobile
}
/// On macOS, copy the source-built TDLib dylib (with 10.15 deployment target)
/// to libraries/ for Tauri bundler. Lookup order:
/// 1. tdlib-prebuilt/macos-<arch>/ (committed to git, no build needed)
/// 2. tdlib-local/lib/ (local build via build-tdlib-from-source.sh)
/// 3. download-tdlib output (fallback, targets macOS 14.0+)
#[cfg(target_os = "macos")]
fn copy_local_tdlib_for_bundle() {
use std::path::PathBuf;
let manifest_dir =
PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"));
let libraries_dir = manifest_dir.join("libraries");
// Use CARGO_CFG_TARGET_ARCH to handle cross-compilation (e.g. arm64 host → x86_64 target)
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_else(|_| "aarch64".into());
let arch_name = match target_arch.as_str() {
"aarch64" => "arm64",
other => other,
};
let tdlib_version = "1.8.29";
let dylib_name = format!("libtdjson.{tdlib_version}.dylib");
// 1. Check tdlib-prebuilt/ (committed to git)
let prebuilt = manifest_dir
.join("tdlib-prebuilt")
.join(format!("macos-{arch_name}"))
.join(&dylib_name);
// 2. Check tdlib-local/ (local source build)
let local = manifest_dir.join("tdlib-local").join("lib").join(&dylib_name);
let src_dylib = if prebuilt.exists() {
println!("cargo:warning=Using prebuilt TDLib from {}", prebuilt.display());
prebuilt
} else if local.exists() {
println!("cargo:warning=Using locally-built TDLib from {}", local.display());
local
} else {
// 3. Fall back to the download-tdlib output
println!(
"cargo:warning=No source-built TDLib found for macos-{arch_name}. \
The prebuilt TDLib will be bundled instead (targets macOS 14.0+). \
Run: cd src-tauri && ./scripts/build-tdlib-from-source.sh"
);
let out_dir = env::var("OUT_DIR").unwrap();
PathBuf::from(&out_dir).join("tdlib").join("lib").join(&dylib_name)
};
if !src_dylib.exists() {
println!("cargo:warning=TDLib dylib not found at {}", src_dylib.display());
return;
}
let dst_dylib = libraries_dir.join(&dylib_name);
std::fs::create_dir_all(&libraries_dir).expect("Failed to create libraries/");
std::fs::copy(&src_dylib, &dst_dylib).expect("Failed to copy TDLib dylib to libraries/");
set_permissions_rw(&dst_dylib);
fix_install_name(&dst_dylib, &dylib_name);
// Add rpath so the binary finds the dylib in Contents/Frameworks/
println!("cargo:rustc-link-arg=-Wl,-rpath,@executable_path/../Frameworks");
}
#[cfg(target_os = "macos")]
fn fix_install_name(dylib_path: &std::path::Path, dylib_name: &str) {
run_cmd(
"install_name_tool",
&[
"-id",
&format!("@rpath/{dylib_name}"),
dylib_path.to_str().unwrap(),
],
);
}
#[cfg(target_os = "macos")]
fn set_permissions_rw(path: &std::path::Path) {
use std::os::unix::fs::PermissionsExt;
let mut perms = std::fs::metadata(path)
.expect("Failed to read metadata")
.permissions();
perms.set_mode(0o755);
std::fs::set_permissions(path, perms).expect("Failed to set permissions");
}
#[cfg(target_os = "macos")]
fn run_cmd(cmd: &str, args: &[&str]) {
let status = std::process::Command::new(cmd)
.args(args)
.status()
.unwrap_or_else(|e| panic!("Failed to run {cmd}: {e}"));
if !status.success() {
panic!("{cmd} failed with exit code {:?}", status.code());
}
}
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env bash
#
# Build TDLib v1.8.29 from source with MACOSX_DEPLOYMENT_TARGET=10.15
# OpenSSL 3.x is statically linked so there are NO external OpenSSL deps.
#
# Usage:
# cd src-tauri
# ./scripts/build-tdlib-from-source.sh [arm64|x86_64]
#
# Output: src-tauri/tdlib-local/ (lib/ + include/)
# Time: 5-15 minutes on first run
set -euo pipefail
TDLIB_VERSION="1.8.29"
TDLIB_COMMIT="af69dd4397b6dc1bf23ba0fd0bf429fcba6454f6"
OPENSSL_VERSION="3.4.1"
export MACOSX_DEPLOYMENT_TARGET="10.15"
# --- Resolve paths relative to src-tauri/ ---
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SRC_TAURI_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
BUILD_DIR="${SRC_TAURI_DIR}/tdlib-build"
INSTALL_DIR="${SRC_TAURI_DIR}/tdlib-local"
# --- Detect or override architecture ---
ARCH="${1:-$(uname -m)}"
case "$ARCH" in
arm64|aarch64) ARCH="arm64" ;;
x86_64) ARCH="x86_64" ;;
*)
echo "Error: unsupported architecture '$ARCH'. Use arm64 or x86_64."
exit 1
;;
esac
echo "==> Building for architecture: $ARCH"
echo "==> Deployment target: macOS $MACOSX_DEPLOYMENT_TARGET"
COMMON_FLAGS="-arch $ARCH -mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET"
# --- Check prerequisites ---
for cmd in cmake gperf make perl; do
if ! command -v $cmd &>/dev/null; then
echo "Error: '$cmd' not found. Install via: brew install $cmd"
exit 1
fi
done
mkdir -p "$BUILD_DIR"
# ============================================================
# 1. Build OpenSSL 3.x (static only)
# ============================================================
OPENSSL_SRC="${BUILD_DIR}/openssl-${OPENSSL_VERSION}"
OPENSSL_INSTALL="${BUILD_DIR}/openssl-install"
if [ -f "${OPENSSL_INSTALL}/lib/libssl.a" ]; then
echo "==> OpenSSL already built, skipping (delete ${OPENSSL_INSTALL} to rebuild)"
else
echo "==> Downloading OpenSSL ${OPENSSL_VERSION}..."
cd "$BUILD_DIR"
if [ ! -d "$OPENSSL_SRC" ]; then
curl -sSL "https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VERSION}/openssl-${OPENSSL_VERSION}.tar.gz" -o openssl.tar.gz
tar xzf openssl.tar.gz
rm openssl.tar.gz
fi
echo "==> Building OpenSSL (static, no-shared)..."
cd "$OPENSSL_SRC"
# Map arch to OpenSSL target
if [ "$ARCH" = "arm64" ]; then
OPENSSL_TARGET="darwin64-arm64-cc"
else
OPENSSL_TARGET="darwin64-x86_64-cc"
fi
./Configure "$OPENSSL_TARGET" \
no-shared \
no-tests \
--prefix="$OPENSSL_INSTALL" \
-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET
make -j"$(sysctl -n hw.ncpu)"
make install_sw
echo "==> OpenSSL installed to ${OPENSSL_INSTALL}"
fi
# ============================================================
# 2. Build TDLib from source
# ============================================================
TDLIB_SRC="${BUILD_DIR}/td"
TDLIB_BUILD="${BUILD_DIR}/td-build"
if [ -f "${INSTALL_DIR}/lib/libtdjson.${TDLIB_VERSION}.dylib" ]; then
echo "==> TDLib already built, skipping (delete ${INSTALL_DIR} to rebuild)"
else
echo "==> Downloading TDLib ${TDLIB_VERSION} (commit ${TDLIB_COMMIT})..."
cd "$BUILD_DIR"
if [ ! -d "$TDLIB_SRC" ]; then
git clone https://github.com/tdlib/td.git
cd td && git checkout "$TDLIB_COMMIT" && cd ..
fi
echo "==> Building TDLib..."
rm -rf "$TDLIB_BUILD"
mkdir -p "$TDLIB_BUILD"
cd "$TDLIB_BUILD"
# CMAKE_OSX_ARCHITECTURES ensures all C/C++ code targets the right arch
cmake "$TDLIB_SRC" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \
-DCMAKE_OSX_DEPLOYMENT_TARGET="$MACOSX_DEPLOYMENT_TARGET" \
-DCMAKE_OSX_ARCHITECTURES="$ARCH" \
-DCMAKE_C_FLAGS="$COMMON_FLAGS" \
-DCMAKE_CXX_FLAGS="$COMMON_FLAGS" \
-DOPENSSL_ROOT_DIR="$OPENSSL_INSTALL" \
-DOPENSSL_USE_STATIC_LIBS=ON \
-DOPENSSL_CRYPTO_LIBRARY="$OPENSSL_INSTALL/lib/libcrypto.a" \
-DOPENSSL_SSL_LIBRARY="$OPENSSL_INSTALL/lib/libssl.a" \
-DOPENSSL_INCLUDE_DIR="$OPENSSL_INSTALL/include" \
-DTD_ENABLE_JNI=OFF
cmake --build . --target tdjson -j"$(sysctl -n hw.ncpu)"
cmake --install .
echo "==> TDLib installed to ${INSTALL_DIR}"
fi
# ============================================================
# 3. Copy to tdlib-prebuilt/ for git commit
# ============================================================
PREBUILT_DIR="${SRC_TAURI_DIR}/tdlib-prebuilt/macos-${ARCH}"
mkdir -p "$PREBUILT_DIR"
cp "${INSTALL_DIR}/lib/libtdjson.${TDLIB_VERSION}.dylib" "$PREBUILT_DIR/"
echo "==> Copied dylib to ${PREBUILT_DIR}/ (commit this to git)"
# ============================================================
# 4. Verify the build
# ============================================================
DYLIB="${INSTALL_DIR}/lib/libtdjson.${TDLIB_VERSION}.dylib"
if [ ! -f "$DYLIB" ]; then
echo "Error: expected dylib not found at ${DYLIB}"
exit 1
fi
echo ""
echo "==> Verification:"
# Check deployment target
MINOS=$(otool -l "$DYLIB" | grep -A2 "minos" | head -3)
echo " Min OS version info:"
echo "$MINOS" | sed 's/^/ /'
# Check for OpenSSL references (should be NONE)
OPENSSL_REFS=$(otool -L "$DYLIB" | grep -i "ssl\|crypto" || true)
if [ -n "$OPENSSL_REFS" ]; then
echo " WARNING: Found external OpenSSL references (should be none):"
echo "$OPENSSL_REFS" | sed 's/^/ /'
else
echo " No external OpenSSL references (statically linked)"
fi
# Show all dylib deps
echo " Dependencies:"
otool -L "$DYLIB" | tail -n +2 | sed 's/^/ /'
echo ""
echo "==> Done! TDLib ${TDLIB_VERSION} built successfully for ${ARCH}."
echo " Install dir: ${INSTALL_DIR}"
echo ""
echo " Next: run 'yarn tauri build --debug --bundles app' to build the app."
-234
View File
@@ -1,234 +0,0 @@
#!/bin/bash
# Script to bundle TDLib dylib and its dependencies into macOS app bundle
# This fixes the "Library not loaded: @rpath/libtdjson.1.8.29.dylib" error
set -e
TDLIB_VERSION="1.8.29"
DYLIB_NAME="libtdjson.${TDLIB_VERSION}.dylib"
# Determine build type (debug or release)
BUILD_TYPE="${1:-release}"
# Optional: specific target (e.g., aarch64-apple-darwin, x86_64-apple-darwin)
TARGET="${2:-}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TAURI_DIR="$(dirname "$SCRIPT_DIR")"
# Determine target directory (handles cross-compilation targets)
if [ -n "$TARGET" ]; then
TARGET_DIR="${TAURI_DIR}/target/${TARGET}/${BUILD_TYPE}"
else
TARGET_DIR="${TAURI_DIR}/target/${BUILD_TYPE}"
fi
# Fallback: if target-specific dir doesn't exist, try without target
if [ ! -d "$TARGET_DIR" ]; then
TARGET_DIR="${TAURI_DIR}/target/${BUILD_TYPE}"
fi
echo "=== TDLib macOS Bundler ==="
echo "Build type: ${BUILD_TYPE}"
echo "Target: ${TARGET:-default}"
echo "Target dir: ${TARGET_DIR}"
# Find the app bundle - check multiple possible locations
APP_BUNDLE=""
for search_dir in \
"${TAURI_DIR}/target/${TARGET}/${BUILD_TYPE}/bundle/macos" \
"${TAURI_DIR}/target/${BUILD_TYPE}/bundle/macos" \
"${TAURI_DIR}/target/release/bundle/macos" \
"${TAURI_DIR}/target/debug/bundle/macos"; do
if [ -d "$search_dir" ]; then
found=$(find "$search_dir" -name "*.app" -type d 2>/dev/null | head -1)
if [ -n "$found" ]; then
APP_BUNDLE="$found"
break
fi
fi
done
if [ -z "$APP_BUNDLE" ]; then
echo "Warning: No .app bundle found"
echo "Searched in:"
echo " - ${TAURI_DIR}/target/${TARGET}/${BUILD_TYPE}/bundle/macos"
echo " - ${TAURI_DIR}/target/${BUILD_TYPE}/bundle/macos"
echo "This script should be run after 'tauri build'"
exit 0
fi
echo "Found app bundle: ${APP_BUNDLE}"
# Create Frameworks directory
FRAMEWORKS_DIR="${APP_BUNDLE}/Contents/Frameworks"
mkdir -p "$FRAMEWORKS_DIR"
echo "Created Frameworks directory: ${FRAMEWORKS_DIR}"
# Find the TDLib dylib in build artifacts - search in multiple locations
DYLIB_PATH=""
for search_dir in \
"${TAURI_DIR}/target/${TARGET}/${BUILD_TYPE}/build" \
"${TAURI_DIR}/target/${BUILD_TYPE}/build" \
"${TAURI_DIR}/target/release/build" \
"${TAURI_DIR}/target/debug/build"; do
if [ -d "$search_dir" ]; then
found=$(find "$search_dir" -name "${DYLIB_NAME}" -type f 2>/dev/null | head -1)
if [ -n "$found" ]; then
DYLIB_PATH="$found"
break
fi
fi
done
if [ -z "$DYLIB_PATH" ]; then
echo "Error: Could not find ${DYLIB_NAME} in build artifacts"
echo "Searched in target/*/build directories"
echo "Make sure TDLib was built correctly."
exit 1
fi
echo "Found TDLib dylib: ${DYLIB_PATH}"
# Copy the dylib to Frameworks
cp "$DYLIB_PATH" "${FRAMEWORKS_DIR}/"
echo "Copied ${DYLIB_NAME} to Frameworks"
# Also copy the symlink version if it exists
DYLIB_SYMLINK="${DYLIB_PATH%/*}/libtdjson.dylib"
if [ -f "$DYLIB_SYMLINK" ] || [ -L "$DYLIB_SYMLINK" ]; then
cp "$DYLIB_SYMLINK" "${FRAMEWORKS_DIR}/" 2>/dev/null || true
fi
# Find the main binary
BINARY_NAME=$(basename "${APP_BUNDLE}" .app)
BINARY_PATH="${APP_BUNDLE}/Contents/MacOS/${BINARY_NAME}"
if [ ! -f "$BINARY_PATH" ]; then
echo "Error: Binary not found at ${BINARY_PATH}"
exit 1
fi
echo "Found binary: ${BINARY_PATH}"
# Bundled dylib path
BUNDLED_DYLIB="${FRAMEWORKS_DIR}/${DYLIB_NAME}"
# Function to bundle a dependency and fix references
bundle_dependency() {
local dep_path="$1"
local dep_name=$(basename "$dep_path")
if [ ! -f "$dep_path" ]; then
echo "Warning: Dependency not found: $dep_path"
return 1
fi
# Copy to Frameworks if not already there
if [ ! -f "${FRAMEWORKS_DIR}/${dep_name}" ]; then
echo "Bundling dependency: ${dep_name}"
cp "$dep_path" "${FRAMEWORKS_DIR}/"
chmod 755 "${FRAMEWORKS_DIR}/${dep_name}"
# Change the dependency's install name to use @rpath
install_name_tool -id "@rpath/${dep_name}" "${FRAMEWORKS_DIR}/${dep_name}"
fi
return 0
}
# Function to fix references in a library
fix_references() {
local lib_path="$1"
local lib_name=$(basename "$lib_path")
echo "Fixing references in: ${lib_name}"
# Get all dependencies
local deps=$(otool -L "$lib_path" | tail -n +2 | awk '{print $1}')
for dep in $deps; do
# Skip system libraries (they're fine as-is)
if [[ "$dep" == /usr/lib/* ]] || [[ "$dep" == /System/* ]] || [[ "$dep" == "@rpath/"* ]] || [[ "$dep" == "@executable_path/"* ]]; then
continue
fi
local dep_name=$(basename "$dep")
# Bundle the dependency if it's from Homebrew or a non-system path
if [[ "$dep" == /opt/homebrew/* ]] || [[ "$dep" == /usr/local/* ]]; then
if bundle_dependency "$dep"; then
# Update the reference to use @rpath
install_name_tool -change "$dep" "@rpath/${dep_name}" "$lib_path"
echo " Fixed reference: ${dep_name}"
fi
fi
done
}
# Fix the TDLib dylib's install name
echo ""
echo "Fixing dylib install name..."
install_name_tool -id "@rpath/${DYLIB_NAME}" "$BUNDLED_DYLIB"
# Bundle OpenSSL and other dependencies from TDLib
echo ""
echo "Bundling TDLib dependencies..."
fix_references "$BUNDLED_DYLIB"
# Fix any cross-references between bundled dependencies
echo ""
echo "Fixing cross-references between dependencies..."
for dylib in "${FRAMEWORKS_DIR}"/*.dylib; do
if [ -f "$dylib" ]; then
fix_references "$dylib"
fi
done
# Fix rpaths in the binary
echo ""
echo "Fixing binary rpaths..."
# Get all current rpaths
CURRENT_RPATHS=$(otool -l "$BINARY_PATH" | grep -A2 "cmd LC_RPATH" | grep "path " | awk '{print $2}')
echo "Current rpaths:"
echo "$CURRENT_RPATHS"
# Remove all rpaths that point to build directories (they won't exist at runtime)
for rpath in $CURRENT_RPATHS; do
# Remove rpaths containing /build/, /target/, or absolute paths that aren't @executable_path
if [[ "$rpath" == *"/build/"* ]] || [[ "$rpath" == *"/target/"* ]] || [[ "$rpath" != @* ]]; then
echo "Removing build-time rpath: $rpath"
install_name_tool -delete_rpath "$rpath" "$BINARY_PATH" 2>/dev/null || true
fi
done
# Delete our target rpath first if it exists (to avoid "already exists" error)
install_name_tool -delete_rpath "@executable_path/../Frameworks" "$BINARY_PATH" 2>/dev/null || true
# Add the correct rpath for the bundled Frameworks
echo "Adding rpath: @executable_path/../Frameworks"
install_name_tool -add_rpath "@executable_path/../Frameworks" "$BINARY_PATH"
# Verify the changes
echo ""
echo "=== Verification ==="
echo ""
echo "Bundled libraries:"
ls -la "${FRAMEWORKS_DIR}/"
echo ""
echo "TDLib dylib dependencies (should all be @rpath or system libs):"
otool -L "$BUNDLED_DYLIB"
echo ""
echo "Binary library dependencies:"
otool -L "$BINARY_PATH" | grep -i tdjson || echo "No tdjson reference found"
echo ""
echo "Binary rpaths:"
otool -l "$BINARY_PATH" | grep -A3 "cmd LC_RPATH" | head -8 || true
echo ""
echo "=== TDLib bundling complete ==="
echo "The app bundle at ${APP_BUNDLE} now includes TDLib and its dependencies."
-81
View File
@@ -1,81 +0,0 @@
#!/bin/bash
# Recreate macOS DMG after TDLib bundling
# The original DMG is created by tauri-action BEFORE we bundle TDLib,
# so we need to recreate it with the updated .app bundle.
#
# Usage:
# ./recreate-dmg-macos.sh <build_type> [target]
#
# Arguments:
# build_type - "release" or "debug" (default: release)
# target - Optional cross-compilation target (e.g., aarch64-apple-darwin)
#
# Examples:
# ./recreate-dmg-macos.sh release
# ./recreate-dmg-macos.sh release aarch64-apple-darwin
set -e
BUILD_TYPE="${1:-release}"
TARGET="${2:-}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TAURI_DIR="$(dirname "$SCRIPT_DIR")"
echo "=== macOS DMG Recreation ==="
echo "Build type: ${BUILD_TYPE}"
echo "Target: ${TARGET:-default}"
# --- Determine bundle directories ---
# Tauri v2 puts .app in bundle/macos/ and .dmg in bundle/dmg/
BASE_BUNDLE_DIR=""
for search_dir in \
"${TAURI_DIR}/target/${TARGET}/${BUILD_TYPE}/bundle" \
"${TAURI_DIR}/target/${BUILD_TYPE}/bundle" \
"${TAURI_DIR}/target/release/bundle" \
"${TAURI_DIR}/target/debug/bundle"; do
if [ -d "$search_dir/macos" ]; then
BASE_BUNDLE_DIR="$search_dir"
break
fi
done
if [ -z "$BASE_BUNDLE_DIR" ]; then
echo "Warning: No bundle directory found"
exit 0
fi
MACOS_DIR="$BASE_BUNDLE_DIR/macos"
DMG_DIR="$BASE_BUNDLE_DIR/dmg"
echo "Bundle base: $BASE_BUNDLE_DIR"
# --- Find the app bundle ---
APP_BUNDLE=$(find "$MACOS_DIR" -name "*.app" -type d 2>/dev/null | head -1)
if [ -z "$APP_BUNDLE" ]; then
echo "Error: No .app bundle found in $MACOS_DIR"
exit 1
fi
APP_NAME=$(basename "$APP_BUNDLE" .app)
echo "App bundle: $APP_BUNDLE"
# --- Find the original DMG ---
ORIGINAL_DMG=$(find "$DMG_DIR" -name "*.dmg" -type f 2>/dev/null | head -1)
if [ -z "$ORIGINAL_DMG" ]; then
echo "Warning: No original DMG found in $DMG_DIR, skipping"
exit 0
fi
DMG_NAME=$(basename "$ORIGINAL_DMG")
echo "Original DMG: $ORIGINAL_DMG"
# --- Remove old DMG and create new one ---
echo ""
echo "Creating new DMG..."
rm -f "$ORIGINAL_DMG"
hdiutil create -volname "$APP_NAME" -srcfolder "$APP_BUNDLE" -ov -format UDZO "$DMG_DIR/$DMG_NAME"
echo ""
echo "=== DMG recreation complete ==="
ls -lh "$DMG_DIR/$DMG_NAME"
-113
View File
@@ -1,113 +0,0 @@
#!/bin/bash
# Re-sign macOS app bundle after TDLib bundling
# Required because modifying the bundle invalidates the original code signature.
#
# Usage:
# ./resign-macos.sh <build_type> [target]
#
# Arguments:
# build_type - "release" or "debug" (default: release)
# target - Optional cross-compilation target (e.g., aarch64-apple-darwin)
#
# Environment variables:
# APPLE_SIGNING_IDENTITY - Signing identity (e.g., "Developer ID Application: ...")
# If unset, uses ad-hoc signing ("-") for local testing.
# APPLE_CERTIFICATE - Base64-encoded .p12 certificate (CI only)
# APPLE_CERTIFICATE_PASSWORD - Password for the .p12 certificate (CI only)
#
# Examples:
# # Local testing (ad-hoc signing)
# ./resign-macos.sh release
#
# # CI with identity
# APPLE_SIGNING_IDENTITY="Developer ID Application: ..." ./resign-macos.sh release aarch64-apple-darwin
set -e
BUILD_TYPE="${1:-release}"
TARGET="${2:-}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TAURI_DIR="$(dirname "$SCRIPT_DIR")"
SIGNING_IDENTITY="${APPLE_SIGNING_IDENTITY:--}"
echo "=== macOS App Re-signing ==="
echo "Build type: ${BUILD_TYPE}"
echo "Target: ${TARGET:-default}"
echo "Signing identity: ${SIGNING_IDENTITY}"
# --- CI keychain setup (only when APPLE_CERTIFICATE is provided) ---
KEYCHAIN_PATH=""
if [ -n "$APPLE_CERTIFICATE" ] && [ -n "$APPLE_CERTIFICATE_PASSWORD" ]; then
echo ""
echo "Importing certificate into temporary keychain..."
TEMP_DIR="${RUNNER_TEMP:-/tmp}"
KEYCHAIN_PATH="$TEMP_DIR/tdlib-signing.keychain-db"
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
CERT_PATH="$TEMP_DIR/certificate.p12"
echo "$APPLE_CERTIFICATE" | base64 --decode > "$CERT_PATH"
security import "$CERT_PATH" -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
rm "$CERT_PATH"
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
echo "Certificate imported"
fi
# --- Find the app bundle ---
APP_BUNDLE=""
for search_dir in \
"${TAURI_DIR}/target/${TARGET}/${BUILD_TYPE}/bundle/macos" \
"${TAURI_DIR}/target/${BUILD_TYPE}/bundle/macos" \
"${TAURI_DIR}/target/release/bundle/macos" \
"${TAURI_DIR}/target/debug/bundle/macos"; do
if [ -d "$search_dir" ]; then
found=$(find "$search_dir" -name "*.app" -type d 2>/dev/null | head -1)
if [ -n "$found" ]; then
APP_BUNDLE="$found"
break
fi
fi
done
if [ -z "$APP_BUNDLE" ]; then
echo "Warning: No .app bundle found, nothing to sign"
exit 0
fi
echo ""
echo "Signing app bundle: $APP_BUNDLE"
# --- Sign bundled dylibs first (inner-to-outer signing order) ---
FRAMEWORKS_DIR="$APP_BUNDLE/Contents/Frameworks"
if [ -d "$FRAMEWORKS_DIR" ]; then
for dylib in "$FRAMEWORKS_DIR"/*.dylib; do
if [ -f "$dylib" ]; then
echo " Signing: $(basename "$dylib")"
codesign --force --options runtime --sign "$SIGNING_IDENTITY" "$dylib"
fi
done
fi
# --- Sign the app bundle ---
echo " Signing: $(basename "$APP_BUNDLE")"
codesign --force --deep --options runtime --sign "$SIGNING_IDENTITY" "$APP_BUNDLE"
# --- Verify ---
echo ""
echo "Verifying signature..."
codesign --verify --verbose=2 "$APP_BUNDLE" 2>&1 || echo "Warning: Signature verification had issues"
# --- Cleanup CI keychain ---
if [ -n "$KEYCHAIN_PATH" ]; then
security delete-keychain "$KEYCHAIN_PATH" || true
fi
echo ""
echo "=== Re-signing complete ==="
+1 -3
View File
@@ -44,9 +44,7 @@
"background": "./images/background-dmg.png"
},
"frameworks": [
"./libraries/libtdjson.1.8.29.dylib",
"./libraries/libssl.3.dylib",
"./libraries/libcrypto.3.dylib"
"./libraries/libtdjson.1.8.29.dylib"
]
}
},