mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-13 09:47:50 -06:00
Add AppImage builder configs and scripts
Added the configuration file `AppImageBuilder.yml.jinja`, the Python script `create_appimage.py`, and the shell script `entrypoint.sh.jinja` for AppImage building and packaging. These additions would enable the Cura application to be built into a single, standalone, executables file for Linux users, improving software deployment and distribution. Contributes CURA-10951
This commit is contained in:
parent
7fbd716bb4
commit
b5fbcce33f
3 changed files with 197 additions and 0 deletions
90
packaging/AppImage-builder/AppImageBuilder.yml.jinja
Normal file
90
packaging/AppImage-builder/AppImageBuilder.yml.jinja
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
AppDir:
|
||||||
|
path: {{ app_dir }}
|
||||||
|
app_info:
|
||||||
|
id: com.ultimaker.cura
|
||||||
|
name: UltiMaker-Cura
|
||||||
|
icon: {{ icon }}
|
||||||
|
version: {{ version }}
|
||||||
|
exec: entrypoint.sh
|
||||||
|
exec_args: $@
|
||||||
|
apt:
|
||||||
|
arch:
|
||||||
|
- amd64
|
||||||
|
allow_unauthenticated: true
|
||||||
|
sources:
|
||||||
|
- sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy main restricted
|
||||||
|
- sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
|
||||||
|
- sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy universe
|
||||||
|
- sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-updates universe
|
||||||
|
- sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy multiverse
|
||||||
|
- sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
|
||||||
|
- sourceline: deb http://nl.archive.ubuntu.com/ubuntu/ jammy-backports main restricted
|
||||||
|
universe multiverse
|
||||||
|
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security main restricted
|
||||||
|
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe
|
||||||
|
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse
|
||||||
|
- sourceline: deb https://releases.jfrog.io/artifactory/jfrog-debs xenial contrib
|
||||||
|
- sourceline: deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-14 main
|
||||||
|
- sourceline: deb https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu/
|
||||||
|
jammy main
|
||||||
|
- sourceline: deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu/ jammy
|
||||||
|
main
|
||||||
|
- sourceline: deb [arch=amd64] https://packages.microsoft.com/repos/ms-teams stable
|
||||||
|
main
|
||||||
|
- sourceline: deb https://ppa.launchpadcontent.net/ppa-verse/cling/ubuntu/ jammy
|
||||||
|
main
|
||||||
|
- sourceline: deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable
|
||||||
|
main
|
||||||
|
- sourceline: deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_14.x
|
||||||
|
jammy main
|
||||||
|
- sourceline: deb [arch=amd64 signed-by=/usr/share/keyrings/transip-stack.gpg]
|
||||||
|
https://mirror.transip.net/stack/software/deb/Ubuntu_22.04/ ./
|
||||||
|
- sourceline: deb http://repository.spotify.com stable non-free
|
||||||
|
- sourceline: deb [arch=amd64,arm64,armhf] http://packages.microsoft.com/repos/code
|
||||||
|
stable main
|
||||||
|
- sourceline: deb https://packagecloud.io/slacktechnologies/slack/debian/ jessie
|
||||||
|
main
|
||||||
|
include:
|
||||||
|
- libc6:amd64
|
||||||
|
- xdg-desktop-portal-kde:amd64
|
||||||
|
files:
|
||||||
|
include: []
|
||||||
|
exclude:
|
||||||
|
- usr/share/man
|
||||||
|
- usr/share/doc/*/README.*
|
||||||
|
- usr/share/doc/*/changelog.*
|
||||||
|
- usr/share/doc/*/NEWS.*
|
||||||
|
- usr/share/doc/*/TODO.*
|
||||||
|
runtime:
|
||||||
|
env:
|
||||||
|
PYTHONPATH: "$APPDIR"
|
||||||
|
QT_PLUGIN_PATH: "$APPDIR/qt/plugins"
|
||||||
|
QML2_IMPORT_PATH: "$APPDIR/qt/qml"
|
||||||
|
QT_QPA_PLATFORMTHEME: xdgdesktopportal
|
||||||
|
test:
|
||||||
|
fedora-30:
|
||||||
|
image: appimagecrafters/tests-env:fedora-30
|
||||||
|
command: ./AppRun
|
||||||
|
use_host_x: True
|
||||||
|
debian-stable:
|
||||||
|
image: appimagecrafters/tests-env:debian-stable
|
||||||
|
command: ./AppRun
|
||||||
|
use_host_x: True
|
||||||
|
archlinux-latest:
|
||||||
|
image: appimagecrafters/tests-env:archlinux-latest
|
||||||
|
command: ./AppRun
|
||||||
|
use_host_x: True
|
||||||
|
centos-7:
|
||||||
|
image: appimagecrafters/tests-env:centos-7
|
||||||
|
command: ./AppRun
|
||||||
|
use_host_x: True
|
||||||
|
ubuntu-xenial:
|
||||||
|
image: appimagecrafters/tests-env:ubuntu-xenial
|
||||||
|
command: ./AppRun
|
||||||
|
use_host_x: True
|
||||||
|
AppImage:
|
||||||
|
arch: {{ arch }}
|
||||||
|
file_name: {{ file_name }}
|
||||||
|
update-information: guess
|
99
packaging/AppImage-builder/create_appimage.py
Normal file
99
packaging/AppImage-builder/create_appimage.py
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
# Copyright (c) 2023 UltiMaker
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
|
|
||||||
|
import argparse # Command line arguments parsing and help.
|
||||||
|
from jinja2 import Template
|
||||||
|
import os # Finding installation directory.
|
||||||
|
import os.path # Finding files.
|
||||||
|
import shutil # Copying files.
|
||||||
|
import stat # For setting file permissions.
|
||||||
|
import subprocess # For calling system commands.
|
||||||
|
|
||||||
|
def build_appimage(dist_path, version, appimage_filename):
|
||||||
|
"""
|
||||||
|
Creates an AppImage file from the build artefacts created so far.
|
||||||
|
"""
|
||||||
|
generate_appimage_builder_config(dist_path, version, appimage_filename)
|
||||||
|
generate_appimage_entrypoint(dist_path)
|
||||||
|
copy_files(dist_path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.remove(os.path.join(dist_path, appimage_filename)) # Ensure any old file is removed, if it exists.
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass # If it didn't exist, that's even better.
|
||||||
|
create_appimage(dist_path, appimage_filename)
|
||||||
|
sign_appimage(dist_path, appimage_filename)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_appimage_builder_config(dist_path, version, appimage_filename):
|
||||||
|
with open(os.path.join(dist_path, "AppImageBuilder.yml.jinja"), "r") as appimage_builder_file:
|
||||||
|
appimage_builder = appimage_builder_file.read()
|
||||||
|
|
||||||
|
template = Template(appimage_builder)
|
||||||
|
appimage_builder = template.render(app_dir = dist_path,
|
||||||
|
icon = os.path.join("..", "icons", "cura-icon_256x256.png"),
|
||||||
|
version = version,
|
||||||
|
arch = "x86_64",
|
||||||
|
file_name = appimage_filename)
|
||||||
|
|
||||||
|
with open(os.path.join(dist_path, "AppImageBuilder.yml"), "w") as appimage_builder_file:
|
||||||
|
appimage_builder_file.write(appimage_builder)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_appimage_entrypoint(dist_path):
|
||||||
|
with open(os.path.join(dist_path, "entrypoint.sh.jinja"), "r") as entrypoint_file:
|
||||||
|
entrypoint = entrypoint_file.read()
|
||||||
|
|
||||||
|
template = Template(entrypoint)
|
||||||
|
entrypoint = template.render(executable = "UltiMaker-Cura")
|
||||||
|
|
||||||
|
with open(os.path.join(dist_path, "entrypoint.sh"), "w") as entrypoint_file:
|
||||||
|
entrypoint_file.write(entrypoint)
|
||||||
|
|
||||||
|
def copy_files(dist_path):
|
||||||
|
"""
|
||||||
|
Copy metadata files for the metadata of the AppImage.
|
||||||
|
"""
|
||||||
|
copied_files = {
|
||||||
|
os.path.join("..", "icons", "cura-icon.svg"): os.path.join("usr", "share", "icons", "hicolor", "scalable", "apps", "cura-icon.svg"),
|
||||||
|
os.path.join("..", "icons", "cura-icon_64x64.png"): os.path.join("usr", "share", "icons", "hicolor", "64x64", "apps", "cura-icon.png"),
|
||||||
|
os.path.join("..", "icons", "cura-icon_128x128.png"): os.path.join("usr", "share", "icons", "hicolor", "128x128", "apps", "cura-icon.png"),
|
||||||
|
os.path.join("..", "icons", "cura-icon_256x256.png"): os.path.join("usr", "share", "icons", "hicolor", "256x256", "apps", "cura-icon.png"),
|
||||||
|
os.path.join("..", "icons", "cura-icon_256x256.png"): "cura-icon.png",
|
||||||
|
"entrypoint.sh": "entrypoint.sh"
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO: openssl.cnf ???
|
||||||
|
|
||||||
|
packaging_dir = os.path.dirname(__file__)
|
||||||
|
for source, dest in copied_files.items():
|
||||||
|
dest_file_path = os.path.join(dist_path, dest)
|
||||||
|
os.makedirs(os.path.dirname(dest_file_path), exist_ok=True)
|
||||||
|
shutil.copyfile(os.path.join(packaging_dir, source), dest_file_path)
|
||||||
|
|
||||||
|
# Ensure that entrypoint.sh has the proper permissions: 755 (user reads, writes and executes, group reads and executes, world reads and executes).
|
||||||
|
os.chmod(os.path.join(dist_path, "entrypoint.sh"), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
|
||||||
|
|
||||||
|
def create_appimage(dist_path, appimage_filename):
|
||||||
|
appimage_path = os.path.join(dist_path, "..", appimage_filename)
|
||||||
|
appimagetool = os.getenv("APPIMAGETOOL_LOCATION", "appimagetool")
|
||||||
|
command = [appimagetool, "--appimage-extract-and-run", f"{dist_path}/", appimage_path]
|
||||||
|
result = subprocess.call(command)
|
||||||
|
if result != 0:
|
||||||
|
raise RuntimeError(f"The AppImageTool command returned non-zero: {result}")
|
||||||
|
|
||||||
|
def sign_appimage(dist_path, appimage_filename):
|
||||||
|
appimage_path = os.path.join(dist_path, "..", appimage_filename)
|
||||||
|
command = ["gpg", "--yes", "--armor", "--detach-sig", appimage_path]
|
||||||
|
result = subprocess.call(command)
|
||||||
|
if result != 0:
|
||||||
|
raise RuntimeError(f"The GPG command returned non-zero: {result}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description = "Create AppImages of Cura.")
|
||||||
|
parser.add_argument("dist_path", type=str, help="Path to where PyInstaller installed the distribution of Cura.")
|
||||||
|
parser.add_argument("version", type=str, help="Full version number of Cura (e.g. '5.1.0-beta')")
|
||||||
|
parser.add_argument("filename", type = str, help = "Filename of the AppImage (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64.AppImage')")
|
||||||
|
args = parser.parse_args()
|
||||||
|
build_appimage(args.dist_path, args.version, args.filename)
|
8
packaging/AppImage-builder/entrypoint.sh.jinja
Normal file
8
packaging/AppImage-builder/entrypoint.sh.jinja
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BIN=`basename "$ARGV0" .AppImage`
|
||||||
|
if [ -f ${APPDIR}/$BIN ]; then
|
||||||
|
${APPDIR}/$BIN "$@"
|
||||||
|
else
|
||||||
|
${APPDIR}/{{ executable }} "$@"
|
||||||
|
fi;
|
Loading…
Add table
Add a link
Reference in a new issue