Переработан скрипт с учетом устаревшей версии ar
This commit is contained in:
parent
98d0774bda
commit
5ee5418365
1 changed files with 240 additions and 125 deletions
|
|
@ -1,65 +1,118 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# title :appimage-builder.sh
|
# title :aib.sh
|
||||||
# description :Script for building AppImage
|
# description :Script for building AppImage
|
||||||
# author :Alexander Zhirov
|
# author :Alexander Zhirov
|
||||||
# date :20240522
|
# date :20251125
|
||||||
# version :0.2.0
|
# version :0.3.0
|
||||||
# usage :bash appimage-builder.sh --help
|
# usage :bash aib.sh --help
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
|
||||||
# Пакеты AppImageTool
|
set -euo pipefail
|
||||||
# https://github.com/AppImage/appimagetool/releases
|
|
||||||
# Среда выполнения
|
|
||||||
# https://github.com/AppImage/type2-runtime/releases
|
|
||||||
|
|
||||||
set -e
|
VERSION="0.3.0"
|
||||||
|
SCRIPT_NAME=${0##*/}
|
||||||
|
|
||||||
version="0.2.0"
|
show_help() {
|
||||||
|
cat <<EOF
|
||||||
|
${SCRIPT_NAME} — скрипт сборки AppImage приложений
|
||||||
|
|
||||||
# Определения по умолчанию
|
Использование:
|
||||||
# Приложение для сборки AppImage
|
${SCRIPT_NAME} [ОПЦИИ]... [СПИСОК ПАКЕТОВ ДЛЯ СБОРКИ]
|
||||||
appimage_tool=""
|
|
||||||
# Среда выполнения
|
|
||||||
appimage_runtime=""
|
|
||||||
# Output
|
|
||||||
appimage_output=""
|
|
||||||
# Директория с рецептами
|
|
||||||
appimage_input="$(dirname $(realpath ${0}))/apps"
|
|
||||||
# Директория с кэшем
|
|
||||||
appimage_cache=""
|
|
||||||
# Список приложений для сборки
|
|
||||||
appimage_apps=()
|
|
||||||
|
|
||||||
# Дополнительные необходимые утилиты
|
Опции:
|
||||||
rpm2cpio_tool=$(which rpm2cpio 2>/dev/null)
|
-t, --appimage-tool Инструмент сборки AppImage
|
||||||
cpio_tool=$(which cpio 2>/dev/null)
|
-r, --appimage-runtime Инструмент времени выполнения
|
||||||
|
-i, --input-path Директория с пакетами исходных файлов (по умолчанию: ./apps)
|
||||||
|
-o, --output-path Директория сохранения собранных AppImage (по умолчанию: \$HOME/AppImages)
|
||||||
|
-c, --cache-path Директория кеша для пакетов sources (по умолчанию: временная через mktemp -d)
|
||||||
|
-l, --log-path Директория для сохранения журнала сборки (по умолчанию: как output-path)
|
||||||
|
|
||||||
if [ ! -x "${rpm2cpio_tool}" ]; then
|
-h, --help Показать эту справку и выйти
|
||||||
echo "Отсутствует утилита rpm2cpio"
|
-v, --version Показать версию скрипта и выйти
|
||||||
exit 1
|
EOF
|
||||||
fi
|
}
|
||||||
|
|
||||||
if [ ! -x "${cpio_tool}" ]; then
|
show_version() {
|
||||||
echo "Отсутствует утилита cpio"
|
echo "${SCRIPT_NAME} ${VERSION}"
|
||||||
exit 1
|
}
|
||||||
fi
|
|
||||||
|
check_requirements() {
|
||||||
|
local appimage_tool="$1"
|
||||||
|
local appimage_runtime="$2"
|
||||||
|
|
||||||
|
local -a missing=()
|
||||||
|
local cmd
|
||||||
|
|
||||||
|
# Базовые утилиты
|
||||||
|
for cmd in fusermount ar rpm2cpio cpio wget tar patch; do
|
||||||
|
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||||
|
missing+=("$cmd")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# appimagetool-x86_64.AppImage
|
||||||
|
if [[ -z "$appimage_tool" || ! -x "$appimage_tool" ]]; then
|
||||||
|
# тут проверяем именно логическое наличие утилиты,
|
||||||
|
# имя в сообщении — как пользователь ожидает её видеть
|
||||||
|
missing+=("appimagetool-x86_64.AppImage")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# runtime-x86_64
|
||||||
|
if [[ -z "$appimage_runtime" || ! -x "$appimage_runtime" ]]; then
|
||||||
|
missing+=("runtime-x86_64")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ((${#missing[@]} > 0)); then
|
||||||
|
echo "Ошибка: отсутствуют необходимые утилиты:" >&2
|
||||||
|
printf ' - %s\n' "${missing[@]}" >&2
|
||||||
|
echo "Установите их и повторите попытку." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
extrpm() {
|
extrpm() {
|
||||||
local rpm="${1}"
|
local rpm="${1}"
|
||||||
local destination_path="${2}"
|
local destination_path="${2}"
|
||||||
|
|
||||||
${rpm2cpio_tool} ${rpm} | ${cpio_tool} -idmvD ${destination_path}
|
rpm2cpio ${rpm} | cpio -idmvD ${destination_path}
|
||||||
|
}
|
||||||
|
|
||||||
|
extdeb() {
|
||||||
|
local deb="$1"
|
||||||
|
local tar_name="$2"
|
||||||
|
local dest_dir="$3"
|
||||||
|
|
||||||
|
local version
|
||||||
|
version=$(ar --version | head -n1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -n1)
|
||||||
|
|
||||||
|
IFS='.' read -r major minor <<< "$version"
|
||||||
|
|
||||||
|
if (( major > 2 )) || (( major == 2 && minor >= 39 )); then
|
||||||
|
ar xv "$deb" "$tar_name" --output "$dest_dir"
|
||||||
|
else
|
||||||
|
local tmpdir
|
||||||
|
tmpdir=$(mktemp -d 2>/dev/null)
|
||||||
|
(cd "$tmpdir" && ar x "$deb")
|
||||||
|
cp "$tmpdir/$tar_name" "$dest_dir/"
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
build_appimage() {
|
build_appimage() {
|
||||||
local pkg="${1}"
|
local appimage_tool="${1}"
|
||||||
|
local appimage_runtime="${2}"
|
||||||
|
local input_path="${3}"
|
||||||
|
local output_path="${4}"
|
||||||
|
local cache_path="${5}"
|
||||||
|
local pkg="${6}"
|
||||||
|
|
||||||
local name=$(basename ${pkg})
|
local name=$(basename ${pkg})
|
||||||
local build="${pkg}/build.sh"
|
local build="${pkg}/build.sh"
|
||||||
local sources="${pkg}/sources"
|
local sources="${pkg}/sources"
|
||||||
local files="${pkg}/files"
|
local files="${pkg}/files"
|
||||||
local cache="${appimage_cache}/${name}"
|
local cache="${cache_path}/${name}"
|
||||||
|
|
||||||
# Временные директории для сборки
|
# Временные директории для сборки
|
||||||
local tmp="/tmp/appimage_${name}_$(date "+%Y%m%d%H%M%S")"
|
local tmp="/tmp/appimage_${name}_$(date "+%Y%m%d%H%M%S")"
|
||||||
local src="${tmp}/src"
|
local src="${tmp}/src"
|
||||||
local app="${tmp}/app"
|
local app="${tmp}/app"
|
||||||
|
|
@ -103,7 +156,7 @@ build_appimage() {
|
||||||
for deb in $(find ${cache} -name "*.deb"); do
|
for deb in $(find ${cache} -name "*.deb"); do
|
||||||
local tar_name=$(ar t ${deb} | grep data)
|
local tar_name=$(ar t ${deb} | grep data)
|
||||||
local tar_archive="${src}/${tar_name}"
|
local tar_archive="${src}/${tar_name}"
|
||||||
ar xv ${deb} ${tar_name} --output ${src}
|
extdeb ${deb} ${tar_name} ${src}
|
||||||
tar xvf ${tar_archive} -C ${app}
|
tar xvf ${tar_archive} -C ${app}
|
||||||
rm -v ${tar_archive}
|
rm -v ${tar_archive}
|
||||||
done
|
done
|
||||||
|
|
@ -116,144 +169,204 @@ build_appimage() {
|
||||||
export current_path=$(dirname ${build})
|
export current_path=$(dirname ${build})
|
||||||
export app_path=${app}
|
export app_path=${app}
|
||||||
${build}
|
${build}
|
||||||
unset ${current_path}
|
unset current_path
|
||||||
unset ${app_path}
|
unset app_path
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local name_appimage=$(grep "Name" ${files}/*.desktop | sed 's/Name=//' | tr ' ' '_')-x86_64.AppImage
|
local name_appimage=$(grep 'Name' ${files}/*.desktop | sed 's/Name=//' | tr ' ' '_')-x86_64.AppImage
|
||||||
|
|
||||||
${appimage_tool} -v --runtime-file ${appimage_runtime} ${app} ${appimage_output}/${name_appimage}
|
${appimage_tool} -v --runtime-file ${appimage_runtime} ${app} ${output_path}/${name_appimage}
|
||||||
|
|
||||||
rm -rvf ${tmp}
|
rm -rvf ${tmp}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
help_scritp() {
|
|
||||||
echo -e "\n" \
|
|
||||||
"Использование: $(basename ${0}) [ОПЦИИ]... [СПИСОК ПАКЕТОВ ДЛЯ СБОРКИ]\n" \
|
|
||||||
"Основные опции:\n" \
|
|
||||||
"\t-t\t--appimage-tool\t\tИнструмент сборки AppImage\n" \
|
|
||||||
"\t-r\t--appimage-runtime\tИнструмент времени выполнения\n" \
|
|
||||||
"\t-i\t--input-path\t\tДиректория с пакетами исходных файлов\n" \
|
|
||||||
"\t-o\t--output-path\t\tДиректория сохранения собранных AppImage\n" \
|
|
||||||
"\t-c\t--cache-path\t\tДиректория кеша для пакетов sources\n" \
|
|
||||||
"\t-l\t--log-path\t\tДиректория для сохранения журнала сборки\n" \
|
|
||||||
"Дополнительно:\n" \
|
|
||||||
"\t-h\t--help\t\t\tПоказать справку\n" \
|
|
||||||
"\t-v\t--version\t\tВерсия скрипта\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
local appimage_tool=""
|
||||||
|
local appimage_runtime=""
|
||||||
|
local input_path=""
|
||||||
|
local output_path=""
|
||||||
|
local cache_path=""
|
||||||
|
local log_path=""
|
||||||
|
|
||||||
|
# флаги: директория была явно передана
|
||||||
|
local output_specified=false
|
||||||
|
local cache_specified=false
|
||||||
|
local log_specified=false
|
||||||
|
|
||||||
|
# массив с именами пакетов для сборки
|
||||||
|
local -a appimage_apps=()
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
key="${1}"
|
case "$1" in
|
||||||
value="${2}"
|
|
||||||
case "${key}" in
|
|
||||||
-t|--appimage-tool)
|
-t|--appimage-tool)
|
||||||
appimage_tool="${value}"
|
if [[ $# -lt 2 ]]; then
|
||||||
shift
|
echo "Ошибка: для опции $1 требуется аргумент" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
appimage_tool=$2
|
||||||
|
shift 2
|
||||||
;;
|
;;
|
||||||
-r|--appimage-runtime)
|
-r|--appimage-runtime)
|
||||||
appimage_runtime="${value}"
|
if [[ $# -lt 2 ]]; then
|
||||||
shift
|
echo "Ошибка: для опции $1 требуется аргумент" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
appimage_runtime=$2
|
||||||
|
shift 2
|
||||||
;;
|
;;
|
||||||
-i|--input-path)
|
-i|--input-path)
|
||||||
appimage_input="${value}"
|
if [[ $# -lt 2 ]]; then
|
||||||
shift
|
echo "Ошибка: для опции $1 требуется аргумент" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
input_path=$2
|
||||||
|
shift 2
|
||||||
;;
|
;;
|
||||||
-o|--output-path)
|
-o|--output-path)
|
||||||
appimage_output="${value}"
|
if [[ $# -lt 2 ]]; then
|
||||||
shift
|
echo "Ошибка: для опции $1 требуется аргумент" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
output_path=$2
|
||||||
|
output_specified=true
|
||||||
|
shift 2
|
||||||
;;
|
;;
|
||||||
-c|--cache-path)
|
-c|--cache-path)
|
||||||
appimage_cache="${value}"
|
if [[ $# -lt 2 ]]; then
|
||||||
shift
|
echo "Ошибка: для опции $1 требуется аргумент" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cache_path=$2
|
||||||
|
cache_specified=true
|
||||||
|
shift 2
|
||||||
;;
|
;;
|
||||||
-l|--log-path)
|
-l|--log-path)
|
||||||
appimage_log="${value}"
|
if [[ $# -lt 2 ]]; then
|
||||||
shift
|
echo "Ошибка: для опции $1 требуется аргумент" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_path=$2
|
||||||
|
log_specified=true
|
||||||
|
shift 2
|
||||||
;;
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
help_scritp
|
show_help
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
-v|--version)
|
-v|--version)
|
||||||
echo "Версия скрипта: ${version}"
|
show_version
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
appimage_apps+=("$1")
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
echo "Неизвестная опция: $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
appimage_apps+=("${key}")
|
appimage_apps+=("$1")
|
||||||
|
shift
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z "${appimage_tool}" ] ; then
|
# Значения по умолчанию для тулов
|
||||||
appimage_tool=$(which appimagetool-x86_64.AppImage 2>/dev/null)
|
if [[ -z "$appimage_tool" ]]; then
|
||||||
|
appimage_tool=$(command -v appimagetool-x86_64.AppImage 2>/dev/null || true)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "${appimage_tool}" ]; then
|
if [[ -z "$appimage_runtime" ]]; then
|
||||||
echo "Отсутствует инструмент сборки: https://github.com/AppImage/appimagetool"
|
appimage_runtime=$(command -v runtime-x86_64 2>/dev/null || true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Значения по умолчанию для директорий
|
||||||
|
if [[ -z "$input_path" ]]; then
|
||||||
|
input_path="${PWD}/apps"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$output_path" ]]; then
|
||||||
|
output_path="${HOME}/AppImages"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# cache: если не указали — mktemp -d
|
||||||
|
if ! $cache_specified; then
|
||||||
|
cache_path=$(mktemp -d /tmp/appimage_cache.XXXXXX)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# log: если не указали — как output_path
|
||||||
|
if [[ -z "$log_path" ]]; then
|
||||||
|
log_path="$output_path"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверяем наличие утилит уже с подставленными дефолтами
|
||||||
|
check_requirements "$appimage_tool" "$appimage_runtime"
|
||||||
|
|
||||||
|
# Проверяем, что есть хотя бы один пакет
|
||||||
|
if ((${#appimage_apps[@]} == 0)); then
|
||||||
|
echo "Ошибка: не указан список пакетов для сборки." >&2
|
||||||
|
echo "См. справку: ${SCRIPT_NAME} --help" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -x "${appimage_tool}" ]; then
|
# INPUT: всегда должен существовать, не создаём
|
||||||
echo "Инструмент сборки $(basename ${appimage_tool}) должен быть исполняемым"
|
if [[ ! -d "$input_path" ]]; then
|
||||||
|
echo "Ошибка: директория input-path не существует: $input_path" >&2
|
||||||
|
echo "Создайте её или укажите путь явно с помощью -i|--input-path." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${appimage_runtime}" ] ; then
|
# OUTPUT:
|
||||||
appimage_runtime=$(which runtime-x86_64 2>/dev/null)
|
if $output_specified; then
|
||||||
|
if [[ ! -d "$output_path" ]]; then
|
||||||
|
echo "Ошибка: указанная директория output-path не существует: $output_path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mkdir -p "$output_path"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "${appimage_runtime}" ]; then
|
# CACHE:
|
||||||
echo "Отсутствует инструмент времени выполнения: https://github.com/AppImage/type2-runtime"
|
if $cache_specified; then
|
||||||
exit 1
|
if [[ ! -d "$cache_path" ]]; then
|
||||||
|
echo "Ошибка: указанная директория cache-path не существует: $cache_path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -x "${appimage_runtime}" ]; then
|
# LOG:
|
||||||
echo "Инструмент времени выполнения $(basename ${appimage_runtime}) должен быть исполняемым"
|
if $log_specified; then
|
||||||
exit 1
|
if [[ ! -d "$log_path" ]]; then
|
||||||
fi
|
echo "Ошибка: указанная директория log-path не существует: $log_path" >&2
|
||||||
|
exit 1
|
||||||
if [ ! -d "${appimage_input}" ]; then
|
fi
|
||||||
echo "Не установлена директория исхоных файлов для сборки AppImage"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$(find ${appimage_input} -maxdepth 1 -type d | wc -l)" -eq 1 ]; then
|
|
||||||
echo "Директория не содержит исхоных файлов для сборки AppImage: ${appimage_input}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "${appimage_output}" ]; then
|
|
||||||
appimage_output="${HOME}/AppImages"
|
|
||||||
mkdir -p "${appimage_output}"
|
|
||||||
echo "Не установлена директория для сохранения AppImage. Будет использована директория по умолчанию: ${appimage_output}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "${appimage_cache}" ]; then
|
|
||||||
appimage_cache="/tmp/appimage_cache"
|
|
||||||
mkdir -p "${appimage_cache}"
|
|
||||||
echo "Не определена директория для кеша. Будет использована директория по умолчанию: ${appimage_cache}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "${appimage_log}" ]; then
|
|
||||||
appimage_log="${appimage_output}"
|
|
||||||
echo "Не определена директория для журнала. Будет использована директория по умолчанию: ${appimage_output}"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Инструмент сборки: ${appimage_tool}"
|
echo "Инструмент сборки: ${appimage_tool}"
|
||||||
echo "Инструмент времени выполнения: ${appimage_runtime}"
|
echo "Инструмент времени выполнения: ${appimage_runtime}"
|
||||||
echo "Директория исходных файлов: ${appimage_input}"
|
echo "Директория исходных файлов: ${input_path}"
|
||||||
echo "Директория для сохранения AppImage: ${appimage_output}"
|
echo "Директория для сохранения AppImage: ${output_path}"
|
||||||
echo "Директория для кеша: ${appimage_cache}"
|
echo "Директория для кеша: ${cache_path}"
|
||||||
echo "Список собираемых пакетов: ${appimage_apps[@]}"
|
echo "Директория для журнала: ${log_path}"
|
||||||
|
echo "Список собираемых пакетов: ${appimage_apps[*]}"
|
||||||
|
|
||||||
local pkgs=$(printf "%s\n" "${appimage_apps[@]}" | xargs -I {} find ${appimage_input} -name {} -mindepth 1 -maxdepth 1 -type d)
|
local pkgs=$(printf "%s\n" "${appimage_apps[*]}" | xargs -I {} find ${input_path} -name {} -mindepth 1 -maxdepth 1 -type d)
|
||||||
|
|
||||||
for pkg in ${pkgs}; do
|
for pkg in ${pkgs}; do
|
||||||
if build_appimage ${pkg} > "${appimage_log}/appimage_build.log" 2>&1 ; then
|
echo $pkg
|
||||||
|
if build_appimage \
|
||||||
|
${appimage_tool} \
|
||||||
|
${appimage_runtime} \
|
||||||
|
${input_path} \
|
||||||
|
${output_path} \
|
||||||
|
${cache_path} \
|
||||||
|
${pkg} &>> "${log_path}/appimage_build.log"; then
|
||||||
echo "AppImage $(basename ${pkg}) был собран"
|
echo "AppImage $(basename ${pkg}) был собран"
|
||||||
else
|
else
|
||||||
echo "AppImage $(basename ${pkg}) не был собран"
|
echo "AppImage $(basename ${pkg}) не был собран"
|
||||||
|
|
@ -261,4 +374,6 @@ main() {
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
main "${@}"
|
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
||||||
|
main "$@"
|
||||||
|
fi
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue