From 540d27d0c3a80fb31ab9300578eb52b2762796d4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Mar 2019 17:38:44 -0400 Subject: [PATCH 01/10] [libcalamares] Convenience function YAML->QStringList - operator>> already existed, but here's a version that can be used in function-call context. --- src/libcalamares/utils/YamlUtils.cpp | 8 ++++++++ src/libcalamares/utils/YamlUtils.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/libcalamares/utils/YamlUtils.cpp b/src/libcalamares/utils/YamlUtils.cpp index e7eb8fd46..b9b3425e6 100644 --- a/src/libcalamares/utils/YamlUtils.cpp +++ b/src/libcalamares/utils/YamlUtils.cpp @@ -109,6 +109,14 @@ yamlMapToVariant( const YAML::Node& mapNode ) return vm; } +QStringList +yamlToStringList(const YAML::Node& listNode) +{ + QStringList l; + listNode >> l; + return l; +} + void explainYamlException( const YAML::Exception& e, const QByteArray& yamlData, const char *label ) diff --git a/src/libcalamares/utils/YamlUtils.h b/src/libcalamares/utils/YamlUtils.h index 49c8d6613..0fa48e270 100644 --- a/src/libcalamares/utils/YamlUtils.h +++ b/src/libcalamares/utils/YamlUtils.h @@ -32,6 +32,7 @@ class Node; class Exception; } +/// @brief Appends all te elements of @p node to the string list @p v void operator>>( const YAML::Node& node, QStringList& v ); namespace CalamaresUtils @@ -51,6 +52,9 @@ QVariant yamlScalarToVariant( const YAML::Node& scalarNode ); QVariant yamlSequenceToVariant( const YAML::Node& sequenceNode ); QVariant yamlMapToVariant( const YAML::Node& mapNode ); +/// @brief Returns all the elements of @p listNode in a StringList +QStringList yamlToStringList( const YAML::Node& listNode ); + /// @brief Save a @p map to @p filename as YAML bool saveYaml( const QString& filename, const QVariantMap& map ); From e18e4e3d6f70f57ca131cb97c0c2ee8b1d8c0524 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Mar 2019 17:48:39 -0400 Subject: [PATCH 02/10] [libcalamares] Refactor module-search path - Refactor code that fills up the module search path from the *modules-search* configuration key. - Improve debug logging while here. --- src/libcalamares/Settings.cpp | 71 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 3a00399f4..22458fcef 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -74,6 +74,46 @@ Settings::instance() return s_instance; } +static void +interpretModulesSearch( const bool debugMode, const QStringList& rawPaths, QStringList& output ) +{ + for ( const auto& path : rawPaths ) + { + if ( path == "local" ) + { + cDebug() << "module-search local"; + + // If we're running in debug mode, we assume we might also be + // running from the build dir, so we add a maximum priority + // module search path in the build dir. + if ( debugMode ) + { + QString buildDirModules = QDir::current().absolutePath() + + QDir::separator() + "src" + + QDir::separator() + "modules"; + if ( QDir( buildDirModules ).exists() ) + output.append( buildDirModules ); + } + + // Install path is set in CalamaresAddPlugin.cmake + output.append( CalamaresUtils::systemLibDir().absolutePath() + + QDir::separator() + "calamares" + + QDir::separator() + "modules" ); + } + else + { + QDir d( path ); + if ( d.exists() && d.isReadable() ) + { + cDebug() << "module-search exists" << d.absolutePath(); + output.append( d.absolutePath() ); + } + else + cDebug() << "module-search non-existent" << path; + } + } +} + Settings::Settings( const QString& settingsFilePath, bool debugMode, QObject* parent ) @@ -94,36 +134,7 @@ Settings::Settings( const QString& settingsFilePath, YAML::Node config = YAML::Load( ba.constData() ); Q_ASSERT( config.IsMap() ); - QStringList rawPaths; - config[ "modules-search" ] >> rawPaths; - for ( int i = 0; i < rawPaths.length(); ++i ) - { - if ( rawPaths[ i ] == "local" ) - { - // If we're running in debug mode, we assume we might also be - // running from the build dir, so we add a maximum priority - // module search path in the build dir. - if ( debugMode ) - { - QString buildDirModules = QDir::current().absolutePath() + - QDir::separator() + "src" + - QDir::separator() + "modules"; - if ( QDir( buildDirModules ).exists() ) - m_modulesSearchPaths.append( buildDirModules ); - } - - // Install path is set in CalamaresAddPlugin.cmake - m_modulesSearchPaths.append( CalamaresUtils::systemLibDir().absolutePath() + - QDir::separator() + "calamares" + - QDir::separator() + "modules" ); - } - else - { - QDir path( rawPaths[ i ] ); - if ( path.exists() && path.isReadable() ) - m_modulesSearchPaths.append( path.absolutePath() ); - } - } + interpretModulesSearch( debugMode, CalamaresUtils::yamlToStringList( config[ "modules-search" ] ), m_modulesSearchPaths ); // Parse the custom instances section if ( config[ "instances" ] ) From 5a8ed8583f51e7a055b6615839b80eada0205636 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 19 Mar 2019 05:39:53 -0400 Subject: [PATCH 03/10] [libcalamaresui] Complain about missing config files - When no config file is found, tell where it wasn't. --- src/libcalamaresui/modulesystem/Module.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index 20e0517ea..73a026fb9 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -169,7 +169,8 @@ moduleConfigurationCandidates( bool assumeBuildDir, const QString& moduleName, c void Module::loadConfigurationFile( const QString& configFileName ) //throws YAML::Exception { - foreach ( const QString& path, moduleConfigurationCandidates( Settings::instance()->debugMode(), m_name, configFileName ) ) + QStringList configCandidates = moduleConfigurationCandidates( Settings::instance()->debugMode(), m_name, configFileName ); + for ( const QString& path : configCandidates ) { QFile configFile( path ); if ( configFile.exists() && configFile.open( QFile::ReadOnly | QFile::Text ) ) @@ -198,6 +199,7 @@ Module::loadConfigurationFile( const QString& configFileName ) //throws YAML::Ex return; } } + cDebug() << "No config file found in" << Logger::DebugList( configCandidates ); } From 7515f36b9629bd872a1429ef4fc1f218b4c7e928 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 19 Mar 2019 05:57:33 -0400 Subject: [PATCH 04/10] [libcalamares] Refactor settings-loading some more - Load instances list in a separate method - Load sequence list in a separate method - Don't rely on QASSERT, explicitly throw if something is missing. --- src/libcalamares/Settings.cpp | 124 +++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 22458fcef..9bedbbe41 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -114,6 +114,72 @@ interpretModulesSearch( const bool debugMode, const QStringList& rawPaths, QStri } } +static void +interpretInstances( const YAML::Node& node, Settings::InstanceDescriptionList& customInstances ) +{ + // Parse the custom instances section + if ( node ) + { + QVariant instancesV = CalamaresUtils::yamlToVariant( node ).toList(); + if ( instancesV.type() == QVariant::List ) + { + const auto instances = instancesV.toList(); + for ( const QVariant& instancesVListItem : instances ) + { + if ( instancesVListItem.type() != QVariant::Map ) + continue; + QVariantMap instancesVListItemMap = + instancesVListItem.toMap(); + Settings::InstanceDescription instanceMap; + for ( auto it = instancesVListItemMap.constBegin(); + it != instancesVListItemMap.constEnd(); ++it ) + { + if ( it.value().type() != QVariant::String ) + continue; + instanceMap.insert( it.key(), it.value().toString() ); + } + customInstances.append( instanceMap ); + } + } + } +} + +static void +interpretSequence( const YAML::Node& node, Settings::ModuleSequence& moduleSequence ) +{ + // Parse the modules sequence section + if ( node ) + { + QVariant sequenceV = CalamaresUtils::yamlToVariant( node ); + if ( !( sequenceV.type() == QVariant::List ) ) + throw YAML::Exception( YAML::Mark(), "sequence key does not have a list-value" ); + + const auto sequence = sequenceV.toList(); + for ( const QVariant& sequenceVListItem : sequence ) + { + if ( sequenceVListItem.type() != QVariant::Map ) + continue; + QString thisActionS = sequenceVListItem.toMap().firstKey(); + ModuleAction thisAction; + if ( thisActionS == "show" ) + thisAction = ModuleAction::Show; + else if ( thisActionS == "exec" ) + thisAction = ModuleAction::Exec; + else + continue; + + QStringList thisActionRoster = sequenceVListItem + .toMap() + .value( thisActionS ) + .toStringList(); + moduleSequence.append( qMakePair( thisAction, + thisActionRoster ) ); + } + } + else + throw YAML::Exception( YAML::Mark(), "sequence key is missing" ); +} + Settings::Settings( const QString& settingsFilePath, bool debugMode, QObject* parent ) @@ -135,62 +201,8 @@ Settings::Settings( const QString& settingsFilePath, Q_ASSERT( config.IsMap() ); interpretModulesSearch( debugMode, CalamaresUtils::yamlToStringList( config[ "modules-search" ] ), m_modulesSearchPaths ); - - // Parse the custom instances section - if ( config[ "instances" ] ) - { - QVariant instancesV - = CalamaresUtils::yamlToVariant( config[ "instances" ] ).toList(); - if ( instancesV.type() == QVariant::List ) - { - const auto instances = instancesV.toList(); - for ( const QVariant& instancesVListItem : instances ) - { - if ( instancesVListItem.type() != QVariant::Map ) - continue; - QVariantMap instancesVListItemMap = - instancesVListItem.toMap(); - QMap< QString, QString > instanceMap; - for ( auto it = instancesVListItemMap.constBegin(); - it != instancesVListItemMap.constEnd(); ++it ) - { - if ( it.value().type() != QVariant::String ) - continue; - instanceMap.insert( it.key(), it.value().toString() ); - } - m_customModuleInstances.append( instanceMap ); - } - } - } - - // Parse the modules sequence section - Q_ASSERT( config[ "sequence" ] ); // It better exist! - { - QVariant sequenceV - = CalamaresUtils::yamlToVariant( config[ "sequence" ] ); - Q_ASSERT( sequenceV.type() == QVariant::List ); - const auto sequence = sequenceV.toList(); - for ( const QVariant& sequenceVListItem : sequence ) - { - if ( sequenceVListItem.type() != QVariant::Map ) - continue; - QString thisActionS = sequenceVListItem.toMap().firstKey(); - ModuleAction thisAction; - if ( thisActionS == "show" ) - thisAction = ModuleAction::Show; - else if ( thisActionS == "exec" ) - thisAction = ModuleAction::Exec; - else - continue; - - QStringList thisActionRoster = sequenceVListItem - .toMap() - .value( thisActionS ) - .toStringList(); - m_modulesSequence.append( qMakePair( thisAction, - thisActionRoster ) ); - } - } + interpretInstances( config[ "instances" ], m_customModuleInstances ); + interpretSequence( config[ "sequence" ], m_modulesSequence ); m_brandingComponentName = requireString( config, "branding" ); m_promptInstall = requireBool( config, "prompt-install", false ); From 5f308e8e17ee1d225e8b4d0ca1a5500e6bb0fc3c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 19 Mar 2019 06:15:11 -0400 Subject: [PATCH 05/10] [calamares] Check that a sequence has been set --- src/calamares/CalamaresApplication.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index c9a171fd2..989290567 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -263,7 +263,12 @@ CalamaresApplication::initSettings() ::exit( EXIT_FAILURE ); } - new Calamares::Settings( settingsFile.absoluteFilePath(), isDebug(), this ); + auto* settings = new Calamares::Settings( settingsFile.absoluteFilePath(), isDebug(), this ); // Creates singleton + if ( settings->modulesSequence().count() < 1 ) + { + cError() << "FATAL: no sequence set."; + ::exit( EXIT_FAILURE ); + } } From 2b7832857c0dbedd3369e336c23330992e12e348 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 19 Mar 2019 09:59:39 -0400 Subject: [PATCH 06/10] [libcalamaresui] Simplify checking dependencies - Avoid crash due to invalid iterator, when modules are removed due to missing requirements. - Simplify code, factor out the determination of which required modules are missing. --- .../modulesystem/ModuleManager.cpp | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index d3705729c..b8dbc4ded 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -325,36 +325,47 @@ ModuleManager::checkRequirements() QTimer::singleShot( 0, rq, &RequirementsChecker::run ); } +static QStringList +missingRequiredModules( const QStringList& required, const QMap< QString, QVariantMap >& available ) +{ + QStringList l; + for( const QString& depName : required ) + { + if ( !available.contains( depName ) ) + l.append( depName ); + } + + return l; +} + QStringList ModuleManager::checkDependencies() { QStringList failed; + bool somethingWasRemovedBecauseOfUnmetDependencies = false; // This goes through the map of available modules, and deletes those whose // dependencies are not met, if any. - forever + do { - bool somethingWasRemovedBecauseOfUnmetDependencies = false; + somethingWasRemovedBecauseOfUnmetDependencies = false; for ( auto it = m_availableDescriptorsByModuleName.begin(); it != m_availableDescriptorsByModuleName.end(); ++it ) { - foreach ( const QString& depName, - it->value( "requiredModules" ).toStringList() ) + QStringList unmet = missingRequiredModules( it->value( "requiredModules" ).toStringList(), m_availableDescriptorsByModuleName ); + + if ( unmet.count() > 0 ) { - if ( !m_availableDescriptorsByModuleName.contains( depName ) ) - { - QString moduleName = it->value( "name" ).toString(); - somethingWasRemovedBecauseOfUnmetDependencies = true; - m_availableDescriptorsByModuleName.erase( it ); - failed << moduleName; - cWarning() << "Module" << moduleName << "has unknown requirement" << depName; - break; - } + QString moduleName = it->value( "name" ).toString(); + somethingWasRemovedBecauseOfUnmetDependencies = true; + m_availableDescriptorsByModuleName.erase( it ); + failed << moduleName; + cWarning() << "Module" << moduleName << "has unknown requirements" << Logger::DebugList( unmet ); + break; } } - if ( !somethingWasRemovedBecauseOfUnmetDependencies ) - break; } + while( somethingWasRemovedBecauseOfUnmetDependencies ); return failed; } From ed2f9b744d57f946e3bd257beaa275c74bcd2755 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Mar 2019 18:50:17 -0400 Subject: [PATCH 07/10] CI: AppImage support - Add a script for building a Calamares AppImage file (this is useful in *some* limited contexts, not a general way to distribute Calamares since it's much more efficient to use installed libs). - Add example config files for this AppImage build. - Download the linuxdeploy tools if they are missing - Document script flags some more --- ci/AppImage.md | 45 ++++ ci/AppImage.sh | 227 ++++++++++++++++++ .../branding/default/squid.png | Bin 0 -> 10796 bytes .../modules/displaymanager.conf | 28 +++ data/config-appimage/modules/finished.conf | 21 ++ data/config-appimage/modules/keyboard.conf | 16 ++ data/config-appimage/modules/locale.conf | 31 +++ data/config-appimage/modules/users.conf | 62 +++++ data/config-appimage/modules/welcome.conf | 46 ++++ data/config-appimage/settings.conf | 35 +++ 10 files changed, 511 insertions(+) create mode 100644 ci/AppImage.md create mode 100644 ci/AppImage.sh create mode 100644 data/config-appimage/branding/default/squid.png create mode 100644 data/config-appimage/modules/displaymanager.conf create mode 100644 data/config-appimage/modules/finished.conf create mode 100644 data/config-appimage/modules/keyboard.conf create mode 100644 data/config-appimage/modules/locale.conf create mode 100644 data/config-appimage/modules/users.conf create mode 100644 data/config-appimage/modules/welcome.conf create mode 100644 data/config-appimage/settings.conf diff --git a/ci/AppImage.md b/ci/AppImage.md new file mode 100644 index 000000000..7fa51a8bc --- /dev/null +++ b/ci/AppImage.md @@ -0,0 +1,45 @@ +# AppImage building for Calamares + +> It is possible to build Calamares as an AppImage (perhaps other +> containerized formats as well). This might make sense for +> OEM phase-1 deployments in environments where Calamares is +> not using the native toolkit. + +## AppImage tools + +You will need + - [`linuxdeploy-x86_64.AppImage`](https://github.com/linuxdeploy/linuxdeploy/releases) + - [`linuxdeploy-plugin-qt-x86_64.AppImage`](https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases) + - [`linuxdeploy-plugin-conda.sh`](https://github.com/linuxdeploy/linuxdeploy-plugin-conda) + +These tools should run -- they are bundled as AppImages after all -- on +any modern Linux system. The [AppImage packaging documentation](https://docs.appimage.org/packaging-guide/) +explains how the whole tooling works. + +If the tools are not present, the build script (see below) will download them, +but you should save them for later. + +## AppImage build + +From the **source** directory, run `ci/AppImage.sh`: + - Use `--tools-dir` to copy the tools from a local cache rather than + downloading them again. + - Run it with `--cmake-args` for special CMake handling. + - Use `--skip-build` to avoid rebuilding Calamares all the time. + - Use `--config-dir` to copy in Calamares configuration files (e.g. + *settings.conf* and the module configuration files) from a given + directory. + +The build process will: + - copy (or download) the AppImage tools into a fresh build directory + - configure and build Calamares with suitable settings + - modifies the standard `.desktop` file to be AppImage-compatible + - builds the image with the AppImage tools + +## AppImage caveats + +The resulting AppImage, `Calamares-x86_64.AppImage`, can be run as if it is +a regular Calamares executable. For internal reasons it always passes the +`-X` flag; any other command-line flags are passed in unchanged. Internally, +`XDG_*_DIRS` are used to get Calamares to find the resources inside the AppImage +rather than in the host system. diff --git a/ci/AppImage.sh b/ci/AppImage.sh new file mode 100644 index 000000000..7dccc4d89 --- /dev/null +++ b/ci/AppImage.sh @@ -0,0 +1,227 @@ +#! /bin/sh +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright 2019 Adriaan de Groot +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +### END LICENSES + +### USAGE +# +# Shell script to help build an AppImage for Calamares. +# +# Usage: +# AppImage.sh [-T|--tools-dir ] +# [-C|--cmake-args ] +# [-c|--config-dir ] +# [-s|--skip-build] +# +# Multiple --cmake-args arguments will be collected together and passed to +# CMake before building the application. +# +# Use --tools-dir to indicate where the linuxdeploy tools are located. +# +# Use --config to copy a config-directory (with settings.conf and others) +# into the resulting image, +# +### END USAGE + +TOOLS_DIR="." +CMAKE_ARGS="" +NO_SKIP_BUILD="true" +CONFIG_DIR="" +while test "$#" -gt 0 +do + case "x$1" in + x--help|x-h) + sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" + return 0 + ;; + x--tools-dir|x-T) + TOOLS_DIR="$2" + shift + ;; + x--cmake-args|x-C) + CMAKE_ARGS="$CMAKE_ARGS $2" + shift + ;; + x--config-dir|x-c) + CONFIG_DIR="$2" + shift + ;; + x--skip-build|x-s) + NO_SKIP_BUILD="false" + ;; + *) + echo "! Unknown argument '$1'." + exit 1 + ;; + esac + test "$#" -gt 0 || { echo "! Missing arguments."; exit 1; } + shift +done + +### Check where we're running +# +BIN_DIR=$( cd $( dirname "$0" ) && pwd -P ) +test -d "$BIN_DIR" || { echo "! Could not find BIN_DIR"; exit 1; } +test -f "$BIN_DIR/AppImage.sh" || { echo "! $BIN_DIR does not have AppImage.sh"; exit 1; } + +SRC_DIR=$( cd "$BIN_DIR/.." && pwd -P ) +test -d "$SRC_DIR" || { echo "! Could not find SRC_DIR"; exit 1; } +test -d "$SRC_DIR/ci" || { echo "! $SRC_DIR isn't a top-level Calamares checkout"; exit 1; } +test -f "$SRC_DIR/CMakeLists.txt" || { echo "! SRC_DIR is missing CMakeLists.txt"; exit 1; } + +### Check pre-requisites +# +BUILD_DIR=build-AppImage +test -d "$BUILD_DIR" || mkdir -p "$BUILD_DIR" +test -d "$BUILD_DIR" || { echo "! Could not create $BUILD_DIR"; exit 1; } + +for tool in linuxdeploy-x86_64.AppImage linuxdeploy-plugin-qt-x86_64.AppImage linuxdeploy-plugin-conda.sh +do + if test -x "$BUILD_DIR/$tool" ; then + # This tool is ok + : + else + if test -f "$TOOLS_DIR/$tool" ; then + cp "$TOOLS_DIR/$tool" "$BUILD_DIR/$tool" || exit 1 + else + fetch=$( grep "^# URL .*$tool\$" "$0" | sed 's/# URL *//' ) + curl -L -o "$BUILD_DIR/$tool" "$fetch" + fi + chmod +x "$BUILD_DIR/$tool" + test -x "$BUILD_DIR/$tool" || { echo "! Missing tool $tool in tools-dir $TOOLS_DIR"; exit 1; } + fi +done + +if test -z "$CONFIG_DIR" ; then + echo "# Using basic settings.conf" +else + test -f "$CONFIG_DIR/settings.conf" || { echo "! No settings.conf in $CONFIG_DIR"; exit 1; } +fi + +### Clean up build-directory +# +rm -rf "$BUILD_DIR/AppDir" +if $NO_SKIP_BUILD ; then + rm -rf "$BUILD_DIR/build" + mkdir "$BUILD_DIR/build" || { echo "! Could not create $BUILD_DIR/build for the cmake-build."; exit 1; } +else + test -d "$BUILD_DIR/build" || { echo "! No build found in $BUILD_DIR, but --skip-build is given."; exit 1; } + test -x "$BUILD_DIR/build/calamares" || { echo "! No complete build found in $BUILD_DIR/build ."; exit 1; } +fi +mkdir "$BUILD_DIR/AppDir" || { echo "! Could not create $BUILD_DIR/AppDir for the AppImage install."; exit 1; } +LOG_FILE="$BUILD_DIR/AppImage.log" +rm -f "$LOG_FILE" + +### Build Calamares +# +if $NO_SKIP_BUILD ; then + echo "# Running cmake ..." + ( + cd "$BUILD_DIR/build" && + cmake "$SRC_DIR" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib $CMAKE_ARGS + ) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run CMake"; exit 1; } + echo "# Running make ..." + ( + cd "$BUILD_DIR/build" && + make -j4 + ) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make"; exit 1; } +fi +echo "# Running make install ..." +( + cd "$BUILD_DIR/build" && + make install DESTDIR=../AppDir +) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make install"; exit 1; } + +### Modify installation +# +IMAGE_DIR="$BUILD_DIR/AppDir" + +# Munge the desktop file to not use absolute paths or pkexec +sed -i \ + -e 's+^Exec=.*+Exec=calamares+' \ + -e 's+^Name=.*+Name=Calamares+' \ + "$IMAGE_DIR"/usr/share/applications/calamares.desktop + +# Replace the executable with a shell-proxy +test -x "$IMAGE_DIR/usr/bin/calamares" || { echo "! Does not seem to have installed calamares"; exit 1; } +mv "$IMAGE_DIR/usr/bin/calamares" "$IMAGE_DIR/usr/bin/calamares.bin" +cat > "$IMAGE_DIR/usr/bin/calamares" <<"EOF" +#! /bin/sh +# +# Calamares proxy-script +export XDG_DATA_DIRS="$APPDIR/usr/share/calamares:" +export XDG_CONFIG_DIRS="$APPDIR/etc/calamares:$D/usr/share:" +cd "$APPDIR" +exec "$APPDIR"/usr/bin/calamares.bin -X "$@" +EOF +chmod 755 "$IMAGE_DIR/usr/bin/calamares" +test -x "$IMAGE_DIR/usr/bin/calamares" || { echo "! Does not seem to have proxy for calamares"; exit 1; } + +### Install additional files +# +PLUGIN_DIR=$( qmake -query QT_INSTALL_PLUGINS ) +for plugin in \ + libpmsfdiskbackendplugin.so \ + libpmdummybackendplugin.so +do + cp "$PLUGIN_DIR/$plugin" "$IMAGE_DIR/usr/lib" || { echo "! Could not copy plugin $plugin"; exit 1; } +done + +# Install configuration files +ETC_DIR="$IMAGE_DIR"/etc/calamares +mkdir -p "$ETC_DIR" +test -d "$ETC_DIR" || { echo "! Could not create /etc/calamares in image."; exit 1; } + +if test -z "$CONFIG_DIR" ; then + echo "# Using basic settings.conf" + cp "$SRC_DIR/settings.conf" "$ETC_DIR" +else + test -f "$CONFIG_DIR/settings.conf" || { echo "! No settings.conf in $CONFIG_DIR"; exit 1; } + mkdir -p "$ETC_DIR/modules" + cp "$CONFIG_DIR/settings.conf" "$ETC_DIR" + test -d "$CONFIG_DIR/modules" && cp -r "$CONFIG_DIR/modules" "$ETC_DIR" + test -d "$CONFIG_DIR/branding" && cp -r "$CONFIG_DIR/branding" "$IMAGE_DIR/usr/share/calamares" +fi + +### Build the AppImage +# +# +echo "# Building AppImage" +( + export QT_SELECT=qt5 # Otherwise might pick Qt4 in image + export LD_LIBRARY_PATH=AppDir/usr/lib # RPATH isn't set in the executable + cd "$BUILD_DIR" && + ./linuxdeploy-x86_64.AppImage --appdir=AppDir/ --plugin=qt --output=appimage +) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not create image"; exit 1; } + +exit 0 +### Database for installation +# +# URL https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage +# URL https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage +# URL https://raw.githubusercontent.com/TheAssassin/linuxdeploy-plugin-conda/master/linuxdeploy-plugin-conda.sh diff --git a/data/config-appimage/branding/default/squid.png b/data/config-appimage/branding/default/squid.png new file mode 100644 index 0000000000000000000000000000000000000000..dbe615c18a3c5e55837fb5fb35ab04cb5180cd37 GIT binary patch literal 10796 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 Date: Tue, 19 Mar 2019 11:33:58 -0400 Subject: [PATCH 08/10] CI: Fix Python modules in AppImage - set PYTHONPATH inside the AppImage so libcalamares is found - add Python module to the sample configuration - relax password requirements (while we're at it) --- ci/AppImage.sh | 1 + data/config-appimage/modules/users.conf | 3 --- data/config-appimage/settings.conf | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ci/AppImage.sh b/ci/AppImage.sh index 7dccc4d89..e22309f12 100644 --- a/ci/AppImage.sh +++ b/ci/AppImage.sh @@ -176,6 +176,7 @@ cat > "$IMAGE_DIR/usr/bin/calamares" <<"EOF" # Calamares proxy-script export XDG_DATA_DIRS="$APPDIR/usr/share/calamares:" export XDG_CONFIG_DIRS="$APPDIR/etc/calamares:$D/usr/share:" +export PYTHONPATH=$APPDIR/usr/lib: cd "$APPDIR" exec "$APPDIR"/usr/bin/calamares.bin -X "$@" EOF diff --git a/data/config-appimage/modules/users.conf b/data/config-appimage/modules/users.conf index 64b3aac43..bdf812878 100644 --- a/data/config-appimage/modules/users.conf +++ b/data/config-appimage/modules/users.conf @@ -55,8 +55,5 @@ doReusePassword: true passwordRequirements: minLength: -1 # Password at least this many characters maxLength: -1 # Password at most this many characters - libpwquality: - - minlen=0 - - minclass=0 userShell: /bin/bash diff --git a/data/config-appimage/settings.conf b/data/config-appimage/settings.conf index 54026cd6e..756710492 100644 --- a/data/config-appimage/settings.conf +++ b/data/config-appimage/settings.conf @@ -19,6 +19,7 @@ sequence: - users - summary - exec: + - dummypython - locale - keyboard - users From 6b40f1f01b1d2f4e94916d1ec9c81d0f9b9ae810 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 20 Mar 2019 10:08:55 +0100 Subject: [PATCH 09/10] CI: AppImage with Conda - Prepare for using Conda for the Python environment in the AppImage. This does not actually work, because the Python support in Calamares doesn't find the alternative environment. - Also log everything, rather than re-starting the log with each build step. --- ci/AppImage.sh | 53 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/ci/AppImage.sh b/ci/AppImage.sh index e22309f12..348784755 100644 --- a/ci/AppImage.sh +++ b/ci/AppImage.sh @@ -37,6 +37,7 @@ # [-C|--cmake-args ] # [-c|--config-dir ] # [-s|--skip-build] +# [-p|--with-python] # # Multiple --cmake-args arguments will be collected together and passed to # CMake before building the application. @@ -46,11 +47,23 @@ # Use --config to copy a config-directory (with settings.conf and others) # into the resulting image, # +# Option --skip-build assumes that there is an already-built Calamares +# available in the AppImage build directory; use this when you are, e.g. +# re-packaging the image with different configuration. Option --with-python +# adds the Conda Python packaging ecosystem to the AppImage, which will make +# it **more** portable by disconnecting from the system Python libraries. +# +# The build process for AppImage proceeds in a directory build-AppImage +# that is created in the current directory. +# +# TODO: Conda / Python support doesn't work yet. +# ### END USAGE TOOLS_DIR="." CMAKE_ARGS="" -NO_SKIP_BUILD="true" +DO_REBUILD="true" +DO_CONDA="false" CONFIG_DIR="" while test "$#" -gt 0 do @@ -72,7 +85,10 @@ do shift ;; x--skip-build|x-s) - NO_SKIP_BUILD="false" + DO_REBUILD="false" + ;; + x--with-python|x-p) + DO_CONDA="true" ;; *) echo "! Unknown argument '$1'." @@ -100,7 +116,10 @@ BUILD_DIR=build-AppImage test -d "$BUILD_DIR" || mkdir -p "$BUILD_DIR" test -d "$BUILD_DIR" || { echo "! Could not create $BUILD_DIR"; exit 1; } -for tool in linuxdeploy-x86_64.AppImage linuxdeploy-plugin-qt-x86_64.AppImage linuxdeploy-plugin-conda.sh +TOOLS_LIST="linuxdeploy-x86_64.AppImage linuxdeploy-plugin-qt-x86_64.AppImage" +$DO_CONDA && TOOLS_LIST="$TOOLS_LIST linuxdeploy-plugin-conda.sh" + +for tool in $TOOLS_LIST do if test -x "$BUILD_DIR/$tool" ; then # This tool is ok @@ -126,7 +145,7 @@ fi ### Clean up build-directory # rm -rf "$BUILD_DIR/AppDir" -if $NO_SKIP_BUILD ; then +if $DO_REBUILD ; then rm -rf "$BUILD_DIR/build" mkdir "$BUILD_DIR/build" || { echo "! Could not create $BUILD_DIR/build for the cmake-build."; exit 1; } else @@ -136,26 +155,42 @@ fi mkdir "$BUILD_DIR/AppDir" || { echo "! Could not create $BUILD_DIR/AppDir for the AppImage install."; exit 1; } LOG_FILE="$BUILD_DIR/AppImage.log" rm -f "$LOG_FILE" +echo "# Calamares build started" `date` > "$LOG_FILE" + +### Python Support +# +# +if $DO_CONDA ; then + export CONDA_CHANNELS="conda-forge;anaconda" + export CONDA_PACKAGES="gettext;py-boost" + + ( + cd "$BUILD_DIR" && + ./linuxdeploy-x86_64.AppImage --appdir=AppDir/ --plugin=conda + ) + + . "$BUILD_DIR/AppDir/usr/conda/bin/activate" +fi ### Build Calamares # -if $NO_SKIP_BUILD ; then +if $DO_REBUILD ; then echo "# Running cmake ..." ( cd "$BUILD_DIR/build" && cmake "$SRC_DIR" -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib $CMAKE_ARGS - ) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run CMake"; exit 1; } + ) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run CMake"; exit 1; } echo "# Running make ..." ( cd "$BUILD_DIR/build" && make -j4 - ) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make"; exit 1; } + ) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make"; exit 1; } fi echo "# Running make install ..." ( cd "$BUILD_DIR/build" && make install DESTDIR=../AppDir -) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make install"; exit 1; } +) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not run make install"; exit 1; } ### Modify installation # @@ -218,7 +253,7 @@ echo "# Building AppImage" export LD_LIBRARY_PATH=AppDir/usr/lib # RPATH isn't set in the executable cd "$BUILD_DIR" && ./linuxdeploy-x86_64.AppImage --appdir=AppDir/ --plugin=qt --output=appimage -) > "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not create image"; exit 1; } +) >> "$LOG_FILE" 2>&1 || { tail -10 "$LOG_FILE" ; echo "! Could not create image"; exit 1; } exit 0 ### Database for installation From 95875c1aabe858f6e608d75b7cd7b8b4863ecf32 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 20 Mar 2019 10:51:24 +0100 Subject: [PATCH 10/10] Changes: document AppImage building --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 232a348ca..fb34dc9d6 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,10 @@ This release contains contributions from (alphabetically by first name): requirements checks in the welcome module (RAM, disk space, ..). The checks have been made asynchronous, so that responsiveness during requirements-checking is improved and the user has better feedback. + * Support for building an AppImage of Calamares has been added to the + `ci/` directory. There are use-cases where a containerized build and + configuration make sense rather than having Calamares installed in the + host system. (Thanks to the AppImage team, Alexis) ## Modules ##