mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
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:
@@ -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/
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+174
@@ -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."
|
||||
@@ -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."
|
||||
@@ -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"
|
||||
@@ -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 ==="
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user