#!/usr/bin/env bash # Creates Linux ".AppImage" for @PROJECT_NAME_UCASE@ # # Depends: linuxdeployqt # # Notes: Will attempt to fetch linuxdeployqt automatically (x86_64 only) # See Also: https://github.com/probonopd/linuxdeployqt/blob/master/BUILDING.md VERBOSITY=2 # 3=debug LOGFILE="@CMAKE_BINARY_DIR@/appimage.log" APPDIR="@CMAKE_BINARY_DIR@/@PROJECT_NAME_UCASE@.AppDir/" DESKTOPFILE="${APPDIR}usr/share/applications/lmms.desktop" STRIP="" # Don't strip for Debug|RelWithDebInfo builds # shellcheck disable=SC2193 if [[ "@CMAKE_BUILD_TYPE@" == *"Deb"* ]]; then STRIP="-no-strip" fi # Console colors RED="\\x1B[1;31m" GREEN="\\x1B[1;32m" YELLOW="\\x1B[1;33m" PLAIN="\\x1B[0m" function error { echo -e " ${PLAIN}[${RED}error${PLAIN}] ${1}" return 1 } function success { echo -e " ${PLAIN}[${GREEN}success${PLAIN}] ${1}" } function skipped { echo -e " ${PLAIN}[${YELLOW}skipped${PLAIN}] ${1}" } # Exit with error message if any command fails trap "error 'Failed to generate AppImage'; exit 1" ERR # Run a command silently, but print output if it fails function run_and_log { echo -e "\n\n>>>>> $1" >> "$LOGFILE" output="$("$@" 2>&1)" status=$? echo "$output" >> "$LOGFILE" [[ $status != 0 ]] && echo "$output" return $status } # Blindly assume system arch is appimage arch ARCH=$(uname -m) export ARCH # Check for problematic install locations INSTALL=$(echo "@CMAKE_INSTALL_PREFIX@" | sed 's/\/*$//g') if [ "$INSTALL" == "/usr/local" ] || [ "$INSTALL" == "/usr" ] ; then error "Incompatible CMAKE_INSTALL_PREFIX for creating AppImage: @CMAKE_INSTALL_PREFIX@" fi # Ensure linuxdeployqt uses the same qmake version as cmake PATH="$(dirname "@QT_QMAKE_EXECUTABLE@"):$PATH" export PATH # Use linuxdeployqt from env or in PATH [[ $LINUXDEPLOYQT ]] || LINUXDEPLOYQT="$(which linuxdeployqt 2>/dev/null)" || true [[ $APPIMAGETOOL ]] || APPIMAGETOOL="$(which appimagetool 2>/dev/null)" || true # Fetch portable linuxdeployqt if not in PATH if [[ -z $LINUXDEPLOYQT || -z $APPIMAGETOOL ]]; then filename="linuxdeployqt-continuous-$ARCH.AppImage" url="https://github.com/probonopd/linuxdeployqt/releases/download/continuous/$filename" echo " [.......] Downloading: ${url}" wget -N -q "$url" && err=0 || err=$? case "$err" in 0) success "Downloaded $PWD/$filename" ;; # 8 == server issued 4xx error 8) error "Download failed (perhaps no package available for $ARCH)" ;; *) error "Download failed" ;; esac # Extract AppImage and replace LINUXDEPLOYQT variable with extracted binary # to support systems without fuse # Also, we need to set LD_LIBRARY_PATH, but linuxdepoyqt's AppRun unsets it # See https://github.com/probonopd/linuxdeployqt/pull/370/ chmod +x "$filename" ./"$filename" --appimage-extract >/dev/null success "Extracted $filename" # Use the extracted linuxdeployqt and appimagetool PATH="$(pwd -P)/squashfs-root/usr/bin:$PATH" [[ $LINUXDEPLOYQT ]] || LINUXDEPLOYQT="$(which linuxdeployqt)" [[ $APPIMAGETOOL ]] || APPIMAGETOOL="$(which appimagetool)" fi # Make skeleton AppDir echo -e "\nCreating ${APPDIR}..." rm -rf "${APPDIR}" mkdir -p "${APPDIR}usr" success "Created ${APPDIR}" # Clone install to AppDir echo -e "\nCopying @CMAKE_INSTALL_PREFIX@ to ${APPDIR}..." cp -R "@CMAKE_INSTALL_PREFIX@/." "${APPDIR}usr" rm -rf "${APPDIR}usr/include" success "${APPDIR}" # Copy rawwaves directory for stk/mallets mkdir -p "${APPDIR}usr/share/stk/" cp -R /usr/share/stk/rawwaves/ "${APPDIR}usr/share/stk/" # Create a wrapper script which calls the lmms executable mv "${APPDIR}usr/bin/lmms" "${APPDIR}usr/bin/lmms.real" cp "@CMAKE_CURRENT_SOURCE_DIR@/launch_lmms.sh" "${APPDIR}usr/bin/lmms" chmod +x "${APPDIR}usr/bin/lmms" # Per https://github.com/probonopd/linuxdeployqt/issues/129 unset LD_LIBRARY_PATH # Ensure linuxdeployqt can find shared objects export LD_LIBRARY_PATH="${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH" # Move executables so linuxdeployqt can find them ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx" VSTLIB32="${APPDIR}usr/lib/lmms/32/RemoteVstPlugin32.exe.so" VSTLIB64="${APPDIR}usr/lib/lmms/RemoteVstPlugin64.exe.so" ZYNBIN="${APPDIR}usr/bin/RemoteZynAddSubFx" VSTBIN32="${APPDIR}usr/bin/RemoteVstPlugin32.exe.so" VSTBIN64="${APPDIR}usr/bin/RemoteVstPlugin64.exe.so" mv "$ZYNLIB" "$ZYNBIN" mv "$VSTLIB32" "$VSTBIN32" || true mv "$VSTLIB64" "$VSTBIN64" || true # Handle wine linking if [ -d "@WINE_32_LIBRARY_DIR@" ] && \ ldd "$VSTBIN32" | grep "libwine\.so" | grep "not found"; then export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_32_LIBRARY_DIRS@" fi if [ -d "@WINE_64_LIBRARY_DIR@" ] && \ ldd "$VSTBIN64" | grep "libwine\.so" | grep "not found"; then export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_64_LIBRARY_DIRS@" fi # Patch the desktop file sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE" echo "X-AppImage-Version=@VERSION@" >> "$DESKTOPFILE" # Fix linking for soft-linked plugins for file in "${APPDIR}usr/lib/lmms/"*.so; do thisfile="${APPDIR}usr/lib/lmms/${file##*/}" executables="${executables} -executable=$thisfile" done executables="${executables} -executable=${ZYNBIN}" executables="${executables} -executable=${VSTBIN32}" executables="${executables} -executable=${VSTBIN64}" executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imp_1199.so" executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imbeq_1197.so" executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1193.so" executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1194.so" echo -e "\nWriting verbose output to \"${LOGFILE}\"" echo -n > "$LOGFILE" # Bundle both qt and non-qt dependencies into appimage format echo -e "\nBundling and relinking system dependencies..." # shellcheck disable=SC2086 run_and_log "$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP success "Bundled and relinked dependencies" # Link to original location so lmms can find them ln -sr "$ZYNBIN" "$ZYNLIB" ln -sr "$VSTBIN32" "$VSTLIB32" || true ln -sr "$VSTBIN64" "$VSTLIB64" || true # Remove wine library conflict rm -f "${APPDIR}/usr/lib/libwine.so.1" # Use system-provided carla rm -f "${APPDIR}usr/lib/"libcarla*.so rm -f "${APPDIR}usr/lib/lmms/optional/"libcarla*.so # Remove bundled jack in LD_LIBRARY_PATH if exists if [ -e "${APPDIR}/usr/lib/libjack.so.0" ]; then rm "${APPDIR}/usr/lib/libjack.so.0" fi # Bundle jack out of LD_LIBRARY_PATH JACK_LIB=$(ldd "${APPDIR}/usr/bin/lmms.real" | sed -n 's/\tlibjack\.so\.0 => \(.\+\) (0x[0-9a-f]\+)/\1/p') if [ -e "$JACK_LIB" ]; then mkdir -p "${APPDIR}usr/lib/lmms/optional/" cp "$JACK_LIB" "${APPDIR}usr/lib/lmms/optional/" fi # Point the AppRun to the shim launcher rm -f "${APPDIR}/AppRun" ln -sr "${APPDIR}/usr/bin/lmms" "${APPDIR}/AppRun" # Add icon ln -srf "${APPDIR}/lmms.png" "${APPDIR}/.DirIcon" # Create AppImage echo -e "\nFinishing the AppImage..." run_and_log "$APPIMAGETOOL" "${APPDIR}" "@APPIMAGE_FILE@" success "Created @APPIMAGE_FILE@" echo -e "\nFinished"