270 lines
8.2 KiB
Bash
Executable File
270 lines
8.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# appimage-packager.sh - 简单的AppImage打包工具
|
|
|
|
set -e
|
|
|
|
# 彩色输出
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# 帮助信息
|
|
show_help() {
|
|
cat << EOF
|
|
${GREEN}AppImage 打包工具${NC}
|
|
${BLUE}════════════════════════════════${NC}
|
|
|
|
${YELLOW}用法:${NC}
|
|
$0 [选项] <可执行文件> [输出名称]
|
|
|
|
${YELLOW}选项:${NC}
|
|
-h, --help 显示帮助信息
|
|
-i, --icon <文件> 指定图标文件 (PNG格式)
|
|
-d, --data <目录> 包含数据文件目录
|
|
-n, --name <名称> 应用程序名称
|
|
-v, --version <版本> 设置版本号
|
|
-t, --terminal 在终端中运行
|
|
|
|
${YELLOW}示例:${NC}
|
|
$0 ./myapp # 基本打包
|
|
$0 -i icon.png ./myapp # 带图标
|
|
$0 -d data/ ./myapp MyApp # 包含数据文件
|
|
$0 -t ./cli-tool # 命令行工具
|
|
|
|
${BLUE}════════════════════════════════${NC}
|
|
EOF
|
|
}
|
|
|
|
# 创建默认图标
|
|
create_default_icon() {
|
|
local icon_path="$1"
|
|
mkdir -p "$(dirname "$icon_path")"
|
|
|
|
# 创建一个简单的1x1像素PNG图标
|
|
echo -ne '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\nIDATx\x9cc\xf8\x0f\x00\x00\x01\x00\x01\x05\x01\x00\x00\x00\x00IEND\xaeB`\x82' > "$icon_path"
|
|
}
|
|
|
|
# 创建AppRun脚本
|
|
create_apprun() {
|
|
local app_dir="$1"
|
|
local exec_name="$2"
|
|
local terminal="$3"
|
|
|
|
cat > "$app_dir/AppRun" << 'EOF'
|
|
#!/bin/bash
|
|
HERE="$(dirname "$(readlink -f "$0")")"
|
|
export PATH="$HERE/usr/bin:$PATH"
|
|
export LD_LIBRARY_PATH="$HERE/usr/lib:$LD_LIBRARY_PATH"
|
|
export XDG_DATA_DIRS="$HERE/usr/share:$XDG_DATA_DIRS"
|
|
|
|
exec "$HERE/usr/bin/EXEC_NAME" "$@"
|
|
EOF
|
|
|
|
# 替换可执行文件名
|
|
sed -i "s/EXEC_NAME/$exec_name/g" "$app_dir/AppRun"
|
|
chmod +x "$app_dir/AppRun"
|
|
}
|
|
|
|
# 收集动态库依赖
|
|
collect_dependencies() {
|
|
local executable="$1"
|
|
local lib_dir="$2"
|
|
|
|
echo -e "${YELLOW}收集动态库依赖...${NC}"
|
|
|
|
mkdir -p "$lib_dir"
|
|
local count=0
|
|
|
|
# 使用ldd获取依赖
|
|
ldd "$executable" 2>/dev/null | grep "=> /" | awk '{print $3}' | while read -r lib; do
|
|
if [ -f "$lib" ] && [ ! -f "$lib_dir/$(basename "$lib")" ]; then
|
|
cp -f "$lib" "$lib_dir/" 2>/dev/null && {
|
|
echo " ✓ $(basename "$lib")"
|
|
count=$((count + 1))
|
|
}
|
|
fi
|
|
done
|
|
|
|
echo -e "${GREEN}✓ 已收集 $count 个库${NC}"
|
|
}
|
|
|
|
# 主程序
|
|
main() {
|
|
# 默认参数
|
|
ICON_FILE=""
|
|
DATA_DIR=""
|
|
APP_NAME=""
|
|
APP_VERSION="1.0"
|
|
TERMINAL=false
|
|
|
|
# 解析参数
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
-i|--icon)
|
|
ICON_FILE="$2"
|
|
shift 2
|
|
;;
|
|
-d|--data)
|
|
DATA_DIR="$2"
|
|
shift 2
|
|
;;
|
|
-n|--name)
|
|
APP_NAME="$2"
|
|
shift 2
|
|
;;
|
|
-v|--version)
|
|
APP_VERSION="$2"
|
|
shift 2
|
|
;;
|
|
-t|--terminal)
|
|
TERMINAL=true
|
|
shift
|
|
;;
|
|
-*)
|
|
echo -e "${RED}错误: 未知选项 $1${NC}"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# 检查参数
|
|
if [[ $# -lt 1 ]]; then
|
|
show_help
|
|
exit 1
|
|
fi
|
|
|
|
EXECUTABLE="$1"
|
|
OUTPUT_NAME="${2:-$(basename "$EXECUTABLE" .AppImage)}"
|
|
|
|
# 检查可执行文件
|
|
if [[ ! -f "$EXECUTABLE" ]]; then
|
|
echo -e "${RED}错误: 文件不存在: $EXECUTABLE${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -x "$EXECUTABLE" ]]; then
|
|
echo -e "${YELLOW}添加执行权限...${NC}"
|
|
chmod +x "$EXECUTABLE"
|
|
fi
|
|
|
|
# 设置应用程序名称
|
|
if [[ -z "$APP_NAME" ]]; then
|
|
APP_NAME="$OUTPUT_NAME"
|
|
fi
|
|
|
|
echo -e "${BLUE}════════════════════════════════${NC}"
|
|
echo -e "${GREEN}AppImage 打包工具${NC}"
|
|
echo -e "${BLUE}════════════════════════════════${NC}"
|
|
echo "程序: $(basename "$EXECUTABLE")"
|
|
echo "输出: $OUTPUT_NAME.AppImage"
|
|
echo "名称: $APP_NAME"
|
|
echo "版本: $APP_VERSION"
|
|
echo ""
|
|
|
|
# 清理旧文件
|
|
rm -rf AppDir "${OUTPUT_NAME}.AppImage"
|
|
|
|
# 步骤1: 创建目录结构
|
|
echo -e "${YELLOW}[1/6] 创建目录结构...${NC}"
|
|
mkdir -p AppDir/usr/bin
|
|
mkdir -p AppDir/usr/lib
|
|
mkdir -p AppDir/usr/share/applications
|
|
mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps
|
|
|
|
# 步骤2: 复制可执行文件
|
|
echo -e "${YELLOW}[2/6] 复制可执行文件...${NC}"
|
|
EXEC_NAME=$(basename "$EXECUTABLE")
|
|
cp "$EXECUTABLE" "AppDir/usr/bin/$EXEC_NAME"
|
|
echo -e "${GREEN}✓ 已复制: $EXEC_NAME${NC}"
|
|
|
|
# 步骤3: 收集动态库
|
|
collect_dependencies "$EXECUTABLE" "AppDir/usr/lib"
|
|
|
|
# 步骤4: 处理数据文件
|
|
if [[ -n "$DATA_DIR" ]] && [[ -d "$DATA_DIR" ]]; then
|
|
echo -e "${YELLOW}[3/6] 复制数据文件...${NC}"
|
|
cp -r "$DATA_DIR"/* "AppDir/usr/share/$APP_NAME/" 2>/dev/null || true
|
|
echo -e "${GREEN}✓ 已复制数据文件${NC}"
|
|
fi
|
|
|
|
# 步骤5: 处理图标
|
|
echo -e "${YELLOW}[4/6] 设置图标...${NC}"
|
|
if [[ -n "$ICON_FILE" ]] && [[ -f "$ICON_FILE" ]]; then
|
|
cp "$ICON_FILE" "AppDir/usr/share/icons/hicolor/256x256/apps/$APP_NAME.png"
|
|
cp "$ICON_FILE" "AppDir/$APP_NAME.png"
|
|
echo -e "${GREEN}✓ 使用自定义图标${NC}"
|
|
else
|
|
create_default_icon "AppDir/usr/share/icons/hicolor/256x256/apps/$APP_NAME.png"
|
|
create_default_icon "AppDir/$APP_NAME.png"
|
|
echo -e "${YELLOW}⚠ 使用默认图标${NC}"
|
|
fi
|
|
cp "AppDir/$APP_NAME.png" "AppDir/.DirIcon"
|
|
|
|
# 步骤6: 创建桌面文件
|
|
echo -e "${YELLOW}[5/6] 创建桌面文件...${NC}"
|
|
TERMINAL_FLAG="$([ "$TERMINAL" = true ] && echo "true" || echo "false")"
|
|
cat > "AppDir/usr/share/applications/$APP_NAME.desktop" << EOF
|
|
[Desktop Entry]
|
|
Version=$APP_VERSION
|
|
Type=Application
|
|
Name=$APP_NAME
|
|
Comment=$APP_NAME application
|
|
Exec=$EXEC_NAME
|
|
Icon=$APP_NAME
|
|
Terminal=$TERMINAL_FLAG
|
|
Categories=Utility;
|
|
StartupNotify=false
|
|
EOF
|
|
ln -sf usr/share/applications/$APP_NAME.desktop "AppDir/"
|
|
|
|
# 步骤7: 创建AppRun
|
|
echo -e "${YELLOW}[6/6] 创建AppRun...${NC}"
|
|
create_apprun "AppDir" "$EXEC_NAME" "$TERMINAL"
|
|
|
|
# 步骤8: 打包AppImage
|
|
echo -e "\n${YELLOW}打包AppImage...${NC}"
|
|
|
|
if command -v appimagetool >/dev/null 2>&1; then
|
|
OUTPUT_FILE="${OUTPUT_NAME}.AppImage"
|
|
appimagetool --no-appstream AppDir "$OUTPUT_FILE" 2>&1 | grep -v "WARNING" | grep -v "gpg" || true
|
|
|
|
if [[ -f "$OUTPUT_FILE" ]]; then
|
|
chmod +x "$OUTPUT_FILE"
|
|
echo -e "\n${GREEN}════════════════════════════════${NC}"
|
|
echo -e "${GREEN}✅ 打包成功!${NC}"
|
|
echo -e "${GREEN}════════════════════════════════${NC}"
|
|
echo "📦 输出: $(realpath "$OUTPUT_FILE")"
|
|
echo "📏 大小: $(du -h "$OUTPUT_FILE" | cut -f1)"
|
|
echo ""
|
|
echo "🚀 运行: ./$OUTPUT_FILE"
|
|
|
|
# 清理
|
|
rm -rf AppDir
|
|
else
|
|
echo -e "${RED}❌ 打包失败${NC}"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo -e "${RED}错误: 未找到 appimagetool${NC}"
|
|
echo ""
|
|
echo "请下载 appimagetool:"
|
|
echo " wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
|
|
echo " chmod +x appimagetool-x86_64.AppImage"
|
|
echo " sudo mv appimagetool-x86_64.AppImage /usr/local/bin/appimagetool"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 运行主程序
|
|
main "$@"
|