1#! /bin/sh 2# 3# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org> 4# SPDX-License-Identifier: BSD-2-Clause 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26# POSSIBILITY OF SUCH DAMAGE. 27# 28### END LICENSES 29 30### USAGE 31# 32# Shell script to help build an AppImage for Calamares. 33# 34# Usage: 35# AppImage.sh [-T|--tools-dir <dir>] 36# [-C|--cmake-args <args>] 37# [-c|--config-dir <dir>] 38# [-s|--skip-build] 39# [-p|--with-python] 40# 41# Multiple --cmake-args arguments will be collected together and passed to 42# CMake before building the application. 43# 44# Use --tools-dir to indicate where the linuxdeploy tools are located. 45# 46# Use --config to copy a config-directory (with settings.conf and others) 47# into the resulting image, 48# 49# Option --skip-build assumes that there is an already-built Calamares 50# available in the AppImage build directory; use this when you are, e.g. 51# re-packaging the image with different configuration. Option --with-python 52# adds the Conda Python packaging ecosystem to the AppImage, which will make 53# it **more** portable by disconnecting from the system Python libraries. 54# 55# The build process for AppImage proceeds in a directory build-AppImage 56# that is created in the current directory. 57# 58# The resulting AppImage has XDG_* enabled, and appends the in-image 59# directories to the current environment. You can set XDG_* in the 60# current environment to use other configurations and data, e.g. the 61# data in the current live environment. Or leave it unset, to try 62# Calamares with only the configuration contained in the AppImage. 63# 64### END USAGE 65 66TOOLS_DIR="." 67CMAKE_ARGS="" 68DO_REBUILD="true" 69DO_CONDA="false" 70CONFIG_DIR="" 71while test "$#" -gt 0 72do 73 case "x$1" in 74 x--help|x-h) 75 sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" 76 return 0 77 ;; 78 x--tools-dir|x-T) 79 TOOLS_DIR="$2" 80 shift 81 ;; 82 x--cmake-args|x-C) 83 CMAKE_ARGS="$CMAKE_ARGS $2" 84 shift 85 ;; 86 x--config-dir|x-c) 87 CONFIG_DIR="$2" 88 shift 89 ;; 90 x--skip-build|x-s) 91 DO_REBUILD="false" 92 ;; 93 x--with-python|x-p) 94 DO_CONDA="true" 95 ;; 96 *) 97 echo "! Unknown argument '$1'." 98 exit 1 99 ;; 100 esac 101 test "$#" -gt 0 || { echo "! Missing arguments."; exit 1; } 102 shift 103done 104 105### Check where we're running 106# 107BIN_DIR=$( cd $( dirname "$0" ) && pwd -P ) 108test -d "$BIN_DIR" || { echo "! Could not find BIN_DIR"; exit 1; } 109test -f "$BIN_DIR/AppImage.sh" || { echo "! $BIN_DIR does not have AppImage.sh"; exit 1; } 110 111SRC_DIR=$( cd "$BIN_DIR/.." && pwd -P ) 112test -d "$SRC_DIR" || { echo "! Could not find SRC_DIR"; exit 1; } 113test -d "$SRC_DIR/ci" || { echo "! $SRC_DIR isn't a top-level Calamares checkout"; exit 1; } 114test -f "$SRC_DIR/CMakeLists.txt" || { echo "! SRC_DIR is missing CMakeLists.txt"; exit 1; } 115 116### Check pre-requisites 117# 118BUILD_DIR=build-AppImage 119test -d "$BUILD_DIR" || mkdir -p "$BUILD_DIR" 120test -d "$BUILD_DIR" || { echo "! Could not create $BUILD_DIR"; exit 1; } 121 122TOOLS_LIST="linuxdeploy-x86_64.AppImage linuxdeploy-plugin-qt-x86_64.AppImage" 123$DO_CONDA && TOOLS_LIST="$TOOLS_LIST linuxdeploy-plugin-conda.sh" 124 125for tool in $TOOLS_LIST 126do 127 if test -x "$BUILD_DIR/$tool" ; then 128 # This tool is ok 129 : 130 else 131 if test -f "$TOOLS_DIR/$tool" ; then 132 cp "$TOOLS_DIR/$tool" "$BUILD_DIR/$tool" || exit 1 133 else 134 fetch=$( grep "^# URL .*$tool\$" "$0" | sed 's/# URL *//' ) 135 curl -L -o "$BUILD_DIR/$tool" "$fetch" 136 fi 137 chmod +x "$BUILD_DIR/$tool" 138 test -x "$BUILD_DIR/$tool" || { echo "! Missing tool $tool in tools-dir $TOOLS_DIR"; exit 1; } 139 fi 140done 141 142if test -n "$CONFIG_DIR" ; then 143 test -f "$CONFIG_DIR/settings.conf" || { echo "! No settings.conf in $CONFIG_DIR"; exit 1; } 144fi 145 146### Clean up build-directory 147# 148rm -rf "$BUILD_DIR/AppDir" 149if $DO_REBUILD ; then 150 rm -rf "$BUILD_DIR/build" 151 mkdir "$BUILD_DIR/build" || { echo "! Could not create $BUILD_DIR/build for the cmake-build."; exit 1; } 152else 153 test -d "$BUILD_DIR/build" || { echo "! No build found in $BUILD_DIR, but --skip-build is given."; exit 1; } 154 test -x "$BUILD_DIR/build/calamares" || { echo "! No complete build found in $BUILD_DIR/build ."; exit 1; } 155fi 156mkdir "$BUILD_DIR/AppDir" || { echo "! Could not create $BUILD_DIR/AppDir for the AppImage install."; exit 1; } 157LOG_FILE="$BUILD_DIR/AppImage.log" 158rm -f "$LOG_FILE" 159{ echo "# Calamares build started" `date` ; echo "# .. build directory $BUILD_DIR"; echo "# .. log file $LOG_FILE"; } > "$LOG_FILE" 160cat "$LOG_FILE" 161 162### Python Support 163# 164# 165if $DO_CONDA ; then 166 export CONDA_CHANNELS="conda-forge;anaconda" 167 export CONDA_PACKAGES="gettext;py-boost" 168 169 ( 170 cd "$BUILD_DIR" && 171 ./linuxdeploy-x86_64.AppImage --appdir=AppDir/ --plugin=conda 172 ) 173 174 . "$BUILD_DIR/AppDir/usr/conda/bin/activate" 175fi 176 177### Build Calamares 178# 179if $DO_REBUILD ; then 180 echo "# Running cmake ..." 181 ( 182 cd "$BUILD_DIR/build" && 183 cmake "$SRC_DIR" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib $CMAKE_ARGS 184 ) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run CMake"; exit 1; } 185 echo "# Running make ..." 186 ( 187 cd "$BUILD_DIR/build" && 188 make -j4 189 ) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make"; exit 1; } 190fi 191echo "# Running make install ..." 192( 193 cd "$BUILD_DIR/build" && 194 make install DESTDIR=../AppDir 195) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make install"; exit 1; } 196 197### Modify installation 198# 199IMAGE_DIR="$BUILD_DIR/AppDir" 200 201# Munge the desktop file to not use absolute paths or pkexec 202sed -i \ 203 -e 's+^Exec=.*+Exec=calamares+' \ 204 -e 's+^Name=.*+Name=Calamares+' \ 205 "$IMAGE_DIR"/usr/share/applications/calamares.desktop 206 207# Replace the executable with a shell-proxy 208test -x "$IMAGE_DIR/usr/bin/calamares" || { echo "! Does not seem to have installed calamares"; exit 1; } 209mv "$IMAGE_DIR/usr/bin/calamares" "$IMAGE_DIR/usr/bin/calamares.bin" 210cat > "$IMAGE_DIR/usr/bin/calamares" <<"EOF" 211#! /bin/sh 212# 213# Calamares proxy-script. Runs Calamares with XDG support enabled, 214# and in-image XDG dirs set up so that compiled-in configuration can be used. 215test -n "${XDG_DATA_DIRS}" && XDG_DATA_DIRS="${XDG_DATA_DIRS}:" 216test -n "${XDG_CONFIG_DIRS}" $$ XDG_CONFIG_DIRS="${XDG_CONFIG_DIRS}:" 217export XDG_DATA_DIRS="${XDG_DATA_DIRS}${APPDIR}/usr/share/" 218export XDG_CONFIG_DIRS="${XDG_CONFIG_DIRS}${APPDIR}/etc/:${APPDIR}/usr/share/" 219export PYTHONPATH="${APPDIR}/usr/lib:" 220cd "$APPDIR" 221exec "$APPDIR"/usr/bin/calamares.bin -X "$@" 222EOF 223chmod 755 "$IMAGE_DIR/usr/bin/calamares" 224test -x "$IMAGE_DIR/usr/bin/calamares" || { echo "! Does not seem to have proxy for calamares"; exit 1; } 225 226### Install additional files 227# 228PLUGIN_DIR=$( qmake -query QT_INSTALL_PLUGINS ) 229for plugin in \ 230 libpmsfdiskbackendplugin.so \ 231 libpmdummybackendplugin.so \ 232 libpmlibpartedbackendplugin.so 233do 234 # Warning, but not fatal: generally you only have two out of three available 235 # depending on the KPMCore version. 236 cp "$PLUGIN_DIR/$plugin" "$IMAGE_DIR/usr/lib" 2> /dev/null || { echo "! Could not copy KPMCore plugin $plugin"; } 237done 238 239# Install configuration files 240ETC_DIR="$IMAGE_DIR"/etc/calamares 241mkdir -p "$ETC_DIR" 242test -d "$ETC_DIR" || { echo "! Could not create /etc/calamares in image."; exit 1; } 243 244if test -z "$CONFIG_DIR" ; then 245 echo "# Using basic settings.conf" 246 cp "$SRC_DIR/settings.conf" "$ETC_DIR" 247else 248 test -f "$CONFIG_DIR/settings.conf" || { echo "! No settings.conf in $CONFIG_DIR"; exit 1; } 249 mkdir -p "$ETC_DIR/modules" 250 cp "$CONFIG_DIR/settings.conf" "$ETC_DIR" 251 test -d "$CONFIG_DIR/modules" && cp -r "$CONFIG_DIR/modules" "$ETC_DIR" 252 test -d "$CONFIG_DIR/branding" && cp -r "$CONFIG_DIR/branding" "$IMAGE_DIR/usr/share/calamares" 253fi 254 255### Build the AppImage 256# 257# 258echo "# Building AppImage" 259( 260 export QT_SELECT=qt5 # Otherwise might pick Qt4 in image 261 export LD_LIBRARY_PATH=AppDir/usr/lib # RPATH isn't set in the executable 262 cd "$BUILD_DIR" && 263 ./linuxdeploy-x86_64.AppImage --appdir=AppDir/ --plugin=qt --output=appimage 264) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not create image"; exit 1; } 265 266echo "# Created in $BUILD_DIR/Calamares-x86_64.AppImage" 267echo "# .. log file at $LOG_FILE" 268 269exit 0 270### Database for installation 271# 272# URL https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage 273# URL https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage 274# URL https://raw.githubusercontent.com/TheAssassin/linuxdeploy-plugin-conda/master/linuxdeploy-plugin-conda.sh 275