File pkg2appimage of Package build-pkg2appimage
#!/bin/bash
#
# pkg 2 appimage converter
# really in alpha state atm
# GOAL: Only build/OBS specific parts shall be inside
# GOAL: As much as possible should be moved to Recipe and functions.sh
#
# stolen from Recipe file
parse_yaml() {
local prefix=$2
local s
local w
local fs
s='[[:space:]]*'
w='[a-zA-Z0-9_]*'
fs="$(echo @|tr @ '\034')"
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)$s[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" |
awk -F"$fs" '{
indent = length($1)/2;
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, $3);
}
}' | sed 's/_=/+=/g'
}
shell_execute() {
if [ -f /tmp/recipe_script ] ; then
rm /tmp/recipe_script
fi
parse_yaml $BUILD_SOURCE_DIR/appimage.yml "_" | grep "^$2+=" > /tmp/recipe_script
sed -i -e 's|^'$2'+=("||g' /tmp/recipe_script
sed -i -e 's|")$||g' /tmp/recipe_script
if [ ! -s /tmp/recipe_script ]; then
echo "ERROR: Empty or missing script section!"
echo " (or parser error, ensure to follow the '2 space2' rule for indenting)"
exit 1
fi
bash -ex /tmp/recipe_script || exit 1
rm /tmp/recipe_script
}
# Echo highest glibc version needed by the executable files in the current directory
glibc_needed()
{
find . -name *.so -or -name *.so.* -or -type f -executable -exec readelf -s '{}' 2>/dev/null \; | sed -n 's/.*@GLIBC_//p'| awk '{print $1}' | sort --version-sort | tail -n 1
}
fix_desktop() {
# fix trailing semicolons
for key in Actions Categories Implements Keywords MimeType NotShowIn OnlyShowIn; do
sed -i '/'"$key"'.*[^;]$/s/$/;/' $1
done
}
export TOPDIR="${PWD%/*}"
export STATIC_FILES=/usr/lib/appimagetool
. $STATIC_FILES/functions.sh
export BUILD_SOURCE_DIR=$TOPDIR/SOURCES/
RELEASE="Build0"
if [ "$1" == "--release" ]; then
RELEASE="Build$2"
fi
# find out details about our master package... is there a better way?
PKG_NAME=`sed -n -e 's,^app: \(.*\),\1,p' appimage.yml`
PKG_ARCH=`uname -m`
if grep -q ^ingredients: appimage.yml; then
APP_PKG_NAME="$PKG_NAME"
if ! rpm -q "$PKG_NAME" >& /dev/null; then
desktop_file=`find /usr/share/applications -iname "*${PKG_NAME}.desktop" | head -n 1`
[ -n "$desktop_file" ] && APP_PKG_NAME=`rpm -qf $desktop_file --qf '%{NAME}'`
fi
if rpm -q "$APP_PKG_NAME" >& /dev/null; then
PKG_NAME="$APP_PKG_NAME"
PKG_VERSION=`rpm -q --qf '%{VERSION}-%{RELEASE}' "$PKG_NAME"`
# PKG_ARCH=`rpm -q --qf '%{ARCH}' "$PKG_NAME"` #bad idea for noarch when additional libs get added
# extend build number with a . since the dash is part of PKG_VERSION already
PKG_VERSION="${PKG_VERSION}.${RELEASE}"
export BUILD_APPDIR="$TOPDIR/${PKG_NAME}-${PKG_VERSION}-${PKG_ARCH}"
fi
fi
# fallback for manual compile
if [ -z "$PKG_VERSION" ]; then
# we build from source only
PKG_VERSION="0"
# try to get the version from .obsinfo
if [ -e "${PKG_NAME}.obsinfo" ]; then
PKG_VERSION=`sed -n -e 's,^version: \(.*\),\1,p' "${PKG_NAME}.obsinfo"`
fi
# add a dash before release since PKG_VERSION contains *no* build number
PKG_VERSION="${PKG_VERSION}-${RELEASE}"
export BUILD_APPDIR="$TOPDIR/${PKG_NAME}-${PKG_VERSION}-${PKG_ARCH}"
fi
ZYPPER="zypper --root=$BUILD_APPDIR -n --config $HOME/.pkg2appimage.zypp.conf"
# create zypp.conf
echo "[main]" > $HOME/.pkg2appimage.zypp.conf
echo "rpm.install.excludedocs = yes" >> $HOME/.pkg2appimage.zypp.conf
# prepare AppDir
rm -rf "$BUILD_APPDIR"
mkdir -p "$BUILD_APPDIR"
# package base only
if [ -n "$ZYPPER" ]; then
cp -al /.build.binaries "$BUILD_APPDIR/"
$ZYPPER ar --no-gpgcheck /.build.binaries BUILD
$ZYPPER ref
# rpm only for now
export BUILD_PKG_INSTALL="$ZYPPER install --no-recommends"
# install ingredients
ingredients=$( parse_yaml appimage.yml | sed -n '/^ingredients_packages+=/ s,.*("\(.*\)"),\1,p' )
if [ -n "$ingredients" ]; then
echo "Echo installing ingredients"
$BUILD_PKG_INSTALL $ingredients || exit 1
fi
# deinstall blacklisted
if [ -n "$ZYPPER" ]; then
grep -v ^# /usr/lib/appimagetool/excludesuselist | while read i; do
rpm --root="$BUILD_APPDIR" -q "$i" > /dev/null && rpm --root="$BUILD_APPDIR" -e --noscripts --nodeps "$i" && echo "deinstalled $i"
done
parse_yaml appimage.yml | sed -n '/^ingredients_exclude+=/ s,.*("\(.*\)"),\1,p' | while read i; do
rpm --root="$BUILD_APPDIR" -q "$i" > /dev/null && rpm --root="$BUILD_APPDIR" -e --noscripts --nodeps "$i" && echo "deinstalled $i"
done
fi
rm "$BUILD_APPDIR/etc/ld.so.cache"
fi
#
# build somehow
# OUTDATED Recipe file
#if [ -e "/$BUILD_SOURCE_DIR/Recipe" ]; then
# pushd "/$BUILD_SOURCE_DIR/"
# chmod a+x "Recipe"
# . "./Recipe" appimage.yml
# popd
#else
pushd "$BUILD_APPDIR"
# Execute extra steps defined in appimage.yml
shell_execute $BUILD_SOURCE_DIR/appimage.yml _script
popd
#fi
pushd "$BUILD_APPDIR"
if ! ls -d *.desktop >& /dev/null ; then
echo "No .desktop file found, skipping AppImage creation"
exit 1
fi
# glibc version extension
PKG_VERSION="${PKG_VERSION}.glibc$(glibc_needed)"
# Add the AppRun either way.
#if [ -n "$ZYPPER" ]; then
[ -L AppRun ] && rm -f AppRun
[ -x AppRun ] || cp -a /usr/lib/appimagetool/AppRun .
#fi
DESKTOP=$(find . -name '*.desktop' | sort | head -n 1)
# desktop-file-validate complains about missing trailing semicolons for some
# keys although the format definition says that they are optional
fix_desktop "$DESKTOP"
# ensure to have removed also all files from generic excludelist
delete_blacklisted
popd
#
# create image
#
rm -rf "$BUILD_APPDIR/.build.binaries"
mkdir -p "$TOPDIR/OTHER/"
# in sync with appimagetool string
img="$TOPDIR/OTHER/${PKG_NAME}-${PKG_VERSION}-${PKG_ARCH}.AppImage"
# NOTE: first sed argument is turning http:// to :///, but it gets fixed by the anyway needed // -> /
#
# AppImage lacks a built-in validation of content and relies on SSL.
# We are aware that SSL is not good enough, because every CA or mirror can manipulate data
# but we have nothing better yet. So, enforce https at least...
ZSYNC_URL="$( rpm --eval '%{_download_url}/%{_project}/%{_repository}'|sed -e 's,:,:/,g' -e 's,//,/,g' )"
[ "${ZSYNC_URL:0:5}" == "http:" ] && ZSYNC_URL="https:${ZSYNC_URL#http:}"
ZSYNC_URL="zsync|$ZSYNC_URL/${PKG_NAME}-latest-${PKG_ARCH}.AppImage.zsync"
echo "echo zsync_url: $ZSYNC_URL"
if [ -x /usr/bin/appimagetool ]; then
echo "Use appimagetool"
pushd "$TOPDIR/OTHER/"
PATH=/usr/lib/appimagetool/:$PATH appimagetool -u "$ZSYNC_URL" "$BUILD_APPDIR" "$img" || exit 1
popd
else
MKSQUASHFS=mksquashfs
[ -x /usr/lib/appimagetool/mksquashfs ] && MKSQUASHFS=/usr/lib/appimagetool/mksquashfs
$MKSQUASHFS "$BUILD_APPDIR" "${PKG_NAME}.squashfs" -root-owned -noappend || exit 1
cat /usr/lib/appimagetool/runtime "${PKG_NAME}.squashfs" > "$img" || exit 1
rm "${PKG_NAME}.squashfs"
chmod a+x "$img" || exit 1
zsyncmake "$img" -u "${img##*/}" -o "${img}.zsync" || exit 1
fi
/usr/lib/appimagetool/digest "$img" > "${img}.digest" || exit 1
#
# validate image if linter exists
#
if [ -x /usr/bin/appimagelint ]; then
/usr/bin/appimagelint "$img" || exit 1
fi
exit 0