mirror of
https://github.com/aaddrick/claude-desktop-debian.git
synced 2026-05-17 00:26:21 +03:00
Getting the deb to work with local packages only
This commit is contained in:
518
build-deb.sh
518
build-deb.sh
@@ -31,16 +31,20 @@ fi
|
||||
|
||||
# Check for root/sudo
|
||||
IS_SUDO=false
|
||||
ORIGINAL_USER=""
|
||||
ORIGINAL_HOME=""
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
IS_SUDO=true
|
||||
# Check if running via sudo (and not directly as root)
|
||||
if [ -n "$SUDO_USER" ]; then
|
||||
ORIGINAL_USER="$SUDO_USER"
|
||||
ORIGINAL_HOME=$(eval echo ~$ORIGINAL_USER)
|
||||
ORIGINAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6) # More reliable way to get home dir
|
||||
echo "Running with sudo as user: $ORIGINAL_USER (Home: $ORIGINAL_HOME)"
|
||||
else
|
||||
# Running directly as root, no original user context
|
||||
ORIGINAL_USER="root"
|
||||
ORIGINAL_HOME="/root"
|
||||
echo "Running directly as root."
|
||||
fi
|
||||
else
|
||||
echo "Please run with sudo to install dependencies"
|
||||
@@ -52,17 +56,19 @@ if [ "$IS_SUDO" = true ] && [ "$ORIGINAL_USER" != "root" ] && [ -d "$ORIGINAL_HO
|
||||
echo "Found NVM installation for user $ORIGINAL_USER, attempting to preserve npm/npx path..."
|
||||
# Source NVM script to set up NVM environment variables temporarily
|
||||
export NVM_DIR="$ORIGINAL_HOME/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
|
||||
if [ -s "$NVM_DIR/nvm.sh" ]; then
|
||||
\. "$NVM_DIR/nvm.sh" # This loads nvm
|
||||
# Find the path to the currently active or default Node version's bin directory
|
||||
NODE_BIN_PATH=$(nvm which current | xargs dirname 2>/dev/null || find "$NVM_DIR/versions/node" -maxdepth 2 -type d -name 'bin' | sort -V | tail -n 1)
|
||||
|
||||
# Find the path to the currently active or default Node version's bin directory
|
||||
# nvm_find_node_version might not be available, try finding the latest installed version
|
||||
NODE_BIN_PATH=$(find "$NVM_DIR/versions/node" -maxdepth 2 -type d -name 'bin' | sort -V | tail -n 1)
|
||||
|
||||
if [ -n "$NODE_BIN_PATH" ] && [ -d "$NODE_BIN_PATH" ]; then
|
||||
echo "Adding $NODE_BIN_PATH to PATH"
|
||||
export PATH="$NODE_BIN_PATH:$PATH"
|
||||
if [ -n "$NODE_BIN_PATH" ] && [ -d "$NODE_BIN_PATH" ]; then
|
||||
echo "Adding $NODE_BIN_PATH to PATH"
|
||||
export PATH="$NODE_BIN_PATH:$PATH"
|
||||
else
|
||||
echo "Warning: Could not determine NVM Node bin path. npm/npx might not be found."
|
||||
fi
|
||||
else
|
||||
echo "Warning: Could not determine NVM Node bin path. npm/npx might not be found."
|
||||
echo "Warning: nvm.sh script not found or not sourceable."
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -77,7 +83,8 @@ echo "Target Architecture: $ARCHITECTURE" # Display the target architecture
|
||||
PACKAGE_NAME="claude-desktop"
|
||||
MAINTAINER="Claude Desktop Linux Maintainers"
|
||||
DESCRIPTION="Claude Desktop for Linux"
|
||||
WORK_DIR="$(pwd)/build" # Top-level build directory
|
||||
PROJECT_ROOT="$(pwd)" # Save project root
|
||||
WORK_DIR="$PROJECT_ROOT/build" # Top-level build directory
|
||||
APP_STAGING_DIR="$WORK_DIR/electron-app" # Staging for app files before packaging
|
||||
VERSION="" # Will be determined after download
|
||||
|
||||
@@ -117,6 +124,43 @@ while true; do
|
||||
done
|
||||
echo "-------------------------------------" # Add separator after selection/before next steps
|
||||
# --- End Build Format Selection ---
|
||||
# --- Cleanup Selection ---
|
||||
PERFORM_CLEANUP=false # Default to keeping files
|
||||
display_cleanup_menu() {
|
||||
echo -e "\n\033[1;34m====== Cleanup Build Files ======\033[0m"
|
||||
echo -e "This refers to the intermediate files created in the '$WORK_DIR' directory."
|
||||
echo -e "\033[1;32m [1] Yes, remove intermediate build files after completion\033[0m"
|
||||
echo -e "\033[1;32m [2] No, keep intermediate build files\033[0m"
|
||||
echo -e "\033[1;34m=================================\033[0m"
|
||||
}
|
||||
|
||||
CLEANUP_CHOICE=""
|
||||
while true; do
|
||||
display_cleanup_menu
|
||||
read -n 1 -p $'\nEnter choice (1 or 2, any other key to cancel prompt): ' CLEANUP_CHOICE
|
||||
echo
|
||||
|
||||
case $CLEANUP_CHOICE in
|
||||
"1")
|
||||
echo -e "\033[1;36m✔ Intermediate build files will be removed upon completion.\033[0m"
|
||||
PERFORM_CLEANUP=true
|
||||
break
|
||||
;;
|
||||
"2")
|
||||
echo -e "\033[1;36m✔ Intermediate build files will be kept.\033[0m"
|
||||
PERFORM_CLEANUP=false
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo # Add newline for clarity
|
||||
echo -e "\033[1;33m⚠ Skipping cleanup decision. Build files will be kept.\033[0m"
|
||||
PERFORM_CLEANUP=false # Default to keeping files
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "-------------------------------------"
|
||||
# --- End Cleanup Selection ---
|
||||
|
||||
|
||||
# Function to check if a command exists
|
||||
@@ -137,7 +181,7 @@ DEPS_TO_INSTALL=""
|
||||
COMMON_DEPS="p7zip wget wrestool icotool convert npx"
|
||||
# Format specific dependencies
|
||||
DEB_DEPS="dpkg-dev"
|
||||
APPIMAGE_DEPS="" # Add appimagetool, fuse if needed later
|
||||
APPIMAGE_DEPS="" # appimagetool handled by its script
|
||||
|
||||
ALL_DEPS_TO_CHECK="$COMMON_DEPS"
|
||||
if [ "$BUILD_FORMAT" = "deb" ]; then
|
||||
@@ -155,7 +199,6 @@ for cmd in $ALL_DEPS_TO_CHECK; do
|
||||
"convert") DEPS_TO_INSTALL="$DEPS_TO_INSTALL imagemagick" ;;
|
||||
"npx") DEPS_TO_INSTALL="$DEPS_TO_INSTALL nodejs npm" ;;
|
||||
"dpkg-deb") DEPS_TO_INSTALL="$DEPS_TO_INSTALL dpkg-dev" ;;
|
||||
# Add cases for AppImage deps if needed
|
||||
esac
|
||||
fi
|
||||
done
|
||||
@@ -168,332 +211,315 @@ if [ ! -z "$DEPS_TO_INSTALL" ]; then
|
||||
echo "System dependencies installed successfully"
|
||||
fi
|
||||
|
||||
# Check for electron - first local, then global (Needed for both formats potentially)
|
||||
LOCAL_ELECTRON="" # Initialize variable
|
||||
# Check for local electron in node_modules
|
||||
if [ -f "$(pwd)/node_modules/.bin/electron" ]; then
|
||||
echo "✓ local electron found in node_modules"
|
||||
LOCAL_ELECTRON="$(pwd)/node_modules/.bin/electron"
|
||||
export PATH="$(pwd)/node_modules/.bin:$PATH"
|
||||
elif ! check_command "electron"; then
|
||||
echo "Installing electron via npm..."
|
||||
# Try local installation first
|
||||
if [ -f "package.json" ]; then
|
||||
echo "Found package.json, installing electron locally..."
|
||||
npm install --save-dev electron
|
||||
if [ -f "$(pwd)/node_modules/.bin/electron" ]; then
|
||||
echo "✓ Local electron installed successfully"
|
||||
LOCAL_ELECTRON="$(pwd)/node_modules/.bin/electron"
|
||||
export PATH="$(pwd)/node_modules/.bin:$PATH"
|
||||
else
|
||||
# Fall back to global installation if local fails
|
||||
echo "Local electron install failed or not possible, trying global..."
|
||||
npm install -g electron
|
||||
# Attempt to fix permissions if installed globally
|
||||
if check_command "electron"; then
|
||||
ELECTRON_PATH=$(command -v electron)
|
||||
echo "Attempting to fix permissions for global electron at $ELECTRON_PATH..."
|
||||
chmod -R a+rx "$(dirname "$ELECTRON_PATH")/../lib/node_modules/electron" || echo "Warning: Failed to chmod global electron installation directory. Permissions might be incorrect."
|
||||
fi
|
||||
if ! check_command "electron"; then
|
||||
echo "Failed to install electron globally. Please install it manually:"
|
||||
echo "npm install -g electron # or npm install --save-dev electron in project root"
|
||||
exit 1
|
||||
fi
|
||||
echo "Global electron installed successfully"
|
||||
fi
|
||||
else
|
||||
# No package.json, try global installation
|
||||
echo "No package.json found, trying global electron installation..."
|
||||
npm install -g electron
|
||||
# Attempt to fix permissions if installed globally
|
||||
if check_command "electron"; then
|
||||
ELECTRON_PATH=$(command -v electron)
|
||||
echo "Attempting to fix permissions for global electron at $ELECTRON_PATH..."
|
||||
chmod -R a+rx "$(dirname "$ELECTRON_PATH")/../lib/node_modules/electron" || echo "Warning: Failed to chmod global electron installation directory. Permissions might be incorrect."
|
||||
fi
|
||||
if ! check_command "electron"; then
|
||||
echo "Failed to install electron globally. Please install it manually:"
|
||||
echo "npm install -g electron"
|
||||
exit 1
|
||||
fi
|
||||
echo "Global electron installed successfully"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean previous build
|
||||
# Clean previous build directory FIRST
|
||||
rm -rf "$WORK_DIR"
|
||||
mkdir -p "$WORK_DIR"
|
||||
mkdir -p "$APP_STAGING_DIR" # Create the app staging directory explicitly
|
||||
|
||||
# Install asar if needed
|
||||
if ! npm list -g asar > /dev/null 2>&1; then
|
||||
echo "Installing asar package globally..."
|
||||
npm install -g asar
|
||||
# --- Electron & Asar Handling ---
|
||||
CHOSEN_ELECTRON_MODULE_PATH="" # Path to the electron module directory to be copied
|
||||
ASAR_EXEC="" # Path to the asar executable
|
||||
TEMP_PACKAGE_JSON_CREATED=false
|
||||
|
||||
# Always ensure local Electron & Asar installation in WORK_DIR
|
||||
echo "Ensuring local Electron and Asar installation in $WORK_DIR..."
|
||||
cd "$WORK_DIR" # Change to build dir for local install
|
||||
|
||||
# Create dummy package.json if none exists in build dir
|
||||
if [ ! -f "package.json" ]; then
|
||||
echo "Creating temporary package.json in $WORK_DIR for local install..."
|
||||
echo '{"name":"claude-desktop-build","version":"0.0.1","private":true}' > package.json
|
||||
TEMP_PACKAGE_JSON_CREATED=true
|
||||
fi
|
||||
|
||||
# Install electron and asar locally if not already present
|
||||
# Check for Electron dist dir and Asar binary first
|
||||
ELECTRON_DIST_PATH="$WORK_DIR/node_modules/electron/dist"
|
||||
ASAR_BIN_PATH="$WORK_DIR/node_modules/.bin/asar"
|
||||
|
||||
INSTALL_NEEDED=false
|
||||
if [ ! -d "$ELECTRON_DIST_PATH" ]; then
|
||||
echo "Electron distribution not found."
|
||||
INSTALL_NEEDED=true
|
||||
fi
|
||||
if [ ! -f "$ASAR_BIN_PATH" ]; then
|
||||
echo "Asar binary not found."
|
||||
INSTALL_NEEDED=true
|
||||
fi
|
||||
|
||||
if [ "$INSTALL_NEEDED" = true ]; then
|
||||
echo "Installing Electron and Asar locally into $WORK_DIR..."
|
||||
# Use --no-save to avoid modifying the temp package.json unnecessarily
|
||||
if ! npm install --no-save electron asar; then
|
||||
echo "❌ Failed to install Electron and/or Asar locally."
|
||||
cd "$PROJECT_ROOT"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Electron and Asar installation command finished."
|
||||
else
|
||||
echo "✓ Local Electron distribution and Asar binary already present."
|
||||
fi
|
||||
|
||||
# Verify Electron installation by checking for the essential 'dist' directory
|
||||
if [ -d "$ELECTRON_DIST_PATH" ]; then
|
||||
echo "✓ Found Electron distribution directory at $ELECTRON_DIST_PATH."
|
||||
CHOSEN_ELECTRON_MODULE_PATH="$(realpath "$WORK_DIR/node_modules/electron")"
|
||||
echo "✓ Setting Electron module path for copying to $CHOSEN_ELECTRON_MODULE_PATH."
|
||||
else
|
||||
echo "❌ Failed to find Electron distribution directory at '$ELECTRON_DIST_PATH' after installation attempt."
|
||||
echo " Cannot proceed without the Electron distribution files."
|
||||
cd "$PROJECT_ROOT" # Go back before exiting
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify Asar installation
|
||||
if [ -f "$ASAR_BIN_PATH" ]; then
|
||||
ASAR_EXEC="$(realpath "$ASAR_BIN_PATH")"
|
||||
echo "✓ Found local Asar binary at $ASAR_EXEC."
|
||||
else
|
||||
echo "❌ Failed to find Asar binary at '$ASAR_BIN_PATH' after installation attempt."
|
||||
cd "$PROJECT_ROOT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT" # Go back to project root
|
||||
|
||||
# Final check for the chosen Electron module path (redundant but safe)
|
||||
if [ -z "$CHOSEN_ELECTRON_MODULE_PATH" ] || [ ! -d "$CHOSEN_ELECTRON_MODULE_PATH" ]; then
|
||||
echo "❌ Critical error: Could not resolve a valid Electron module path to copy."
|
||||
exit 1
|
||||
fi
|
||||
echo "Using Electron module path: $CHOSEN_ELECTRON_MODULE_PATH"
|
||||
echo "Using asar executable: $ASAR_EXEC"
|
||||
# --- End Electron & Asar Handling ---
|
||||
|
||||
|
||||
# Download Claude Windows installer for the target architecture
|
||||
echo "📥 Downloading Claude Desktop installer for $ARCHITECTURE..."
|
||||
CLAUDE_EXE_PATH="$WORK_DIR/$CLAUDE_EXE_FILENAME" # Use the arch-specific filename
|
||||
CLAUDE_EXE_PATH="$WORK_DIR/$CLAUDE_EXE_FILENAME"
|
||||
if ! wget -O "$CLAUDE_EXE_PATH" "$CLAUDE_DOWNLOAD_URL"; then
|
||||
echo "❌ Failed to download Claude Desktop installer from $CLAUDE_DOWNLOAD_URL"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Download complete: $CLAUDE_EXE_FILENAME"
|
||||
|
||||
# Extract resources
|
||||
echo "📦 Extracting resources from $CLAUDE_EXE_FILENAME..."
|
||||
cd "$WORK_DIR"
|
||||
if ! 7z x -y "$CLAUDE_EXE_PATH"; then # Use the arch-specific path
|
||||
# Extract resources into a dedicated subdirectory to avoid conflicts
|
||||
echo "📦 Extracting resources from $CLAUDE_EXE_FILENAME into separate directory..."
|
||||
CLAUDE_EXTRACT_DIR="$WORK_DIR/claude-extract"
|
||||
mkdir -p "$CLAUDE_EXTRACT_DIR"
|
||||
if ! 7z x -y "$CLAUDE_EXE_PATH" -o"$CLAUDE_EXTRACT_DIR"; then # Extract to specific dir
|
||||
echo "❌ Failed to extract installer"
|
||||
exit 1
|
||||
cd "$PROJECT_ROOT" && exit 1
|
||||
fi
|
||||
|
||||
# Extract nupkg filename and version
|
||||
# The nupkg name might differ slightly for arm64, adjust find pattern if needed
|
||||
# Assuming it still starts with AnthropicClaude- for now
|
||||
NUPKG_PATH=$(find . -name "AnthropicClaude-*.nupkg" | head -1)
|
||||
if [ -z "$NUPKG_PATH" ]; then
|
||||
echo "❌ Could not find AnthropicClaude nupkg file in $WORK_DIR"
|
||||
exit 1
|
||||
cd "$CLAUDE_EXTRACT_DIR" # Change into the extract dir to find files
|
||||
NUPKG_PATH_RELATIVE=$(find . -maxdepth 1 -name "AnthropicClaude-*.nupkg" | head -1)
|
||||
if [ -z "$NUPKG_PATH_RELATIVE" ]; then
|
||||
echo "❌ Could not find AnthropicClaude nupkg file in $CLAUDE_EXTRACT_DIR"
|
||||
cd "$PROJECT_ROOT" && exit 1
|
||||
fi
|
||||
echo "Found nupkg: $NUPKG_PATH"
|
||||
NUPKG_PATH="$CLAUDE_EXTRACT_DIR/$NUPKG_PATH_RELATIVE" # Store full path
|
||||
echo "Found nupkg: $NUPKG_PATH_RELATIVE (in $CLAUDE_EXTRACT_DIR)"
|
||||
|
||||
# Extract version from the nupkg filename (using LC_ALL=C for locale compatibility)
|
||||
# Assuming version format is consistent across architectures
|
||||
VERSION=$(echo "$NUPKG_PATH" | LC_ALL=C grep -oP 'AnthropicClaude-\K[0-9]+\.[0-9]+\.[0-9]+(?=-full|-arm64-full)') # Adjusted regex slightly
|
||||
VERSION=$(echo "$NUPKG_PATH_RELATIVE" | LC_ALL=C grep -oP 'AnthropicClaude-\K[0-9]+\.[0-9]+\.[0-9]+(?=-full|-arm64-full)')
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "❌ Could not extract version from nupkg filename: $NUPKG_PATH"
|
||||
exit 1
|
||||
echo "❌ Could not extract version from nupkg filename: $NUPKG_PATH_RELATIVE"
|
||||
cd "$PROJECT_ROOT" && exit 1
|
||||
fi
|
||||
echo "✓ Detected Claude version: $VERSION"
|
||||
|
||||
if ! 7z x -y "$NUPKG_PATH"; then
|
||||
# Extract nupkg within its directory
|
||||
if ! 7z x -y "$NUPKG_PATH_RELATIVE"; then # Use relative path since we are in CLAUDE_EXTRACT_DIR
|
||||
echo "❌ Failed to extract nupkg"
|
||||
exit 1
|
||||
cd "$PROJECT_ROOT" && exit 1
|
||||
fi
|
||||
echo "✓ Resources extracted"
|
||||
echo "✓ Resources extracted from nupkg"
|
||||
|
||||
# Extract and convert icons (needed by the packaging script later)
|
||||
# Assuming claude.exe exists in the extracted structure for both archs
|
||||
# Still operating within CLAUDE_EXTRACT_DIR
|
||||
EXE_RELATIVE_PATH="lib/net45/claude.exe" # Check if this path is correct for arm64 too
|
||||
if [ ! -f "$EXE_RELATIVE_PATH" ]; then
|
||||
echo "❌ Cannot find claude.exe at expected path: $EXE_RELATIVE_PATH"
|
||||
# Add alternative path check if needed for arm64
|
||||
# find . -name claude.exe # Uncomment to help debug if needed
|
||||
exit 1
|
||||
echo "❌ Cannot find claude.exe at expected path within extraction dir: $CLAUDE_EXTRACT_DIR/$EXE_RELATIVE_PATH"
|
||||
cd "$PROJECT_ROOT" && exit 1
|
||||
fi
|
||||
echo "🎨 Processing icons from $EXE_RELATIVE_PATH..."
|
||||
if ! wrestool -x -t 14 "$EXE_RELATIVE_PATH" -o claude.ico; then
|
||||
# Output icons within the extraction directory
|
||||
if ! wrestool -x -t 14 "$EXE_RELATIVE_PATH" -o claude.ico; then # Output relative to current dir (CLAUDE_EXTRACT_DIR)
|
||||
echo "❌ Failed to extract icons from exe"
|
||||
exit 1
|
||||
cd "$PROJECT_ROOT" && exit 1
|
||||
fi
|
||||
|
||||
if ! icotool -x claude.ico; then
|
||||
if ! icotool -x claude.ico; then # Input relative to current dir (CLAUDE_EXTRACT_DIR)
|
||||
echo "❌ Failed to convert icons"
|
||||
exit 1
|
||||
cd "$PROJECT_ROOT" && exit 1
|
||||
fi
|
||||
echo "✓ Icons processed (will be used by packaging script)"
|
||||
# Copy extracted icons to WORK_DIR for packaging scripts to find easily
|
||||
cp claude_*.png "$WORK_DIR/"
|
||||
echo "✓ Icons processed and copied to $WORK_DIR"
|
||||
|
||||
# Process app.asar
|
||||
# Assuming app.asar structure is consistent across architectures
|
||||
echo "⚙️ Processing app.asar..."
|
||||
cp "lib/net45/resources/app.asar" "$APP_STAGING_DIR/"
|
||||
cp -r "lib/net45/resources/app.asar.unpacked" "$APP_STAGING_DIR/"
|
||||
# Copy resources to staging dir first, using full paths from the extraction dir
|
||||
cp "$CLAUDE_EXTRACT_DIR/lib/net45/resources/app.asar" "$APP_STAGING_DIR/"
|
||||
cp -a "$CLAUDE_EXTRACT_DIR/lib/net45/resources/app.asar.unpacked" "$APP_STAGING_DIR/" # Use -a to preserve links/permissions
|
||||
|
||||
cd "$APP_STAGING_DIR"
|
||||
npx asar extract app.asar app.asar.contents
|
||||
cd "$APP_STAGING_DIR" # Change to staging dir for asar processing
|
||||
"$ASAR_EXEC" extract app.asar app.asar.contents
|
||||
|
||||
# Replace native module with stub implementation
|
||||
echo "Creating stub native module..."
|
||||
cat > app.asar.contents/node_modules/claude-native/index.js << EOF
|
||||
// Stub implementation of claude-native using KeyboardKey enum values
|
||||
const KeyboardKey = {
|
||||
Backspace: 43,
|
||||
Tab: 280,
|
||||
Enter: 261,
|
||||
Shift: 272,
|
||||
Control: 61,
|
||||
Alt: 40,
|
||||
CapsLock: 56,
|
||||
Escape: 85,
|
||||
Space: 276,
|
||||
PageUp: 251,
|
||||
PageDown: 250,
|
||||
End: 83,
|
||||
Home: 154,
|
||||
LeftArrow: 175,
|
||||
UpArrow: 282,
|
||||
RightArrow: 262,
|
||||
DownArrow: 81,
|
||||
Delete: 79,
|
||||
Meta: 187
|
||||
};
|
||||
|
||||
const KeyboardKey = { Backspace: 43, Tab: 280, Enter: 261, Shift: 272, Control: 61, Alt: 40, CapsLock: 56, Escape: 85, Space: 276, PageUp: 251, PageDown: 250, End: 83, Home: 154, LeftArrow: 175, UpArrow: 282, RightArrow: 262, DownArrow: 81, Delete: 79, Meta: 187 };
|
||||
Object.freeze(KeyboardKey);
|
||||
|
||||
module.exports = {
|
||||
getWindowsVersion: () => "10.0.0", // Keep this generic?
|
||||
setWindowEffect: () => {},
|
||||
removeWindowEffect: () => {},
|
||||
getIsMaximized: () => false,
|
||||
flashFrame: () => {},
|
||||
clearFlashFrame: () => {},
|
||||
showNotification: () => {},
|
||||
setProgressBar: () => {},
|
||||
clearProgressBar: () => {},
|
||||
setOverlayIcon: () => {},
|
||||
clearOverlayIcon: () => {},
|
||||
KeyboardKey
|
||||
};
|
||||
module.exports = { getWindowsVersion: () => "10.0.0", setWindowEffect: () => {}, removeWindowEffect: () => {}, getIsMaximized: () => false, flashFrame: () => {}, clearFlashFrame: () => {}, showNotification: () => {}, setProgressBar: () => {}, clearProgressBar: () => {}, setOverlayIcon: () => {}, clearOverlayIcon: () => {}, KeyboardKey };
|
||||
EOF
|
||||
|
||||
# Copy Tray icons
|
||||
mkdir -p app.asar.contents/resources
|
||||
mkdir -p app.asar.contents/resources/i18n
|
||||
|
||||
cp ../lib/net45/resources/Tray* app.asar.contents/resources/
|
||||
# Copy only the language-specific JSON files (e.g., en-US.json)
|
||||
cp ../lib/net45/resources/*-*.json app.asar.contents/resources/i18n/
|
||||
# Copy from the extraction directory (use full path for clarity)
|
||||
cp "$CLAUDE_EXTRACT_DIR/lib/net45/resources/Tray"* app.asar.contents/resources/
|
||||
cp "$CLAUDE_EXTRACT_DIR/lib/net45/resources/"*-*.json app.asar.contents/resources/i18n/
|
||||
|
||||
echo "Downloading Main Window Fix Assets"
|
||||
cd app.asar.contents
|
||||
wget -O- https://github.com/emsi/claude-desktop/raw/refs/heads/main/assets/main_window.tgz | tar -zxvf -
|
||||
cd ..
|
||||
cd .. # Back to APP_STAGING_DIR
|
||||
|
||||
# Repackage app.asar
|
||||
npx asar pack app.asar.contents app.asar
|
||||
"$ASAR_EXEC" pack app.asar.contents app.asar
|
||||
|
||||
# Create native module stub within the staging area's unpacked directory
|
||||
mkdir -p "$APP_STAGING_DIR/app.asar.unpacked/node_modules/claude-native"
|
||||
cat > "$APP_STAGING_DIR/app.asar.unpacked/node_modules/claude-native/index.js" << EOF
|
||||
// Stub implementation of claude-native using KeyboardKey enum values
|
||||
const KeyboardKey = {
|
||||
Backspace: 43,
|
||||
Tab: 280,
|
||||
Enter: 261,
|
||||
Shift: 272,
|
||||
Control: 61,
|
||||
Alt: 40,
|
||||
CapsLock: 56,
|
||||
Escape: 85,
|
||||
Space: 276,
|
||||
PageUp: 251,
|
||||
PageDown: 250,
|
||||
End: 83,
|
||||
Home: 154,
|
||||
LeftArrow: 175,
|
||||
UpArrow: 282,
|
||||
RightArrow: 262,
|
||||
DownArrow: 81,
|
||||
Delete: 79,
|
||||
Meta: 187
|
||||
};
|
||||
|
||||
const KeyboardKey = { Backspace: 43, Tab: 280, Enter: 261, Shift: 272, Control: 61, Alt: 40, CapsLock: 56, Escape: 85, Space: 276, PageUp: 251, PageDown: 250, End: 83, Home: 154, LeftArrow: 175, UpArrow: 282, RightArrow: 262, DownArrow: 81, Delete: 79, Meta: 187 };
|
||||
Object.freeze(KeyboardKey);
|
||||
|
||||
module.exports = {
|
||||
getWindowsVersion: () => "10.0.0",
|
||||
setWindowEffect: () => {},
|
||||
removeWindowEffect: () => {},
|
||||
getIsMaximized: () => false,
|
||||
flashFrame: () => {},
|
||||
clearFlashFrame: () => {},
|
||||
showNotification: () => {},
|
||||
setProgressBar: () => {},
|
||||
clearProgressBar: () => {},
|
||||
setOverlayIcon: () => {},
|
||||
clearOverlayIcon: () => {},
|
||||
KeyboardKey
|
||||
};
|
||||
module.exports = { getWindowsVersion: () => "10.0.0", setWindowEffect: () => {}, removeWindowEffect: () => {}, getIsMaximized: () => false, flashFrame: () => {}, clearFlashFrame: () => {}, showNotification: () => {}, setProgressBar: () => {}, clearProgressBar: () => {}, setOverlayIcon: () => {}, clearOverlayIcon: () => {}, KeyboardKey };
|
||||
EOF
|
||||
|
||||
# Copy local electron if available
|
||||
if [ ! -z "$LOCAL_ELECTRON" ]; then
|
||||
echo "Copying local electron to staging area..."
|
||||
# Ensure the target node_modules directory exists in staging
|
||||
mkdir -p "$APP_STAGING_DIR/node_modules"
|
||||
# Copy the entire electron module directory
|
||||
# Go up one level from the binary path to get the module root
|
||||
ELECTRON_MODULE_PATH=$(dirname "$LOCAL_ELECTRON")/..
|
||||
echo "Copying from $ELECTRON_MODULE_PATH to $APP_STAGING_DIR/node_modules/"
|
||||
cp -r "$ELECTRON_MODULE_PATH" "$APP_STAGING_DIR/node_modules/"
|
||||
# Copy the chosen electron installation to the staging area
|
||||
echo "Copying chosen electron installation to staging area..."
|
||||
# Ensure the target node_modules directory exists in staging
|
||||
mkdir -p "$APP_STAGING_DIR/node_modules/"
|
||||
# Extract the directory name to copy (e.g., "electron")
|
||||
ELECTRON_DIR_NAME=$(basename "$CHOSEN_ELECTRON_MODULE_PATH")
|
||||
echo "Copying from $CHOSEN_ELECTRON_MODULE_PATH to $APP_STAGING_DIR/node_modules/"
|
||||
# Copy the directory itself into node_modules
|
||||
cp -a "$CHOSEN_ELECTRON_MODULE_PATH" "$APP_STAGING_DIR/node_modules/" # Use cp -a to preserve links/permissions
|
||||
|
||||
# Explicitly set executable permission on the copied electron binary
|
||||
STAGED_ELECTRON_BIN="$APP_STAGING_DIR/node_modules/$ELECTRON_DIR_NAME/dist/electron"
|
||||
if [ -f "$STAGED_ELECTRON_BIN" ]; then
|
||||
echo "Setting executable permission on staged Electron binary: $STAGED_ELECTRON_BIN"
|
||||
chmod +x "$STAGED_ELECTRON_BIN"
|
||||
else
|
||||
echo "Warning: Staged Electron binary not found at expected path: $STAGED_ELECTRON_BIN"
|
||||
fi
|
||||
|
||||
echo "✓ app.asar processed and staged in $APP_STAGING_DIR"
|
||||
|
||||
# Return to the original directory (project root) before calling the packaging script
|
||||
# We were in $APP_STAGING_DIR which is $WORK_DIR/electron-app
|
||||
cd .. # Go back from build/electron-app to build/
|
||||
cd .. # Go back from build/ to the project root
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# --- Call the appropriate packaging script ---
|
||||
FINAL_OUTPUT_PATH="" # Initialize variable for final path
|
||||
FINAL_DESKTOP_FILE_PATH="" # Initialize variable for desktop file path
|
||||
|
||||
if [ "$BUILD_FORMAT" = "deb" ]; then
|
||||
echo "📦 Calling Debian packaging script for $ARCHITECTURE..."
|
||||
# Ensure the script is executable
|
||||
chmod +x scripts/build-deb-package.sh
|
||||
|
||||
# Execute the script, passing necessary variables including the detected ARCHITECTURE
|
||||
scripts/build-deb-package.sh \
|
||||
"$VERSION" \
|
||||
"$ARCHITECTURE" \
|
||||
"$WORK_DIR" \
|
||||
"$APP_STAGING_DIR" \
|
||||
"$PACKAGE_NAME" \
|
||||
"$MAINTAINER" \
|
||||
"$DESCRIPTION"
|
||||
|
||||
# Check the exit code of the packaging script
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Debian packaging script failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Capture the final deb file path (using the determined ARCHITECTURE)
|
||||
# Find the .deb file in the work directory
|
||||
"$VERSION" "$ARCHITECTURE" "$WORK_DIR" "$APP_STAGING_DIR" \
|
||||
"$PACKAGE_NAME" "$MAINTAINER" "$DESCRIPTION"
|
||||
if [ $? -ne 0 ]; then echo "❌ Debian packaging script failed."; exit 1; fi
|
||||
DEB_FILE=$(find "$WORK_DIR" -maxdepth 1 -name "${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb" | head -n 1)
|
||||
|
||||
echo "✓ Debian Build complete!"
|
||||
if [ -n "$DEB_FILE" ] && [ -f "$DEB_FILE" ]; then
|
||||
echo "Package created at: $DEB_FILE"
|
||||
FINAL_OUTPUT_PATH="./${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb"
|
||||
mv "$DEB_FILE" "$FINAL_OUTPUT_PATH"
|
||||
echo "Package created at: $FINAL_OUTPUT_PATH"
|
||||
else
|
||||
echo "Warning: Could not determine final .deb file path from $WORK_DIR for ${ARCHITECTURE}."
|
||||
FINAL_OUTPUT_PATH="Not Found"
|
||||
fi
|
||||
|
||||
elif [ "$BUILD_FORMAT" = "appimage" ]; then
|
||||
echo "📦 Calling AppImage packaging script for $ARCHITECTURE..."
|
||||
# Ensure the script is executable
|
||||
chmod +x scripts/build-appimage.sh
|
||||
|
||||
# Execute the script, passing necessary variables
|
||||
scripts/build-appimage.sh \
|
||||
"$VERSION" \
|
||||
"$ARCHITECTURE" \
|
||||
"$WORK_DIR" \
|
||||
"$APP_STAGING_DIR" \
|
||||
"$PACKAGE_NAME" \
|
||||
"$MAINTAINER" \
|
||||
"$DESCRIPTION" # Maintainer/Desc might not be used but passed for consistency
|
||||
|
||||
# Check the exit code of the packaging script
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ AppImage packaging script failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Capture the final AppImage file path (using the determined ARCHITECTURE)
|
||||
# Find the .AppImage file in the work directory (adjust pattern if needed)
|
||||
"$VERSION" "$ARCHITECTURE" "$WORK_DIR" "$APP_STAGING_DIR" "$PACKAGE_NAME"
|
||||
if [ $? -ne 0 ]; then echo "❌ AppImage packaging script failed."; exit 1; fi
|
||||
APPIMAGE_FILE=$(find "$WORK_DIR" -maxdepth 1 -name "${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage" | head -n 1)
|
||||
|
||||
echo "✓ AppImage Build complete! (Placeholder)"
|
||||
echo "✓ AppImage Build complete!"
|
||||
if [ -n "$APPIMAGE_FILE" ] && [ -f "$APPIMAGE_FILE" ]; then
|
||||
echo "Package created at: $APPIMAGE_FILE"
|
||||
FINAL_OUTPUT_PATH="./${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage"
|
||||
mv "$APPIMAGE_FILE" "$FINAL_OUTPUT_PATH"
|
||||
echo "Package created at: $FINAL_OUTPUT_PATH"
|
||||
|
||||
# --- Generate .desktop file for AppImage ---
|
||||
FINAL_DESKTOP_FILE_PATH="./${PACKAGE_NAME}-appimage.desktop"
|
||||
APPIMAGE_ABS_PATH=$(realpath "$FINAL_OUTPUT_PATH")
|
||||
echo "📝 Generating .desktop file for AppImage at $FINAL_DESKTOP_FILE_PATH..."
|
||||
cat > "$FINAL_DESKTOP_FILE_PATH" << EOF
|
||||
[Desktop Entry]
|
||||
Name=Claude (AppImage)
|
||||
Comment=Claude Desktop (AppImage Version $VERSION)
|
||||
Exec=$APPIMAGE_ABS_PATH %u
|
||||
Icon=claude-desktop
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Categories=Office;Utility;Network;
|
||||
MimeType=x-scheme-handler/claude;
|
||||
StartupWMClass=Claude
|
||||
X-AppImage-Version=$VERSION
|
||||
X-AppImage-Name=Claude Desktop (AppImage)
|
||||
EOF
|
||||
echo "✓ .desktop file generated."
|
||||
|
||||
else
|
||||
echo "Note: AppImage creation is currently a placeholder."
|
||||
echo "Warning: Could not determine final .AppImage file path from $WORK_DIR for ${ARCHITECTURE}."
|
||||
FINAL_OUTPUT_PATH="Not Found"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean up intermediate files (optional, keep for debugging if needed)
|
||||
# echo "🧹 Cleaning up intermediate files..."
|
||||
# rm -rf "$WORK_DIR/lib" "$WORK_DIR/claude.ico" "$WORK_DIR"/*.png "$WORK_DIR/electron-app" "$WORK_DIR/package" "$WORK_DIR/RELEASES" "$WORK_DIR/Setup.exe" "$WORK_DIR/Setup.msi" "$WORK_DIR"/*.nupkg
|
||||
# --- Set Final Package Ownership ---
|
||||
if [ "$IS_SUDO" = true ] && [ "$ORIGINAL_USER" != "root" ]; then
|
||||
if [ "$FINAL_OUTPUT_PATH" != "Not Found" ] && [ -e "$FINAL_OUTPUT_PATH" ]; then
|
||||
echo "🔒 Setting ownership of $FINAL_OUTPUT_PATH to $ORIGINAL_USER..."
|
||||
chown "$ORIGINAL_USER":"$(id -gn "$ORIGINAL_USER")" "$FINAL_OUTPUT_PATH"
|
||||
echo "✓ Ownership set for package."
|
||||
fi
|
||||
# Set ownership for generated desktop file as well
|
||||
if [ -n "$FINAL_DESKTOP_FILE_PATH" ] && [ -e "$FINAL_DESKTOP_FILE_PATH" ]; then
|
||||
echo "🔒 Setting ownership of $FINAL_DESKTOP_FILE_PATH to $ORIGINAL_USER..."
|
||||
chown "$ORIGINAL_USER":"$(id -gn "$ORIGINAL_USER")" "$FINAL_DESKTOP_FILE_PATH"
|
||||
echo "✓ Ownership set for .desktop file."
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Cleanup ---
|
||||
if [ "$PERFORM_CLEANUP" = true ]; then
|
||||
echo "🧹 Cleaning up intermediate build files in $WORK_DIR..."
|
||||
# Be careful not to delete the final output package or desktop file
|
||||
# Keep the final package and desktop file, remove everything else in WORK_DIR
|
||||
find "$WORK_DIR" -mindepth 1 -maxdepth 1 \
|
||||
! -name "$(basename "$FINAL_OUTPUT_PATH" 2>/dev/null)" \
|
||||
! -name "$(basename "$FINAL_DESKTOP_FILE_PATH" 2>/dev/null)" \
|
||||
-exec rm -rf {} +
|
||||
echo "✓ Cleanup complete."
|
||||
else
|
||||
echo "Skipping cleanup of intermediate build files in $WORK_DIR."
|
||||
fi
|
||||
|
||||
# Clean up temporary package.json if created
|
||||
if [ "$TEMP_PACKAGE_JSON_CREATED" = true ] && [ -f "$WORK_DIR/package.json" ]; then
|
||||
echo "Removing temporary package.json from $WORK_DIR..."
|
||||
rm "$WORK_DIR/package.json"
|
||||
fi
|
||||
|
||||
echo "✅ Build process finished."
|
||||
exit 0
|
||||
|
||||
267
scripts/build-appimage.sh
Normal file → Executable file
267
scripts/build-appimage.sh
Normal file → Executable file
@@ -25,37 +25,250 @@ mkdir -p "$APPDIR_PATH/usr/share/icons/hicolor/256x256/apps"
|
||||
mkdir -p "$APPDIR_PATH/usr/share/applications"
|
||||
|
||||
echo "📦 Staging application files into AppDir..."
|
||||
# Copy the core application files (asar, unpacked resources)
|
||||
cp -r "$APP_STAGING_DIR/"* "$APPDIR_PATH/usr/lib/" # Copy contents into usr/lib
|
||||
|
||||
# Copy the launcher script (needs modification for AppDir context)
|
||||
# TODO: Create an AppRun script or adapt the existing launcher
|
||||
|
||||
# Copy icons
|
||||
echo "🎨 Copying icons..."
|
||||
ICON_SOURCE_PATH="$WORK_DIR/claude_6_256x256x32.png" # Assuming 256x256 icon exists from previous steps
|
||||
if [ -f "$ICON_SOURCE_PATH" ]; then
|
||||
cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/usr/share/icons/hicolor/256x256/apps/${PACKAGE_NAME}.png"
|
||||
# Also copy to top-level for AppImage icon
|
||||
cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/${PACKAGE_NAME}.png"
|
||||
else
|
||||
echo "Warning: Missing 256x256 icon at $ICON_SOURCE_PATH"
|
||||
# Copy the core application files (asar, unpacked resources, node_modules if present)
|
||||
# Explicitly copy required components to ensure hidden files/dirs like .bin are included
|
||||
if [ -f "$APP_STAGING_DIR/app.asar" ]; then
|
||||
cp -a "$APP_STAGING_DIR/app.asar" "$APPDIR_PATH/usr/lib/"
|
||||
fi
|
||||
if [ -d "$APP_STAGING_DIR/app.asar.unpacked" ]; then
|
||||
cp -a "$APP_STAGING_DIR/app.asar.unpacked" "$APPDIR_PATH/usr/lib/"
|
||||
fi
|
||||
if [ -d "$APP_STAGING_DIR/node_modules" ]; then
|
||||
echo "Copying node_modules from staging to AppDir..."
|
||||
cp -a "$APP_STAGING_DIR/node_modules" "$APPDIR_PATH/usr/lib/"
|
||||
fi
|
||||
|
||||
# Copy desktop file (needs modification for AppDir context)
|
||||
echo "📝 Copying desktop file..."
|
||||
DESKTOP_SOURCE_PATH="$APP_STAGING_DIR/../package/usr/share/applications/${PACKAGE_NAME}.desktop" # Assuming it was created for deb
|
||||
# TODO: Adapt desktop file Exec= line for AppDir
|
||||
# cp "$DESKTOP_SOURCE_PATH" "$APPDIR_PATH/" # Copy to top level
|
||||
# Ensure Electron is bundled within the AppDir for portability
|
||||
# Check if electron was copied into the staging dir's node_modules
|
||||
# The actual executable is usually inside the 'dist' directory
|
||||
BUNDLED_ELECTRON_PATH="$APPDIR_PATH/usr/lib/node_modules/electron/dist/electron"
|
||||
echo "Checking for executable at: $BUNDLED_ELECTRON_PATH"
|
||||
if [ ! -x "$BUNDLED_ELECTRON_PATH" ]; then # Check if it exists and is executable
|
||||
echo "❌ Electron executable not found or not executable in staging area ($BUNDLED_ELECTRON_PATH)."
|
||||
echo " AppImage requires Electron to be bundled. Ensure the main script copies it correctly."
|
||||
exit 1
|
||||
fi
|
||||
# Ensure the bundled electron is executable (redundant check, but safe)
|
||||
chmod +x "$BUNDLED_ELECTRON_PATH"
|
||||
|
||||
echo "🚧 AppImage building logic is not fully implemented yet."
|
||||
echo " - Need to create/adapt AppRun script."
|
||||
echo " - Need to adapt .desktop file."
|
||||
echo " - Need to download and use appimagetool."
|
||||
# --- Create AppRun Script ---
|
||||
echo "🚀 Creating AppRun script..."
|
||||
# Note: We use $VERSION and $PACKAGE_NAME from the build script environment here
|
||||
# They will be embedded into the AppRun script.
|
||||
DESKTOP_FILE_BASENAME="${PACKAGE_NAME}-${VERSION}.desktop" # Unique name
|
||||
cat > "$APPDIR_PATH/AppRun" << EOF
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Example placeholder for final step:
|
||||
# appimagetool "$APPDIR_PATH" "$WORK_DIR/${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage"
|
||||
# Find the location of the AppRun script and the AppImage file itself
|
||||
APPDIR=\$(dirname "\$0")
|
||||
# Try to get the absolute path of the AppImage file being run
|
||||
# $APPIMAGE is often set by the AppImage runtime, otherwise try readlink
|
||||
APPIMAGE_PATH="\${APPIMAGE:-}"
|
||||
if [ -z "\$APPIMAGE_PATH" ]; then
|
||||
# Find the AppRun script itself, which should be $0
|
||||
# Use readlink -f to get the absolute path, handling symlinks
|
||||
# Go up one level from AppRun's dir to get the AppImage path (usually)
|
||||
# This might be fragile if AppRun is not at the root, but it's standard.
|
||||
APPIMAGE_PATH=\$(readlink -f "\$APPDIR/../$(basename "$APPDIR" .AppDir).AppImage" 2>/dev/null || readlink -f "\$0" 2>/dev/null)
|
||||
# As a final fallback, just use $0, hoping it's the AppImage path
|
||||
if [ -z "\$APPIMAGE_PATH" ] || [ ! -f "\$APPIMAGE_PATH" ]; then
|
||||
APPIMAGE_PATH="\$0"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "--- AppImage Build Placeholder Finished ---"
|
||||
# --- Attempt to Register claude:// URI Scheme Handler ---
|
||||
register_uri_scheme() {
|
||||
local desktop_file_basename="$1"
|
||||
local appimage_exec_path="$2"
|
||||
local scheme="claude"
|
||||
|
||||
echo "AppRun: Attempting to register x-scheme-handler/$scheme..."
|
||||
|
||||
# Check if necessary tools exist
|
||||
if ! command -v xdg-mime >/dev/null 2>&1 || ! command -v update-desktop-database >/dev/null 2>&1; then
|
||||
echo "AppRun: Warning - xdg-mime or update-desktop-database not found. Cannot register URI scheme."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Define user's local applications directory
|
||||
local user_apps_dir="\$HOME/.local/share/applications"
|
||||
mkdir -p "\$user_apps_dir"
|
||||
|
||||
local desktop_file_path="\$user_apps_dir/\$desktop_file_basename"
|
||||
|
||||
echo "AppRun: Creating desktop file at \$desktop_file_path"
|
||||
# Create the .desktop file
|
||||
# Use the determined absolute path to the AppImage for Exec
|
||||
cat > "\$desktop_file_path" << DESKTOP_EOF
|
||||
[Desktop Entry]
|
||||
Name=Claude (AppImage $VERSION)
|
||||
Comment=Claude Desktop (AppImage Version $VERSION)
|
||||
Exec=$appimage_exec_path %u
|
||||
Icon=$PACKAGE_NAME
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Categories=Office;Utility;Network;
|
||||
MimeType=x-scheme-handler/$scheme;
|
||||
StartupWMClass=Claude
|
||||
X-AppImage-Version=$VERSION
|
||||
X-AppImage-Name=Claude Desktop (AppImage)
|
||||
DESKTOP_EOF
|
||||
|
||||
echo "AppRun: Running xdg-mime default..."
|
||||
xdg-mime default "\$desktop_file_basename" "x-scheme-handler/\$scheme"
|
||||
|
||||
echo "AppRun: Running update-desktop-database..."
|
||||
update-desktop-database "\$user_apps_dir"
|
||||
|
||||
echo "AppRun: URI scheme registration attempted."
|
||||
}
|
||||
|
||||
# Run registration in the background to avoid delaying app start significantly
|
||||
# Pass the unique desktop file name and the determined AppImage path
|
||||
register_uri_scheme "$DESKTOP_FILE_BASENAME" "\$APPIMAGE_PATH" &
|
||||
|
||||
# --- End URI Scheme Handler Registration ---
|
||||
|
||||
|
||||
# Set up environment variables if needed (e.g., LD_LIBRARY_PATH)
|
||||
# export LD_LIBRARY_PATH="\$APPDIR/usr/lib:\$LD_LIBRARY_PATH"
|
||||
|
||||
# Detect if Wayland is likely running
|
||||
IS_WAYLAND=false
|
||||
if [ ! -z "\$WAYLAND_DISPLAY" ]; then
|
||||
IS_WAYLAND=true
|
||||
fi
|
||||
|
||||
# Path to the bundled Electron executable
|
||||
# Use the path relative to AppRun within the 'electron/dist' module directory
|
||||
ELECTRON_EXEC="\$APPDIR/usr/lib/node_modules/electron/dist/electron"
|
||||
APP_PATH="\$APPDIR/usr/lib/app.asar"
|
||||
|
||||
# Base command arguments array
|
||||
ELECTRON_ARGS=("\$APP_PATH")
|
||||
|
||||
# Add Wayland flags if Wayland is detected
|
||||
if [ "\$IS_WAYLAND" = true ]; then
|
||||
echo "AppRun: Wayland detected, adding flags."
|
||||
ELECTRON_ARGS+=("--enable-features=UseOzonePlatform,WaylandWindowDecorations" "--ozone-platform=wayland")
|
||||
fi
|
||||
|
||||
# Change to the application resources directory (where app.asar is)
|
||||
cd "\$APPDIR/usr/lib" || exit 1
|
||||
|
||||
# Execute Electron with app path, flags, and script arguments passed to AppRun
|
||||
echo "AppRun: Executing \$ELECTRON_EXEC \${ELECTRON_ARGS[@]} \$@"
|
||||
exec "\$ELECTRON_EXEC" "\${ELECTRON_ARGS[@]}" "\$@"
|
||||
EOF
|
||||
chmod +x "$APPDIR_PATH/AppRun"
|
||||
echo "✓ AppRun script created with URI scheme registration logic"
|
||||
|
||||
# --- Create Desktop Entry (Bundled inside AppDir) ---
|
||||
echo "📝 Creating bundled desktop entry..."
|
||||
# Use package name for icon (AppImage tools expect this)
|
||||
ICON_NAME=$PACKAGE_NAME
|
||||
# This is the desktop file *inside* the AppImage, used by tools like appimaged
|
||||
cat > "$APPDIR_PATH/$PACKAGE_NAME.desktop" << EOF
|
||||
[Desktop Entry]
|
||||
Name=Claude
|
||||
Exec=AppRun %u
|
||||
Icon=$ICON_NAME
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Categories=Office;Utility;Network;
|
||||
Comment=Claude Desktop for Linux
|
||||
MimeType=x-scheme-handler/claude;
|
||||
StartupWMClass=Claude
|
||||
X-AppImage-Version=$VERSION
|
||||
X-AppImage-Name=Claude Desktop
|
||||
EOF
|
||||
# Also place it in the standard location for tools like appimaged
|
||||
cp "$APPDIR_PATH/$PACKAGE_NAME.desktop" "$APPDIR_PATH/usr/share/applications/"
|
||||
echo "✓ Bundled desktop entry created"
|
||||
|
||||
# --- Copy Icons ---
|
||||
echo "🎨 Copying icons..."
|
||||
# Use the 256x256 icon as the main AppImage icon
|
||||
ICON_SOURCE_PATH="$WORK_DIR/claude_6_256x256x32.png"
|
||||
if [ -f "$ICON_SOURCE_PATH" ]; then
|
||||
# Standard location within AppDir
|
||||
cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/usr/share/icons/hicolor/256x256/apps/${PACKAGE_NAME}.png"
|
||||
# Top-level icon (used by appimagetool)
|
||||
cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/${ICON_NAME}.png"
|
||||
echo "✓ Icon copied"
|
||||
else
|
||||
echo "Warning: Missing 256x256 icon at $ICON_SOURCE_PATH. AppImage icon might be missing."
|
||||
fi
|
||||
|
||||
# --- Get appimagetool ---
|
||||
APPIMAGETOOL_PATH=""
|
||||
if command -v appimagetool &> /dev/null; then
|
||||
APPIMAGETOOL_PATH=$(command -v appimagetool)
|
||||
echo "✓ Found appimagetool in PATH: $APPIMAGETOOL_PATH"
|
||||
elif [ -f "$WORK_DIR/appimagetool-x86_64.AppImage" ]; then # Check for specific arch first
|
||||
APPIMAGETOOL_PATH="$WORK_DIR/appimagetool-x86_64.AppImage"
|
||||
echo "✓ Found downloaded x86_64 appimagetool: $APPIMAGETOOL_PATH"
|
||||
elif [ -f "$WORK_DIR/appimagetool-aarch64.AppImage" ]; then # Check for other arch
|
||||
APPIMAGETOOL_PATH="$WORK_DIR/appimagetool-aarch64.AppImage"
|
||||
echo "✓ Found downloaded aarch64 appimagetool: $APPIMAGETOOL_PATH"
|
||||
else
|
||||
echo "🛠️ Downloading appimagetool..."
|
||||
# Determine architecture for download URL
|
||||
TOOL_ARCH=""
|
||||
case "$ARCHITECTURE" in
|
||||
"amd64") TOOL_ARCH="x86_64" ;;
|
||||
"arm64") TOOL_ARCH="aarch64" ;;
|
||||
*) echo "❌ Unsupported architecture for appimagetool download: $ARCHITECTURE"; exit 1 ;;
|
||||
esac
|
||||
|
||||
APPIMAGETOOL_URL="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${TOOL_ARCH}.AppImage"
|
||||
APPIMAGETOOL_PATH="$WORK_DIR/appimagetool-${TOOL_ARCH}.AppImage"
|
||||
|
||||
if wget -q -O "$APPIMAGETOOL_PATH" "$APPIMAGETOOL_URL"; then
|
||||
chmod +x "$APPIMAGETOOL_PATH"
|
||||
echo "✓ Downloaded appimagetool to $APPIMAGETOOL_PATH"
|
||||
else
|
||||
echo "❌ Failed to download appimagetool from $APPIMAGETOOL_URL"
|
||||
rm -f "$APPIMAGETOOL_PATH" # Clean up partial download
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Build AppImage ---
|
||||
echo "📦 Building AppImage..."
|
||||
OUTPUT_FILENAME="${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage"
|
||||
OUTPUT_PATH="$WORK_DIR/$OUTPUT_FILENAME"
|
||||
|
||||
# Ensure chrome-sandbox has correct permissions within AppDir before building
|
||||
SANDBOX_PATH="$APPDIR_PATH/usr/lib/node_modules/electron/dist/chrome-sandbox"
|
||||
if [ -f "$SANDBOX_PATH" ]; then
|
||||
echo "Setting permissions for bundled chrome-sandbox..."
|
||||
# No need for chown root:root inside AppDir, just setuid
|
||||
chmod 4755 "$SANDBOX_PATH" || echo "Warning: Failed to chmod chrome-sandbox"
|
||||
else
|
||||
# Try alternative sandbox path sometimes found directly in electron dir
|
||||
SANDBOX_PATH_ALT="$APPDIR_PATH/usr/lib/node_modules/electron/chrome-sandbox"
|
||||
if [ -f "$SANDBOX_PATH_ALT" ]; then
|
||||
echo "Setting permissions for bundled chrome-sandbox (alternative path)..."
|
||||
chmod 4755 "$SANDBOX_PATH_ALT" || echo "Warning: Failed to chmod chrome-sandbox (alternative path)"
|
||||
SANDBOX_PATH="$SANDBOX_PATH_ALT" # Update SANDBOX_PATH if found here
|
||||
else
|
||||
echo "Warning: Bundled chrome-sandbox not found at standard or alternative paths."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Execute appimagetool
|
||||
# Export ARCH instead of using env
|
||||
export ARCH="$ARCHITECTURE"
|
||||
echo "Using ARCH=$ARCH" # Debug output
|
||||
if "$APPIMAGETOOL_PATH" "$APPDIR_PATH" "$OUTPUT_PATH"; then
|
||||
echo "✓ AppImage built successfully: $OUTPUT_PATH"
|
||||
else
|
||||
echo "❌ Failed to build AppImage using $APPIMAGETOOL_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "--- AppImage Build Finished ---"
|
||||
|
||||
exit 0
|
||||
@@ -153,10 +153,8 @@ echo "✓ Launcher script created"
|
||||
echo "📄 Creating control file..."
|
||||
# Determine dependencies based on whether electron was packaged
|
||||
DEPENDS="nodejs, npm, p7zip-full" # Base dependencies
|
||||
if [ ! -d "$INSTALL_DIR/lib/$PACKAGE_NAME/node_modules/electron" ]; then
|
||||
DEPENDS="$DEPENDS, electron" # Add electron if not packaged locally
|
||||
echo "Adding 'electron' to Depends list as it was not packaged locally."
|
||||
fi
|
||||
# Electron is now always packaged locally, so it's not listed as an external dependency.
|
||||
echo "Electron is packaged locally; not adding to external Depends list."
|
||||
|
||||
cat > "$PACKAGE_ROOT/DEBIAN/control" << EOF
|
||||
Package: $PACKAGE_NAME
|
||||
@@ -186,23 +184,10 @@ update-desktop-database /usr/share/applications &> /dev/null || true
|
||||
# Set correct permissions for chrome-sandbox if electron is installed globally or locally packaged
|
||||
echo "Setting chrome-sandbox permissions..."
|
||||
SANDBOX_PATH=""
|
||||
# Check for sandbox in locally packaged electron first
|
||||
# Electron is always packaged locally now, so only check the local path.
|
||||
LOCAL_SANDBOX_PATH="/usr/lib/$PACKAGE_NAME/node_modules/electron/dist/chrome-sandbox"
|
||||
if [ -f "\$LOCAL_SANDBOX_PATH" ]; then
|
||||
SANDBOX_PATH="\$LOCAL_SANDBOX_PATH"
|
||||
# If not found locally, try to find it in the path of the globally installed electron
|
||||
elif command -v electron >/dev/null 2>&1; then
|
||||
ELECTRON_PATH=\$(command -v electron)
|
||||
# Try to find sandbox relative to the electron binary path
|
||||
# Common locations: ../lib/node_modules/electron/dist/ or directly beside electron binary
|
||||
POTENTIAL_SANDBOX_1="\$(dirname "\$ELECTRON_PATH")/../lib/node_modules/electron/dist/chrome-sandbox"
|
||||
POTENTIAL_SANDBOX_2="\$(dirname "\$ELECTRON_PATH")/chrome-sandbox"
|
||||
|
||||
if [ -f "\$POTENTIAL_SANDBOX_1" ]; then
|
||||
SANDBOX_PATH="\$POTENTIAL_SANDBOX_1"
|
||||
elif [ -f "\$POTENTIAL_SANDBOX_2" ]; then
|
||||
SANDBOX_PATH="\$POTENTIAL_SANDBOX_2"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "\$SANDBOX_PATH" ] && [ -f "\$SANDBOX_PATH" ]; then
|
||||
@@ -211,7 +196,7 @@ if [ -n "\$SANDBOX_PATH" ] && [ -f "\$SANDBOX_PATH" ]; then
|
||||
chmod 4755 "\$SANDBOX_PATH" || echo "Warning: Failed to chmod chrome-sandbox"
|
||||
echo "Permissions set for \$SANDBOX_PATH"
|
||||
else
|
||||
echo "Warning: chrome-sandbox binary not found (checked local package and global path). Sandbox may not function correctly."
|
||||
echo "Warning: chrome-sandbox binary not found in local package at \$LOCAL_SANDBOX_PATH. Sandbox may not function correctly."
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user