From d0fdcb43fc53dfc2224f6c21479a01702d09ce03 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Thu, 5 Feb 2026 20:32:23 +0530 Subject: [PATCH] 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. --- src-tauri/.gitignore | 4 + src-tauri/Cargo.toml | 11 +- src-tauri/build.rs | 117 +++++++++- src-tauri/scripts/build-tdlib-from-source.sh | 174 ++++++++++++++ src-tauri/scripts/bundle-tdlib-macos.sh | 234 ------------------- src-tauri/scripts/recreate-dmg-macos.sh | 81 ------- src-tauri/scripts/resign-macos.sh | 113 --------- src-tauri/tauri.conf.json | 4 +- 8 files changed, 303 insertions(+), 435 deletions(-) create mode 100755 src-tauri/scripts/build-tdlib-from-source.sh delete mode 100755 src-tauri/scripts/bundle-tdlib-macos.sh delete mode 100755 src-tauri/scripts/recreate-dmg-macos.sh delete mode 100755 src-tauri/scripts/resign-macos.sh diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore index 3a30809c8..28b36d3b1 100644 --- a/src-tauri/.gitignore +++ b/src-tauri/.gitignore @@ -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/ diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 93239b688..becb1fc2c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -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] diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 7cc371b36..9a9a04670 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -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-/ (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()); + } } diff --git a/src-tauri/scripts/build-tdlib-from-source.sh b/src-tauri/scripts/build-tdlib-from-source.sh new file mode 100755 index 000000000..6d2bd8afd --- /dev/null +++ b/src-tauri/scripts/build-tdlib-from-source.sh @@ -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." diff --git a/src-tauri/scripts/bundle-tdlib-macos.sh b/src-tauri/scripts/bundle-tdlib-macos.sh deleted file mode 100755 index 99d5ac53c..000000000 --- a/src-tauri/scripts/bundle-tdlib-macos.sh +++ /dev/null @@ -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." diff --git a/src-tauri/scripts/recreate-dmg-macos.sh b/src-tauri/scripts/recreate-dmg-macos.sh deleted file mode 100755 index e8cd3ca42..000000000 --- a/src-tauri/scripts/recreate-dmg-macos.sh +++ /dev/null @@ -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 [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" diff --git a/src-tauri/scripts/resign-macos.sh b/src-tauri/scripts/resign-macos.sh deleted file mode 100755 index 7d57fb989..000000000 --- a/src-tauri/scripts/resign-macos.sh +++ /dev/null @@ -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 [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 ===" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 848569802..435f130b5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -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" ] } },