From 1c4fb0b822e428cadc3312d62be98b12cc96e268 Mon Sep 17 00:00:00 2001 From: iVAN <88724353+ivan-hc@users.noreply.github.com> Date: Sun, 12 Jan 2025 08:17:32 +0100 Subject: [PATCH] Archimage 4.2 (#32) * Add new template on steroids, named "NEW-junest.sh" - unuque flexible AppRun that allows to run the AppImage using Namespaces via Bwrap and switches to PROOT in case the system has Namespaces restrictions (see Ubuntu) - always made an updatable AppImage - multilib in now optional, you can enable it via CLI - if the app is on AUR, the cli will suggest to enable ChaoticAUR - the standard configuration only enables network and audio keywords, and in most case it is enough for the app - extract dependendes of dependences and dependences of the latter - include better support to open external browsers (tested with Firefox) - add an exclude list not to include developer packages (gcc, make...) - include optdepend as dependences - download and extract optdepend packages before the others, not to include their dependencies - move pk and p11 internet keywords from the CLI to the script - changed the question for network support - add message of each process when detecting libraries - improve speed of libraries detection for dependencies - add "extract_count" variable to set dependencies extraction level (default 1) - include more coreutils binaries - use worldwide mirror for Arch Linux in case the script is running on github actions - more elegant way to remove bloatwares - set extraction level on dependencies --- NEW-junest.sh | 621 ++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 195 ++++++++++++++-- archimage-cli | 138 +++++------ 3 files changed, 859 insertions(+), 95 deletions(-) create mode 100644 NEW-junest.sh diff --git a/NEW-junest.sh b/NEW-junest.sh new file mode 100644 index 0000000..c3bae5a --- /dev/null +++ b/NEW-junest.sh @@ -0,0 +1,621 @@ +#!/usr/bin/env bash + +APP=SAMPLE +BIN="$APP" #CHANGE THIS IF THE NAME OF THE BINARY IS DIFFERENT FROM "$APP" (for example, the binary of "obs-studio" is "obs") +DEPENDENCES="" #SYNTAX: "APP1 APP2 APP3 APP4...", LEAVE BLANK IF NO OTHER DEPENDENCES ARE NEEDED +#BASICSTUFF="binutils debugedit gzip" +#COMPILERS="base-devel" + +############################################################################# +# KEYWORDS TO FIND AND SAVE WHEN COMPILING THE APPIMAGE +############################################################################# + +BINSAVED="SAVEBINSPLEASE" +SHARESAVED="SAVESHAREPLEASE" +#lib_audio_keywords="alsa jack pipewire pulse" +#lib_browser_launcher="gio-launch-desktop libdl.so libpthread.so librt.so libasound.so libX11-xcb.so libxapp-gtk3-module.so libgtk-3.so.0 pk p11" +LIBSAVED="SAVELIBSPLEASE $lib_audio_keywords $lib_browser_launcher" + +############################################################################# +# SETUP THE ENVIRONMENT +############################################################################# + +# Download appimagetool +if [ ! -f ./appimagetool ]; then + echo "-----------------------------------------------------------------------------" + echo "◆ Downloading \"appimagetool\" from https://github.com/AppImage/appimagetool" + echo "-----------------------------------------------------------------------------" + curl -#Lo appimagetool https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage && chmod a+x appimagetool +fi + +# Create and enter the AppDir +mkdir -p "$APP".AppDir && cd "$APP".AppDir || exit 1 + +# Set the AppDir as a temporary $HOME directory +HOME="$(dirname "$(readlink -f "$0")")" + +############################################################################# +# DOWNLOAD, INSTALL AND CONFIGURE JUNEST +############################################################################# + +_enable_multilib() { + printf "\n[multilib]\nInclude = /etc/pacman.d/mirrorlist" >> ./.junest/etc/pacman.conf +} + +_enable_chaoticaur() { + # This function is ment to be used during the installation of JuNest, see "_pacman_patches" + ./.local/share/junest/bin/junest -- sudo pacman-key --recv-key 3056513887B78AEB --keyserver keyserver.ubuntu.com + ./.local/share/junest/bin/junest -- sudo pacman-key --lsign-key 3056513887B78AEB + ./.local/share/junest/bin/junest -- sudo pacman-key --populate chaotic + ./.local/share/junest/bin/junest -- sudo pacman --noconfirm -U 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst' 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst' + printf "\n[chaotic-aur]\nInclude = /etc/pacman.d/chaotic-mirrorlist" >> ./.junest/etc/pacman.conf +} + +_custom_mirrorlist() { + COUNTRY=$(curl -i ipinfo.io 2>/dev/null | grep country | cut -c 15- | cut -c -2) + if [ -n "$GITHUB_REPOSITORY_OWNER" ] || ! curl --output /dev/null --silent --head --fail "https://archlinux.org/mirrorlist/?country=$COUNTRY" 1>/dev/null; then + curl -Ls https://archlinux.org/mirrorlist/all | awk NR==2 RS= | sed 's/#Server/Server/g' > ./.junest/etc/pacman.d/mirrorlist + else + curl -Ls "https://archlinux.org/mirrorlist/?country=$COUNTRY" | sed 's/#Server/Server/g' > ./.junest/etc/pacman.d/mirrorlist + fi +} + +_bypass_signature_check_level() { + sed -i 's/#SigLevel/SigLevel/g; s/Required DatabaseOptional/Never/g' ./.junest/etc/pacman.conf +} + +_install_junest() { + echo "-----------------------------------------------------------------------------" + echo "◆ Clone JuNest from https://github.com/fsquillace/junest" + echo "-----------------------------------------------------------------------------" + git clone https://github.com/fsquillace/junest.git ./.local/share/junest + echo "-----------------------------------------------------------------------------" + echo "◆ Downloading JuNest archive from https://github.com/ivan-hc/junest" + echo "-----------------------------------------------------------------------------" + curl -#Lo junest-x86_64.tar.gz https://github.com/ivan-hc/junest/releases/download/continuous/junest-x86_64.tar.gz + ./.local/share/junest/bin/junest setup -i junest-x86_64.tar.gz + rm -f junest-x86_64.tar.gz + echo " Apply patches to PacMan..." + #_enable_multilib + #_enable_chaoticaur + _custom_mirrorlist + _bypass_signature_check_level + + # Update arch linux in junest + ./.local/share/junest/bin/junest -- sudo pacman -Syy + ./.local/share/junest/bin/junest -- sudo pacman --noconfirm -Syu +} + +_restore_junest() { + cd .. + echo "-----------------------------------------------------------------------------" + echo " RESTORATION OF BACKUPS IN PROGRESS..." + echo "-----------------------------------------------------------------------------" + echo "" + rsync -av ./junest-backups/ ./"$APP".AppDir/.junest/ | echo "◆ Restore the content of the Arch Linux container, please wait" + [ -d ./"$APP".AppDir/.cache ] && rsync -av ./stock-cache/ ./"$APP".AppDir/.cache/ | echo "◆ Restore the content of JuNest's ~/.cache directory" + rsync -av ./stock-local/ ./"$APP".AppDir/.local/ | echo "◆ Restore the content of JuNest's ~/.local directory" + echo "" + echo "-----------------------------------------------------------------------------" + echo "" + cd ./"$APP".AppDir || exit 1 +} + +if ! test -d "$HOME/.local/share/junest"; then + _install_junest +else + _restore_junest +fi + +############################################################################# +# INSTALL PROGRAMS USING YAY +############################################################################# + +./.local/share/junest/bin/junest -- yay -Syy +#./.local/share/junest/bin/junest -- gpg --keyserver keyserver.ubuntu.com --recv-key C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF # UNCOMMENT IF YOU USE THE AUR +if [ -n "$BASICSTUFF" ]; then + ./.local/share/junest/bin/junest -- yay --noconfirm -S "$BASICSTUFF" +fi +if [ -n "$COMPILERS" ]; then + ./.local/share/junest/bin/junest -- yay --noconfirm -S "$COMPILERS" +fi +if [ -n "$DEPENDENCES" ]; then + ./.local/share/junest/bin/junest -- yay --noconfirm -S "$DEPENDENCES" +fi +if [ -n "$APP" ]; then + ./.local/share/junest/bin/junest -- yay --noconfirm -S alsa-lib gtk3 xapp + ./.local/share/junest/bin/junest -- yay --noconfirm -S "$APP" + ./.local/share/junest/bin/junest -- glib-compile-schemas /usr/share/glib-2.0/schemas/ +else + echo "No app found, exiting"; exit 1 +fi + +# Backup JuNest for furter tests +cd .. +echo "" +echo "-----------------------------------------------------------------------------" +echo " BACKUP OF JUNEST FOR FURTHER APPIMAGE BUILDING ATTEMPTS" +echo "-----------------------------------------------------------------------------" +mkdir -p ./junest-backups ./stock-cache ./stock-local +echo "" +rsync -av --ignore-existing ./"$APP".AppDir/.junest/ ./junest-backups/ | echo "◆ Backup the content of the Arch Linux container, please wait" +[ -d ./"$APP".AppDir/.cache ] && rsync -av --ignore-existing ./"$APP".AppDir/.cache/ ./stock-cache/ | echo "◆ Backup the content of JuNest's ~/.cache directory" +rsync -av --ignore-existing ./"$APP".AppDir/.local/ ./stock-local/ | echo "◆ Backup the content of JuNest's ~/.local directory" +echo "" +echo "-----------------------------------------------------------------------------" +cd ./"$APP".AppDir || exit 1 + +############################################################################# +# LAUNCHER AND ICON / MADE JUNEST A PORTABLE CONTAINER +############################################################################# + +# Set locale +rm -f ./.junest/etc/locale.conf +sed -i 's/LANG=${LANG:-C}/LANG=$LANG/g' ./.junest/etc/profile.d/locale.sh + +# Add launcher and icon +rm -f ./*.desktop +LAUNCHER=$(grep -iRl "$BIN" ./.junest/usr/share/applications/* | grep ".desktop" | head -1) +cp -r "$LAUNCHER" ./ +ICON=$(cat "$LAUNCHER" | grep "Icon=" | cut -c 6-) +cp -r ./.junest/usr/share/icons/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/22x22/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/24x24/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/32x32/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/48x48/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/64x64/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/128x128/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/192x192/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/256x256/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/512x512/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/icons/hicolor/scalable/apps/*"$ICON"* ./ 2>/dev/null +cp -r ./.junest/usr/share/pixmaps/*"$ICON"* ./ 2>/dev/null + +# Test if the desktop file and the icon are in the root of the future appimage (./*appdir/*) +if test -f ./*.desktop; then + echo "◆ The .desktop file is available in $APP.AppDir/" +elif test -f ./.junest/usr/bin/"$BIN"; then + echo "" + echo "◆ No .desktop file available for $APP, creating a new one..." + echo "" + cat <<-HEREDOC >> ./"$APP".desktop + [Desktop Entry] + Version=1.0 + Type=Application + Name=$(echo "$APP" | tr '[:lower:]' '[:upper:]') + Comment= + Exec=$BIN + Icon=tux + Categories=Utility; + Terminal=true + StartupNotify=true + HEREDOC + curl -Lo tux.png https://raw.githubusercontent.com/Portable-Linux-Apps/Portable-Linux-Apps.github.io/main/favicon.ico 2>/dev/null +else + echo "No binary in path... aborting all the processes." + exit 0 +fi + +# Made JuNest a portable app and remove "read-only file system" errors +sed -i 's#${JUNEST_HOME}/usr/bin/junest_wrapper#${HOME}/.cache/junest_wrapper.old#g' ./.local/share/junest/lib/core/wrappers.sh +sed -i 's/rm -f "${JUNEST_HOME}${bin_path}_wrappers/#rm -f "${JUNEST_HOME}${bin_path}_wrappers/g' ./.local/share/junest/lib/core/wrappers.sh +sed -i 's/ln/#ln/g' ./.local/share/junest/lib/core/wrappers.sh +sed -i 's/rm -f "$file"/test -f "$file"/g' ./.local/share/junest/lib/core/wrappers.sh +sed -i 's#--bind "$HOME" "$HOME"#--bind-try /home /home --bind-try /run/user /run/user#g' .local/share/junest/lib/core/namespace.sh + +############################################################################# +# APPRUN +############################################################################# + +rm -f ./AppRun +cat <<-'HEREDOC' >> ./AppRun +#!/bin/sh +HERE="$(dirname "$(readlink -f "$0")")" +export UNION_PRELOAD="$HERE" +export JUNEST_HOME="$HERE"/.junest + +if command -v unshare >/dev/null 2>&1 && ! unshare --user -p /bin/true >/dev/null 2>&1; then + PROOT_ON=1 + export PATH="$HERE"/.local/share/junest/bin/:"$PATH" + mkdir -p "$HOME"/.cache +else + export PATH="$PATH":"$HERE"/.local/share/junest/bin +fi + +[ -z "$NVIDIA_ON" ] && NVIDIA_ON=0 +if [ "$NVIDIA_ON" = 1 ]; then + DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}" + CONTY_DIR="${DATADIR}/Conty/overlayfs_shared" + [ -f /sys/module/nvidia/version ] && nvidia_driver_version="$(cat /sys/module/nvidia/version)" + if [ -n "$nvidia_driver_version" ]; then + mkdir -p "${CONTY_DIR}"/nvidia "${CONTY_DIR}"/up/usr/lib "${CONTY_DIR}"/up/usr/share + nvidia_data_dirs="egl glvnd nvidia vulkan" + for d in $nvidia_data_dirs; do [ ! -d "${CONTY_DIR}"/up/usr/share/"$d" ] && ln -s /usr/share/"$d" "${CONTY_DIR}"/up/usr/share/ 2>/dev/null; done + [ ! -f "${CONTY_DIR}"/nvidia/current-nvidia-version ] && echo "${nvidia_driver_version}" > "${CONTY_DIR}"/nvidia/current-nvidia-version + [ -f "${CONTY_DIR}"/nvidia/current-nvidia-version ] && nvidia_driver_conty=$(cat "${CONTY_DIR}"/nvidia/current-nvidia-version) + if [ "${nvidia_driver_version}" != "${nvidia_driver_conty}" ]; then + rm -f "${CONTY_DIR}"/up/usr/lib/*; echo "${nvidia_driver_version}" > "${CONTY_DIR}"/nvidia/current-nvidia-version + fi + /sbin/ldconfig -p > "${CONTY_DIR}"/nvidia/host_libs + grep -i "nvidia\|libcuda" "${CONTY_DIR}"/nvidia/host_libs | cut -d ">" -f 2 > "${CONTY_DIR}"/nvidia/host_nvidia_libs + libnv_paths=$(grep "libnv" "${CONTY_DIR}"/nvidia/host_libs | cut -d ">" -f 2) + for f in $libnv_paths; do strings "${f}" | grep -qi -m 1 "nvidia" && echo "${f}" >> "${CONTY_DIR}"/nvidia/host_nvidia_libs; done + nvidia_libs=$(cat "${CONTY_DIR}"/nvidia/host_nvidia_libs) + for n in $nvidia_libs; do libname=$(echo "$n" | sed 's:.*/::') && [ ! -f "${CONTY_DIR}"/up/usr/lib/"$libname" ] && cp "$n" "${CONTY_DIR}"/up/usr/lib/; done + libvdpau_nvidia="${CONTY_DIR}/up/usr/lib/libvdpau_nvidia.so" + if ! test -f "${libvdpau_nvidia}*"; then cp "$(find /usr/lib -type f -name 'libvdpau_nvidia.so*' -print -quit 2>/dev/null | head -1)" "${CONTY_DIR}"/up/usr/lib/; fi + [ -f "${libvdpau_nvidia}"."${nvidia_driver_version}" ] && [ ! -f "${libvdpau_nvidia}" ] && ln -s "${libvdpau_nvidia}"."${nvidia_driver_version}" "${libvdpau_nvidia}" + [ -d "${CONTY_DIR}"/up/usr/lib ] && export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}":"${CONTY_DIR}"/up/usr/lib:"${LD_LIBRARY_PATH}" + [ -d "${CONTY_DIR}"/up/usr/share ] && export XDG_DATA_DIRS="${XDG_DATA_DIRS}":"${CONTY_DIR}"/up/usr/share:"${XDG_DATA_DIRS}" + fi +fi + +PROOT_BINDINGS="" +BWRAP_BINDINGS="" + +bind_files="/etc/resolv.conf /etc/hosts /etc/nsswitch.conf /etc/passwd /etc/group /etc/machine-id /etc/asound.conf /etc/localtime " +for f in $bind_files; do [ -f "$f" ] && PROOT_BINDINGS=" $PROOT_BINDINGS --bind=$f" && BWRAP_BINDINGS=" $BWRAP_BINDINGS --ro-bind-try $f $f"; done + +bind_dirs=" /media /mnt /opt /run/media /usr/lib/locale /usr/share/fonts /usr/share/themes /var" +for d in $bind_dirs; do [ -d "$d" ] && PROOT_BINDINGS=" $PROOT_BINDINGS --bind=$d" && BWRAP_BINDINGS=" $BWRAP_BINDINGS --bind-try $d $d"; done + +PROOT_BINDS=" --bind=/dev --bind=/sys --bind=/tmp --bind=/proc $PROOT_BINDINGS --bind=/home --bind=/home/$USER " +BWRAP_BINDS=" --dev-bind /dev /dev --ro-bind /sys /sys --bind-try /tmp /tmp --proc /proc $BWRAP_BINDINGS " + +_JUNEST_CMD() { + if [ "$PROOT_ON" = 1 ]; then + "$HERE"/.local/share/junest/bin/junest proot -n -b "$PROOT_BINDS" "$@" + else + "$HERE"/.local/share/junest/bin/junest -n -b "$BWRAP_BINDS" "$@" + fi +} + +EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2- | sed -e 's|%.||g') + +_JUNEST_CMD -- $EXEC "$@" + +HEREDOC +chmod a+x ./AppRun + +cd .. || exit 1 + +############################################################################# +# EXTRACT PACKAGES +############################################################################# + +# EXTRACT PACKAGES +_extract_main_package() { + mkdir -p base + rm -Rf ./base/* + pkg_full_path=$(find ./"$APP".AppDir -type f -name "$APP-*zst") + if [ "$(echo "$pkg_full_path" | wc -l)" = 1 ]; then + pkg_full_path=$(find ./"$APP".AppDir -type f -name "$APP-*zst") + else + for p in $pkg_full_path; do + if tar "$p" .PKGINFO -O | grep -q "pkgname = $APP$"; then + pkg_full_path="$p" + fi + done + fi + [ -z "$pkg_full_path" ] && echo "💀 ERROR: no package found for \"$APP\", operation aborted!" && exit 0 + tar fx "$pkg_full_path" -C ./base/ + VERSION=$(cat ./base/.PKGINFO | grep pkgver | cut -c 10- | sed 's@.*:@@') + mkdir -p deps + rm -Rf ./deps/* +} + +_download_missing_packages() { + localpackage=$(find ./"$APP".AppDir -name "$arg-[0-9]*zst") + if ! test -f "$localpackage"; then + ./"$APP".AppDir/.local/share/junest/bin/junest -- yay --noconfirm -Sw "$arg" + fi +} + +_extract_package() { + _download_missing_packages &> /dev/null + pkg_full_path=$(find ./"$APP".AppDir -name "$arg-[0-9]*zst") + pkgname=$(echo "$pkg_full_path" | sed 's:.*/::') + if test -f "$pkg_full_path"; then + if ! grep -q "$pkgname" ./packages 2>/dev/null;then + echo "◆ Extracting $pkgname" + tar fx "$pkg_full_path" -C ./deps/ --warning=no-unknown-keyword + echo "$pkgname" >> ./packages + else + tar fx "$pkg_full_path" -C ./deps/ --warning=no-unknown-keyword + echo "$pkgname" >> ./packages + fi + [ -n "$lib_browser_launcher" ] && [[ "$arg" =~ (hicolor-icon-theme|xapp) ]] && tar fx "$pkg_full_path" -C ./base/ --warning=no-unknown-keyword --exclude='.PKGINFO' + fi +} + +_determine_packages_and_libraries() { + if echo "$arg" | grep -q "\.so"; then + LIBSAVED="$LIBSAVED $arg" + elif [ "$arg" != autoconf ] && [ "$arg" != autoconf ] && [ "$arg" != automake ] && [ "$arg" != bison ] && [ "$arg" != debugedit ] && [ "$arg" != dkms ] && [ "$arg" != fakeroot ] && [ "$arg" != flatpak ] && [ "$arg" != linux ] && [ "$arg" != gcc ] && [ "$arg" != make ] && [ "$arg" != pacman ] && [ "$arg" != patch ] && [ "$arg" != systemd ]; then + _extract_package + cat ./deps/.PKGINFO 2>/dev/null | grep "^depend = " | cut -c 10- | sed 's/=.*//' >> depdeps + rm -f ./deps/.* + fi +} + +_extract_deps() { + DEPS=$(sort -u ./depdeps) + for arg in $DEPS; do + _determine_packages_and_libraries + done +} + +_extract_all_dependences() { + rm -f ./depdeps + + OPTDEPS=$(cat ./base/.PKGINFO 2>/dev/null | grep "^optdepend = " | sed 's/optdepend = //g' | sed 's/=.*//' | sed 's/:.*//') + for arg in $OPTDEPS; do + _determine_packages_and_libraries + done + [ -f ./depdeps ] && _extract_deps + rm -f ./depdeps + + ARGS=$(echo "$DEPENDENCES" | tr " " "\n") + for arg in $ARGS; do + _determine_packages_and_libraries + done + + DEPS=$(cat ./base/.PKGINFO 2>/dev/null | grep "^depend = " | sed 's/depend = //g' | sed 's/=.*//') + for arg in $DEPS; do + _determine_packages_and_libraries + done + + # Set the level of sub-dependencies extraction, the higher the number, the bigger the AppImage will be + [ -z "$extraction_count" ] && extraction_count=1 + for e in $(seq "$extraction_count"); do _extract_deps; done + + rm -f ./packages +} + +echo "-----------------------------------------------------------------------------" +echo " EXTRACTING DEPENDENCES" +echo "-----------------------------------------------------------------------------" +echo "" +_extract_main_package +_extract_all_dependences + +# SAVE ESSENTIAL FILES AND LIBRARIES +echo "" +echo "-----------------------------------------------------------------------------" +echo " IMPLEMENTING NECESSARY LIBRARIES (MAY TAKE SEVERAL MINUTES)" +echo "-----------------------------------------------------------------------------" +echo "" + +############################################################################# +# SAVE FILES AND DIRECTORIES AND DETECT THE NEEDED LIBRARIES +############################################################################# + +# Save files in /usr/bin +_savebins() { + echo "◆ Saving files in /usr/bin" + mkdir save + mv ./"$APP".AppDir/.junest/usr/bin/bwrap ./save/ + mv ./"$APP".AppDir/.junest/usr/bin/proot* ./save/ + mv ./"$APP".AppDir/.junest/usr/bin/*$BIN* ./save/ + coreutils="[ basename cat chmod chown cp cut dir dirname du echo env expand expr fold head id ln ls mkdir mv readlink realpath rm rmdir seq sleep sort stty sum sync tac tail tee test timeout touch tr true tty uname uniq wc who whoami yes" + utils_bin="bash $coreutils grep ld sed sh strings" + for b in $utils_bin; do + mv ./"$APP".AppDir/.junest/usr/bin/"$b" ./save/ + done + for arg in $BINSAVED; do + mv ./"$APP".AppDir/.junest/usr/bin/*"$arg"* ./save/ + done + rm -Rf ./"$APP".AppDir/.junest/usr/bin/* + mv ./save/* ./"$APP".AppDir/.junest/usr/bin/ + rmdir save +} + +# Save files in /usr/lib +_binlibs() { + echo "◆ Saving libraries related to /usr/bin files" + readelf -d ./"$APP".AppDir/.junest/usr/bin/* | grep .so | sed 's:.* ::' | cut -c 2- | sed 's/\(^.*so\).*$/\1/' | uniq >> ./list + mv ./"$APP".AppDir/.junest/usr/lib/ld-linux-x86-64.so* ./save/ + mv ./"$APP".AppDir/.junest/usr/lib/*$APP* ./save/ + mv ./"$APP".AppDir/.junest/usr/lib/*$BIN* ./save/ + mv ./"$APP".AppDir/.junest/usr/lib/libdw* ./save/ + mv ./"$APP".AppDir/.junest/usr/lib/libelf* ./save/ + for arg in $SHARESAVED; do + mv ./"$APP".AppDir/.junest/usr/lib/*"$arg"* ./save/ + done + ARGS=$(tail -n +2 ./list | sort -u | uniq) + for arg in $ARGS; do + mv ./"$APP".AppDir/.junest/usr/lib/"$arg"* ./save/ + find ./"$APP".AppDir/.junest/usr/lib/ -name "$arg" -exec cp -r --parents -t save/ {} + + done + rm -Rf "$(find ./save/ | sort | grep ".AppDir" | head -1)" + rm list +} + +_include_swrast_dri() { + mkdir ./save/dri + mv ./"$APP".AppDir/.junest/usr/lib/dri/swrast_dri.so ./save/dri/ +} + +_libkeywords() { + echo "◆ Saving libraries using keywords" + for arg in $LIBSAVED; do + mv ./"$APP".AppDir/.junest/usr/lib/*"$arg"* ./save/ + done +} + +_readelf_save() { + echo "◆ Saving libraries related to previously saved files" + find_libs=$(find ./save -type f -name '*.so*' | uniq) + for f in $find_libs; do + readelf -d "$f" | grep .so | sed 's:.* ::' | cut -c 2- | sed 's/\(^.*so\).*$/\1/' | uniq >> ./list & + done + wait + ARGS=$(tail -n +2 ./list | sort -u | uniq) + for arg in $ARGS; do + mv ./"$APP".AppDir/.junest/usr/lib/"$arg"* ./save/ + find ./"$APP".AppDir/.junest/usr/lib/ -name "$arg" -exec cp -r --parents -t save/ {} + + done + rsync -av ./save/"$APP".AppDir/.junest/usr/lib/ ./save/ + rm -Rf "$(find ./save/ | sort | grep ".AppDir" | head -1)" + rm list +} + +_readelf_base() { + echo "◆ Detect libraries of the main package" + find_libs=$(find ./base -type f | uniq) + for f in $find_libs; do + readelf -d "$f" | grep .so | sed 's:.* ::' | cut -c 2- | sed 's/\(^.*so\).*$/\1/' | uniq >> ./list & + done + wait +} + +_readelf_deps() { + echo "◆ Detect libraries of the dependencies" + find_libs=$(find ./deps -executable -type f | uniq) + for f in $find_libs; do + readelf -d "$f" | grep .so | sed 's:.* ::' | cut -c 2- | sed 's/\(^.*so\).*$/\1/' | uniq >> ./list & + done + wait +} + +_liblibs() { + _readelf_base + _readelf_deps + echo "◆ Saving libraries related to the previously extracted packages" + ARGS=$(tail -n +2 ./list | sort -u | uniq) + for arg in $ARGS; do + mv ./"$APP".AppDir/.junest/usr/lib/"$arg"* ./save/ + find ./"$APP".AppDir/.junest/usr/lib/ -name "$arg" -exec cp -r --parents -t save/ {} + + done + rsync -av ./save/"$APP".AppDir/.junest/usr/lib/ ./save/ + rm -Rf "$(find ./save/ | sort | grep ".AppDir" | head -1)" + rm list + _readelf_save + _readelf_save + _readelf_save + _readelf_save +} + +_mvlibs() { + echo "◆ Restore saved libraries to /usr/lib" + rm -Rf ./"$APP".AppDir/.junest/usr/lib/* + mv ./save/* ./"$APP".AppDir/.junest/usr/lib/ +} + +_savelibs() { + mkdir save + #_binlibs 2> /dev/null + #_include_swrast_dri 2> /dev/null + #_libkeywords 2> /dev/null + #_liblibs 2> /dev/null + #_mvlibs 2> /dev/null + rmdir save +} + +# Save files in /usr/share +_saveshare() { + mkdir save + mv ./"$APP".AppDir/.junest/usr/share/*$APP* ./save/ + mv ./"$APP".AppDir/.junest/usr/share/*$BIN* ./save/ + mv ./"$APP".AppDir/.junest/usr/share/fontconfig ./save/ + mv ./"$APP".AppDir/.junest/usr/share/glib-* ./save/ + mv ./"$APP".AppDir/.junest/usr/share/locale ./save/ + mv ./"$APP".AppDir/.junest/usr/share/mime ./save/ + mv ./"$APP".AppDir/.junest/usr/share/wayland ./save/ + mv ./"$APP".AppDir/.junest/usr/share/X11 ./save/ + for arg in $SHARESAVED; do + mv ./"$APP".AppDir/.junest/usr/share/*"$arg"* ./save/ + done + rm -Rf ./"$APP".AppDir/.junest/usr/share/* + mv ./save/* ./"$APP".AppDir/.junest/usr/share/ + rmdir save +} + +#_savebins 2> /dev/null +_savelibs +#_saveshare 2> /dev/null + +# ASSEMBLING THE APPIMAGE PACKAGE +_rsync_main_package() { + echo "" + echo "-----------------------------------------------------------------------------" + rm -Rf ./base/.* + rsync -av ./base/ ./"$APP".AppDir/.junest/ | echo "◆ Rsync the content of the \"$APP\" package" +} + +_rsync_dependences() { + rm -Rf ./deps/.* + #rsync -av ./deps/ ./"$APP".AppDir/.junest/ | echo "◆ Rsync all dependeces, please wait..." + echo "-----------------------------------------------------------------------------" + echo "" +} + +############################################################################# +# REMOVE BLOATWARES, ENABLE MOUNTPOINTS +############################################################################# + +_remove_more_bloatwares() { + etc_remove="makepkg.conf pacman" + for r in $etc_remove; do + rm -Rf ./"$APP".AppDir/.junest/etc/"$r"* + done + bin_remove="gcc" + for r in $bin_remove; do + rm -Rf ./"$APP".AppDir/.junest/usr/bin/"$r"* + done + lib_remove="gcc" + for r in $lib_remove; do + rm -Rf ./"$APP".AppDir/.junest/usr/lib/"$r"* + done + share_remove="gcc" + for r in $share_remove; do + rm -Rf ./"$APP".AppDir/.junest/usr/share/"$r"* + done + echo Y | rm -Rf ./"$APP".AppDir/.cache/yay/* + find ./"$APP".AppDir/.junest/usr/share/doc/* -not -iname "*$BIN*" -a -not -name "." -delete 2> /dev/null #REMOVE ALL DOCUMENTATION NOT RELATED TO THE APP + find ./"$APP".AppDir/.junest/usr/share/locale/*/*/* -not -iname "*$BIN*" -a -not -name "." -delete 2> /dev/null #REMOVE ALL ADDITIONAL LOCALE FILES + rm -Rf ./"$APP".AppDir/.junest/home # remove the inbuilt home + rm -Rf ./"$APP".AppDir/.junest/usr/include # files related to the compiler + rm -Rf ./"$APP".AppDir/.junest/usr/share/man # AppImages are not ment to have man command + rm -Rf ./"$APP".AppDir/.junest/usr/lib/python*/__pycache__/* # if python is installed, removing this directory can save several megabytes + #rm -Rf ./"$APP".AppDir/.junest/usr/lib/libgallium* + #rm -Rf ./"$APP".AppDir/.junest/usr/lib/libgo.so* + #rm -Rf ./"$APP".AppDir/.junest/usr/lib/libLLVM* # included in the compilation phase, can sometimes be excluded for daily use + rm -Rf ./"$APP".AppDir/.junest/var/* # remove all packages downloaded with the package manager +} + +_enable_mountpoints_for_the_inbuilt_bubblewrap() { + mkdir -p ./"$APP".AppDir/.junest/home + mkdir -p ./"$APP".AppDir/.junest/media + mkdir -p ./"$APP".AppDir/.junest/usr/lib/locale + mkdir -p ./"$APP".AppDir/.junest/usr/share/fonts + mkdir -p ./"$APP".AppDir/.junest/usr/share/themes + mkdir -p ./"$APP".AppDir/.junest/run/media + mkdir -p ./"$APP".AppDir/.junest/run/user + rm -f ./"$APP".AppDir/.junest/etc/localtime && touch ./"$APP".AppDir/.junest/etc/localtime + [ ! -f ./"$APP".AppDir/.junest/etc/asound.conf ] && touch ./"$APP".AppDir/.junest/etc/asound.conf +} + +_rsync_main_package +_rsync_dependences +_remove_more_bloatwares +find ./"$APP".AppDir/.junest/usr/lib ./"$APP".AppDir/.junest/usr/lib32 -type f -regex '.*\.a' -exec rm -f {} \; +find ./"$APP".AppDir/.junest/usr -type f -regex '.*\.so.*' -exec strip --strip-debug {} \; +find ./"$APP".AppDir/.junest/usr/bin -type f ! -regex '.*\.so.*' -exec strip --strip-unneeded {} \; +_enable_mountpoints_for_the_inbuilt_bubblewrap + +############################################################################# +# CREATE THE APPIMAGE +############################################################################# + +if test -f ./*.AppImage; then rm -Rf ./*archimage*.AppImage; fi + +APPNAME=$(cat ./"$APP".AppDir/*.desktop | grep 'Name=' | head -1 | cut -c 6- | sed 's/ /-/g') +REPO="$APPNAME-appimage" +TAG="continuous" +VERSION="$VERSION" +UPINFO="gh-releases-zsync|$GITHUB_REPOSITORY_OWNER|$REPO|$TAG|*x86_64.AppImage.zsync" + +ARCH=x86_64 ./appimagetool --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 20 \ + -u "$UPINFO" \ + ./"$APP".AppDir "$APPNAME"_"$VERSION"-archimage4.2-x86_64.AppImage diff --git a/README.md b/README.md index f2054ef..3228441 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,22 @@ ArchImage is the bundling of Arch Linux packages into an AppImage using [JuNest] This allows you to use the latest programs from Arch Linux and AUR on every distribution, old or newer. -Being this a container into an AppImage, it has its own "bubblewrap" or "proot" to work using its inbuilt resources, including GLIBC, so it can run also on 10+ years old GNU/Linux distributions: +Being this a container into an AppImage, it has its own "bubblewrap" or "proot" to work using its inbuilt resources, including GLIBC, so it can run also on 10+ years old GNU/Linux distributions. +**From version 4.2 is available a NEW template that creates AppImages that can work on both systems with or without Namespaces restrictions:** + +- **[NEW-junest.sh](https://github.com/ivan-hc/ArchImage/blob/main/NEW-junest.sh)** + +It is the mix of the two previous templates used until version 4.1: - [sample-next-junest.sh](https://github.com/ivan-hc/ArchImage/blob/main/sample-next-junest.sh) uses bubblewrap and namespaces, so it is more flexible - [sample-junest.sh](https://github.com/ivan-hc/ArchImage/blob/main/sample-junest.sh) uses proot to be more portable but less integrated with the host system +If you have already installed `archimage-cli`, please run +``` +archimage-cli -s +``` +...to use the latest version. + Archimage combines the flexibility of JuNest with the power of Conty, the two portable Arch Linux containers that run on any other GNU/Linux distribution, offering the ability to package all the software available in the official Arch Linux repositories, the AUR and ChaoticAUR. ------------------------------------------------------------------------ @@ -36,6 +47,8 @@ Archimage combines the flexibility of JuNest with the power of Conty, the two po [Files removed by default](#files-removed-by-default) +[Customize your script](#customize-your-script) + [Drafts](#drafts) [Troubleshooting](#troubleshooting) @@ -106,22 +119,112 @@ Follow the steps at "[*What to do*](#what-to-do)" and watch the "[video example] ### Step by step guide Before proceeding, make sure you have understood "[What to do](#what-to-do)" and above all "[**What NOT to do**](#what-not-to-do)"! -1. Create the script, use the option `-b` or `--build`, example with "firefox" (see the above "[video](#example)"): +### 1. Create the script +Use the option `-b` or `--build`, example with "obs-studio" ``` -./archimage-cli -b firefox +./archimage-cli -b obs-studio ``` -2. The script will ask you if you want to specify the name of the binary or leave blank if the name is the same of [PROGRAM]. Being the executable `/usr/bin/firefox` of "firefox" named "firefox", press ENTER to leave blank. Some apps, have a different name for their executable (for example "handbrake" have `/usr/bin/ghb`, so just write "ghb" for it). If you're not sure about thename of the main executable, use https://archlinux.org/packages/ or read the PKGBUILD if the app is hosted on the AUR. By default, the script will use "yay" to install all the programs in JuNest. -3. The script will ask you to add a list of additional packages you want to include into the AppImage (with the syntax `app1 app2 app3...`), leave blank if no dependency is needed. -4. The next questions are about implementing or not all dependences, choose "Y" to bundle all the dependences, or "N" to do this in other steps. -5. **A new question has been added from version 4**, "*DO YOU WANT TO ENABLE HARDWARE ACCELERATION FOR NVIDIA USERS?*", leave blank not to allow the AppImage to configure Nvidia drivers via Conty for the AppImage, or press "y" to set `NVIDIA_ON=1`. This will use [Conty](https://github.com/Kron4ek/Conty) to check and setup the Nvidia drivers locally if needed, only fo Nvidia users. See "[Hardware Acceleration](#hardware-acceleration)" for more. -6. This phase, shown in the [video](#example), has a last message asking you to use a standard configuration with the following defaults if you press "Y": -- a package availability check in the Arch User Repository (if so, enable AUR and installs "binutils", "gzip" and "basedevel", all of them are only required to compile from and will not be included in the AppImage package) -- the AUR is enabled -- installs "ca-certificates" -- includes keywords for the internet connections and audio trying to enable them -- the file "/usr/lib/dri/swrast_dri.so" will NOT be included if not needed -If you press "N" (or leave blank) instead, you have a lot of configurations you can do by your own. -6. Run the script. + +![1](https://github.com/user-attachments/assets/d9c7b29b-2ccc-4cf0-b3ff-5de10cf13e5b) + +this will download and rename the script [NEW-junest.sh](https://github.com/ivan-hc/ArchImage/blob/dev/NEW-junest.sh) on your desktop. + +### 2. Add binary name +The script will ask you if you want to specify the name of the binary or leave blank if the name is the same of [PROGRAM]. In most cases we can leave blank, but for some applications, like OBS Studio, the executable name is different, in our case it is `obs` + +![2](https://github.com/user-attachments/assets/961d03ec-9c6a-4faa-a9ab-fa7dbb557b14) + +If you're not sure about thename of the main executable, use https://archlinux.org/packages/ or read the PKGBUILD if the app is hosted on the AUR. By default, the script will use "yay" to install all the programs in JuNest. + +### 3. Add extra dependencies +The script will ask you to add a list of additional packages you want to include into the AppImage (with the syntax `app1 app2 app3...`) + +![3](https://github.com/user-attachments/assets/2d6a3a5a-9fab-4c32-9081-d5bf5f51fe28) + +leave blank if no dependency is needed. In our example, we are using Archimage version 4.2, so we don't need add dependencies for `obs-studio`. Previous versions were less automatic and to build `obs-studio` we needed to add `python`. You can add many more packages, according to your needs. + +### 4. Extract dependencies and subdependencies by level +Assign a number to the variable "`$extraction_count`". The higher the number, the more dependencies will be downloaded separately, the longer the process will be, the bigger the final AppImage package will be... but at the same time the easier our AppImage will work. + +![4](https://github.com/user-attachments/assets/7e46e63a-8a60-426f-91c3-6eca36effb15) + +By default the level is 1, so only the dependencies of the direct dependencies of the application we want to package are extracted. For OBS Studio I set a level of 2, and this is enough to have an AppImage that works out of the box, but only if you include all dependencies and set the "**standard configuration**". Keep read. + +### 5. Include all dependencies? +Do you want to include all dependencies? Press "y", or leave blank if you want to keep customize (recommended) + +![5](https://github.com/user-attachments/assets/d50dd4bc-9bd4-43d9-82d7-6819d7c86d74) + +In my workflows I usually include all dependencies, to remove the extra files after I confirm that the application works. + +If you press "N" or leave blank, only the main package will be included, near the libraries and files imported when the script is running. + +Please, see the [tutorial](#tutorial) to learn more on how to investigate on app's malfunctions. + +### 5,5. AUR, whant tu use ChaoticAUR instead? The hidden question +Between question 5 (include all dependencies) and 6 (enable multilib) exists another hidden question + +![Istantanea_2025-01-12_07-20-18](https://github.com/user-attachments/assets/ab650430-a2da-4663-ae9d-c4d97d3f4103) + +this question come up only if the program is not hosted on the official repositories, so it come from AUR. + +In this case `binutils`, `gzip` and `base-devel` are enabled by default. You can choose to enable ChaoticAUR to save time and resources while compiling the program. For example `gimp-git` lasts 5 minutes or less from ChaoticAUR, while from AUR it can take 30 minutes or more (with the risk that it fails). + +Of course, this question will not come up with `obs-studio`, since it is on the official Arch Linux repositories. + +### 6. Enable multilib +Want to enable the "multilib" repo? It is usally needed for 32bit libraries, used in programs like WINE and frontends like Bottles + +![Istantanea_2025-01-12_06-53-42](https://github.com/user-attachments/assets/2e036728-49d5-4362-a042-f6b44efff393) + +in our case, we can leave blank or press "N". We don't need 32 bits libraries at all in this case. + +### 7. Enable hardware acceleration for Nvidia users +Do you want to allow hardware acceleration? This will enable Nvidia users to use your application where hardware acceleration is needed + +![Istantanea_2025-01-12_06-55-57](https://github.com/user-attachments/assets/2bd7483d-c521-4827-b7b8-20bb6301f704) + +to learn more on how hardware acceleration works with Archimages, see "[Hardware Acceleration](#hardware-acceleration)". + +### 8. Standard configuration +Standard configuration only enables keywords for Networking and Audio. If you have choosen to include all dependencies at point 5, press "y". This will exit the wizard + +![8](https://github.com/user-attachments/assets/c0f55b4f-b28f-4153-8735-14cf23ea8b92) + +if you press N or leave blank, you can keep customize the script. + +### 9. `binutils` and `gzip` +Junest is a very minimal system, you can choose to include `gzip` and `binutils` if you know that none of the previous packages will install them as dependencies. + +### 10. `base-devel` for AUR +If you need to build something from AUR, enable `base-devel` with all its related compilers + +This is how questions 9 and 10 appear + +![9-10](https://github.com/user-attachments/assets/0595778d-1687-4546-b3b4-3a26cffb095e) + +### 11. `BINSAVED`, `LIBSAVED` and `SHARESAVED` +Questions about keywords for binaries in /usr/bin, directories in /usr/share and various files and directories (mostly libraries) in /usr/lib are up to you. For example, if you want to include all Qt related files and directories, write `Qt` for the question related to the interested path. In my case I included `libgallium.so`, the search will be done using `find` and `grep` + +![Istantanea_2025-01-12_07-08-55](https://github.com/user-attachments/assets/1cb78573-d653-4866-a770-fbc95207977f) + +### 12. Preset of Audio and Networking keywords +Next two questions are related to a preset of keywords used to check files and libraries for networking and audio, the same that can be enabled in one go at point 8 + +![Istantanea_2025-01-12_07-12-50](https://github.com/user-attachments/assets/adc17a3b-36b9-4d27-8d8b-7d5f1f32df94) + +Personally I never go further than point 8, and press "y", because the script is simple enough to understand, if you have the patience to read what is written. So i prefer to edit manually my scripts when they are ready. + +### Ending message +At the end of the wizard you will have a series of suggestions like this + +![Istantanea_2025-01-12_07-19-02](https://github.com/user-attachments/assets/139698b4-c2aa-4675-9840-4c7c93e73c39) + +now you can finally run the script in an empty and dedicated directory. + +Again, make sure you have understood "[What to do](#what-to-do)" and above all "[**What NOT to do**](#what-not-to-do)"! + +Also, see the **[tutorial](#tutorial)** to debug and improve your AppImage. ----------------------------------------------------------- ## Requirements of an AppImage @@ -211,12 +314,15 @@ To create the basic script I'll use a standard configuration: 1. name: signal-desktop 2. name binary: leave blank, its the same 3. dependences: none -4. include all dependences: y -5. use defaults: y +4. extraction level: 1, default... leave blank. Whit only one level, the app will be smaller, but will not easily run at first go (for the sake of this tutorial) +5. include all dependences: y +6. multilib: nope, leave blank +7. hardware acceleration: nope, leave blank +8. use defaults: y like this: -https://github.com/user-attachments/assets/06308a6d-24db-417f-917c-8e1a9d78fe0b +https://github.com/user-attachments/assets/0e373cbd-f473-4214-bf3c-8530867762dd Once I created the script, I create a "tmp" directory (you can name it the way you want) and I put the script into it. @@ -356,6 +462,9 @@ This is a list of the AppImages I've built until I wrote this brief guide: - AppRun script very minimal and easy to configure; - all programs for Arch Linux within AppImage's reach, therefore one of the most extensive software parks in the GNU/Linux panorama. +### Disadvantages +- the AppImage can be bloated if you don't set a list of removable items manually + ------------------------------------------------------------------------ # Drafts @@ -368,7 +477,55 @@ in my experiments, if I uploaded them here, it means that they work quite well o ------------------------------------------------------------------------ # Files removed by default -After the line "`# REMOVE SOME BLOATWARES`" I added a list of functions that you can use with Archimage 2.x and above. You can edit the script as you like to add/remove files in case they are not enough for your experiments. +The following function is responsible of removals of unneeded files and directories, you can find it to the end of the script +``` +_remove_more_bloatwares() { + etc_remove="makepkg.conf pacman" + for r in $etc_remove; do + rm -Rf ./"$APP".AppDir/.junest/etc/"$r"* + done + bin_remove="gcc" + for r in $bin_remove; do + rm -Rf ./"$APP".AppDir/.junest/usr/bin/"$r"* + done + lib_remove="gcc" + for r in $lib_remove; do + rm -Rf ./"$APP".AppDir/.junest/usr/lib/"$r"* + done + share_remove="gcc" + for r in $share_remove; do + rm -Rf ./"$APP".AppDir/.junest/usr/share/"$r"* + done + echo Y | rm -Rf ./"$APP".AppDir/.cache/yay/* + find ./"$APP".AppDir/.junest/usr/share/doc/* -not -iname "*$BIN*" -a -not -name "." -delete 2> /dev/null #REMOVE ALL DOCUMENTATION NOT RELATED TO THE APP + find ./"$APP".AppDir/.junest/usr/share/locale/*/*/* -not -iname "*$BIN*" -a -not -name "." -delete 2> /dev/null #REMOVE ALL ADDITIONAL LOCALE FILES + rm -Rf ./"$APP".AppDir/.junest/home # remove the inbuilt home + rm -Rf ./"$APP".AppDir/.junest/usr/include # files related to the compiler + rm -Rf ./"$APP".AppDir/.junest/usr/share/man # AppImages are not ment to have man command + rm -Rf ./"$APP".AppDir/.junest/usr/lib/python*/__pycache__/* # if python is installed, removing this directory can save several megabytes + #rm -Rf ./"$APP".AppDir/.junest/usr/lib/libgallium* + #rm -Rf ./"$APP".AppDir/.junest/usr/lib/libgo.so* + #rm -Rf ./"$APP".AppDir/.junest/usr/lib/libLLVM* # included in the compilation phase, can sometimes be excluded for daily use + rm -Rf ./"$APP".AppDir/.junest/var/* # remove all packages downloaded with the package manager +} +``` +it contains 4 variables: +- `etc_remove` to remove files in /etc +- `bin_remove` to remove files in /usr/bin +- `lib_remove` to remove files and directories in /usr/lib +- `share_remove` to remove files and directories in /usr/share + +it is enough to add the name or the first keywords of the names you want to remove. For example if you add `z` in `share_remove`, all directories starting with "z" will be removed. If you add `icons/Adwaita/cursors/` in `share_remove`, all files under /usr/share/icons/Adwaita/cursors/ will be removed. + +A known list of big ligraries is also commented in this function (`libgallium`, `libgo.so` and `libLLVM`), uncomment if the app works without them. + +The `find` commands of the abofe function will remove languages and documentation not related to "`$BIN`" (the binary name of the app, in most cases the value is `BIN="$APP"`, but it may change, depending on the script you have created. + +------------------------------------------------------------------------ +# Customize your script +Once you created the script, it is yours and only yours. You can add/remove functions as you like. + +Of course, **DO IT ON YOUR OWN RISK!** ------------------------------------------------------------------------ diff --git a/archimage-cli b/archimage-cli index 9779e5a..ec4d83c 100644 --- a/archimage-cli +++ b/archimage-cli @@ -1,6 +1,6 @@ #!/usr/bin/env bash -VERSION="4.1" +VERSION="4.2" DIR="$( cd "$( dirname "$0" )" && pwd )" ARCHIMAGE_REPO="https://raw.githubusercontent.com/ivan-hc/ArchImage/main" @@ -101,61 +101,47 @@ _sync() { ################################################################################ # First step -GETTING_STARTED_MSG="----------------------------------------------------------------------------- +GETTING_STARTED_HEADER="----------------------------------------------------------------------------- ${LightBlue}ARCHIMAGE SCRIPT CREATING WIZARD\033[0m, v$VERSION -$DIVIDING_LINE -After creating the script, make sure to run it in a dedicated directory. Do not run the script in directories that are already occupied! +$DIVIDING_LINE" +GETTING_STARTED_MSG="After creating the script, make sure to run it in a dedicated directory. -You can re-run the same script at the end of the process in case the AppImage creation failed and the program does not work as you wanted, as long as everything happens always in the same dedicated directory. -$DIVIDING_LINE -Choose whether to build the AppImage using: +Do not run the script in directories that are already occupied! -1. BubbleWrap (default), uses Linux namespaces for greater host compatibility -2. Proot (new), maximum portability, but still experimental -" -_get_started() { - printf "%b\n" "$GETTING_STARTED_MSG" | _fit | sed "s/ --/--/g" - read -r -ep "◆ Choose between BubbleWrap (1, default) and Proot (2): " choose - if [ "$choose" = 2 ]; then - TEMPLATE="sample-junest.sh" - else - TEMPLATE="sample-next-junest.sh" - fi -} +You can re-run the same script at the end of the process in case the AppImage creation failed and the program does not work as you wanted, as long as everything happens always in the same dedicated directory." # Name the executable in /usr/bin if different from the appname _usr_bin_executable_name() { echo "$DIVIDING_LINE" read -r -ep "◆ NAME THE MAIN EXECUTABLE IN \$PATH, OR LEAVE BLANK IF IT IS THE SAME: " response - if [ -n "$response" ]; then - mv ./"$APP"-junest.sh ./"$APP"-junest.sh.old - sed -n '1,4p' ./"$APP"-junest.sh.old >> ./"$APP"-junest.sh - echo "BIN=\"$response\"" >> ./"$APP"-junest.sh - sed -n '6,20000000p' ./"$APP"-junest.sh.old >> ./"$APP"-junest.sh - rm -f ./"$APP"-junest.sh.old - fi + [ -n "$response" ] && sed -i "s/^BIN=\"\$APP\"/BIN=\"$response\"/g" ./"$APP"-junest.sh } # Add optional dependencies -_add_dependences() { - read -r -ep "◆ ADD (OPTIONAL) DEPENDENCES OR LEAVE BLANK: " RESPONSE - if [ -n "$RESPONSE" ]; then - mv ./"$APP"-junest.sh ./"$APP"-junest.sh.old - sed -n '1,5p' ./"$APP"-junest.sh.old >> ./"$APP"-junest.sh - echo "DEPENDENCES=\"$RESPONSE\"" >> ./"$APP"-junest.sh - sed -n '7,20000000p' ./"$APP"-junest.sh.old >> ./"$APP"-junest.sh - rm -f ./"$APP"-junest.sh.old - fi +_add_dependencies() { + read -r -ep "◆ ADD (OPTIONAL) DEPENDENCIES OR LEAVE BLANK: " RESPONSE + [ -n "$RESPONSE" ] && sed -i "s/^DEPENDENCES=\"\"/DEPENDENCES=\"$RESPONSE\"/g" ./"$APP"-junest.sh +} + +# Set the level of sub-dependencies extraction, the higher the number, the bigger the AppImage will be +_extraction_level() { + echo "◆ Set the level of sub-dependencies." + echo "" + echo "The variable \"\$extraction_count\" indicates the number of checks made on dependencies and dependencies of dependencies. The higher the number, the more packages will be included, the more successfully the app will work... the bigger the AppImage will be." | _fit | sed 's/^/ /g' + echo "" + read -r -ep " LEAVE BLANK TO SET THE DEFAULT VALUE TO 1 (RECOMMENDED): " extraction_number + [ -n "$extraction_number" ] && [[ "$extraction_number" =~ ^[0-9]+$ ]] && sed -i "s/extraction_count=1/extraction_count=$extraction_number/g" ./"$APP"-junest.sh } # Include all dependencies in the final AppImage -_include_all_dependences() { +_include_all_dependencies() { echo "◆ Automatic library checking should be more than enough. However..." - read -r -ep " DO YOU WANT TO INCLUDE ALL DEPENDENCES? THE PACKAGE MAY BE BLOATED (y,N) " yn + echo "" + read -r -ep " DO YOU WANT TO INCLUDE ALL DEPENDENCIES? THE PACKAGE MAY BE BLOATED (y,N) " yn if echo "$yn" | grep -qi "^y"; then sed -i 's/#rsync -av/rsync -av/g' ./"$APP"-junest.sh - fi + fi } # Allow Nvidia check in the final AppImage @@ -167,18 +153,20 @@ _enable_nvidia() { } # Start configuration -STANDARD_CONFIGURATION_MSG="◆ Choose to finish using a standard configuration with the bare minimum or continue by customizing the script as much as possible (default). -The standard configuration includes a package availability check in the Arch User Repository (if so, enable AUR and installs \"binutils\", \"gzip\" and \"basedevel\", all of them are only required to compile from and will not be included in the AppImage package), the AUR is enabled, installs \"ca-certificates\", includes keywords for the internet connections and audio trying to enable them. -The file \"/usr/lib/dri/swrast_dri.so\" will NOT be included if not needed. - -Choose \"N\" or leave blank instead to continue customization (RECOMMENDED). +STANDARD_CONFIGURATION_MSG="◆ Press \"y\" to finish using a standard configuration with the bare minimum for network and audio support, press \"N\" or leave blank instead to continue customization (RECOMMENDED). " _enable_chaoticaur() { - echo "$DIVIDING_LINE" read -r -ep "◆ DO YOU WANT TO ENABLE CHAOTIC-AUR (y,N)? " yn if echo "$yn" | grep -qi "^y"; then - sed -i 's/###_enable_chaoticaur/_enable_chaoticaur/g' ./"$APP"-junest.sh + sed -i 's/#_enable_chaoticaur/_enable_chaoticaur/g' ./"$APP"-junest.sh + fi +} + +_enable_multilib() { + read -r -ep "◆ DO YOU WANT TO ENABLE MULTILIB WITH 32BIT LIBRARIES (y,N)? " yn + if echo "$yn" | grep -qi "^y"; then + sed -i 's/#_enable_multilib/_enable_multilib/g' ./"$APP"-junest.sh fi } @@ -231,21 +219,14 @@ _include_swrast() { _include_audio_keywords() { read -r -ep "◆ DO YOU WISH TO ADD KEYWORDS IN /usr/lib TO ENABLE THE AUDIO (y,N)?" yn if echo "$yn" | grep -qi "^y"; then - sed -i 's/LIBSAVED="/LIBSAVED="alsa jack pipewire pulse /g' ./"$APP"-junest.sh + sed -i 's/^#lib_audio_keywords/lib_audio_keywords/g' ./"$APP"-junest.sh fi } _include_internet_keywords() { - read -r -ep "◆ I RECOMMEND TO USE CA-CERTIFICATES TRYING TO ENABLE THE INTERNET $(echo -e '\n DO YOU WISH TO ADD IT INTO THE SCIPT (y,N)?') " yn + read -r -ep "◆ DO YOU WISH TO ADD KEYWORDS IN /use/lib TO USE NETWORK (y,N)? " yn if echo "$yn" | grep -qi "^y"; then - sed -i 's/DEPENDENCES="/DEPENDENCES="ca-certificates /g' ./"$APP"-junest.sh - sed -i 's/BINSAVED="/BINSAVED="certificates /g' ./"$APP"-junest.sh - sed -i 's/#_binlibs/_binlibs/g' ./"$APP"-junest.sh - sed -i 's/SHARESAVED="/SHARESAVED="certificates /g' ./"$APP"-junest.sh - sed -i 's/#_saveshare/_saveshare/g' ./"$APP"-junest.sh - sed -i 's/LIBSAVED="/LIBSAVED="pk p11 /g' ./"$APP"-junest.sh - sed -i 's/#_mvlibs/_mvlibs/g' ./"$APP"-junest.sh - sed -i 's/#_liblibs/_liblibs/g' ./"$APP"-junest.sh + sed -i 's/^#lib_browser_launcher/lib_browser_launcher/g' ./"$APP"-junest.sh fi } @@ -286,15 +267,27 @@ case "$1" in echo " USAGE: archimage-cli -b [PROGRAM]" exit 0 else - _get_started + printf "%b" "$GETTING_STARTED_HEADER" + echo "$GETTING_STARTED_MSG" | _fit APP="$2" - wget -q "$ARCHIMAGE_REPO/$TEMPLATE" -O "$APP"-junest.sh + wget -q "$ARCHIMAGE_REPO/NEW-junest.sh" -O "$APP"-junest.sh sed -i "s#APP=SAMPLE#APP=$APP#g" "$APP"-junest.sh _usr_bin_executable_name echo "$DIVIDING_LINE" - _add_dependences + _add_dependencies echo "$DIVIDING_LINE" - _include_all_dependences + _extraction_level + echo "$DIVIDING_LINE" + _include_all_dependencies + echo "$DIVIDING_LINE" + if curl --output /dev/null --silent --fail -r 0-0 https://aur.archlinux.org/packages/"$APP" 2> /dev/null; then + sed -i 's/#BASICSTUFF/BASICSTUFF/g' ./"$APP"-junest.sh # INSTALL BINUTILS AND GZIP + sed -i 's/#COMPILERS/COMPILERS/g' ./"$APP"-junest.sh # INSTALL BASE-DEVEL + sed -i '/-- gpg --keyserver/ s/^#*//' ./"$APP"-junest.sh # ENABLE AUR GPG VALIDATION + _enable_chaoticaur + echo "$DIVIDING_LINE" + fi + _enable_multilib echo "$DIVIDING_LINE" _enable_nvidia echo "$DIVIDING_LINE" @@ -305,26 +298,14 @@ case "$1" in sed -i 's/#_liblibs/_liblibs/g' ./"$APP"-junest.sh # CHECK LIBRARIES RELATED TO OTHER LIBRARIES sed -i 's/#_mvlibs/_mvlibs/g' ./"$APP"-junest.sh # MV ALL LIBRARIES SAVED IN THE COMMANDS ABOVE AND BELOW sed -i 's/#_libkeywords/_libkeywords/g' ./"$APP"-junest.sh # CHECK LIBRARIES RELATED TO KEYWORD SAVED BELOW - sed -i 's/LIBSAVED="/LIBSAVED="alsa jack pipewire pulse /g' ./"$APP"-junest.sh # SAVE KEYWORDS RELATED TO AUDIO - sed -i 's/DEPENDENCES="/DEPENDENCES="ca-certificates /g' ./"$APP"-junest.sh # INSTALL CA-CERTIFICATES - sed -i 's/BINSAVED="/BINSAVED="certificates /g' ./"$APP"-junest.sh # SAVE CA-CERTIFICATES IN /usr/bin + sed -i 's/#lib_audio_keywords/lib_audio_keywords/g' ./"$APP"-junest.sh # SAVE KEYWORDS RELATED TO AUDIO sed -i 's/#_savebins/_savebins/g' ./"$APP"-junest.sh # SAVE KEYWORDS IN /usr/bin sed -i 's/#_binlibs/_binlibs/g' ./"$APP"-junest.sh # CHECK LIBRARIES RELATED TO BINARIES IN /usr/bin - sed -i 's/SHARESAVED="/SHARESAVED="certificates /g' ./"$APP"-junest.sh # SAVE CA-CERTIFICATES IN /usr/share sed -i 's/#_saveshare/_saveshare/g' ./"$APP"-junest.sh # SAVE KEYWORDS IN /usr/share - sed -i 's/LIBSAVED="/LIBSAVED="pk p11 /g' ./"$APP"-junest.sh # SAVE SOME KEYWORDS NEEDED FOR INTERNET - if curl --output /dev/null --silent --fail -r 0-0 https://aur.archlinux.org/packages/"$APP" 2> /dev/null; then - sed -i 's/#BASICSTUFF/BASICSTUFF/g' ./"$APP"-junest.sh # INSTALL BINUTILS AND GZIP - sed -i 's/#COMPILERS/COMPILERS/g' ./"$APP"-junest.sh # INSTALL BASE-DEVEL - sed -i '/-- gpg --keyserver/ s/^#*//' ./"$APP"-junest.sh # ENABLE AUR GPG VALIDATION - fi + sed -i 's/^#lib_browser_launcher/lib_browser_launcher/g' ./"$APP"-junest.sh # ALLOW THE PROGRAM TO OPEN THE SYSTEM BROWSER else - echo "$DIVIDING_LINE" - _enable_chaoticaur - echo "$DIVIDING_LINE" - _enable_basicstuff - echo "$DIVIDING_LINE" - _enable_compilers + grep -q "^#BASICSTUFF" ./"$APP"-junest.sh && echo "$DIVIDING_LINE" && _enable_basicstuff + grep -q "^#COMPILERS" ./"$APP"-junest.sh && echo "$DIVIDING_LINE" && _enable_compilers echo "$DIVIDING_LINE" _keywords_to_save_in_usr_bin echo "$DIVIDING_LINE" @@ -337,7 +318,12 @@ case "$1" in chmod a+x ./"$APP"-junest.sh echo " THE SCRIPT IS READY, RUN IT TO CREATE AN APPIMAGE!" echo "" - printf "\nSUGGESTIONS:\n\n- from line titled 'REMOVE SOME BLOATWARES', add a list of items to be deleted to avoid an excess in the size of the final AppImage archive.\n\n" | _fit + echo " SUGGESTIONS:" + echo "" + echo "◆ you can manually complete the function named \"_remove_more_bloatwares\" with a list of items to be deleted to avoid an excess in the size of the final AppImage" | _fit + echo "◆ in the footer of the script you can manually add TAG and REPO in case you want to host an updatable AppImage on github.com" | _fit + echo "◆ about the \"\$extraction_count\" variable, you can also set its value externally, for example, by running \"export extraction_count=2\"" | _fit + echo "" exit 0 done ;;