create_appimage.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. # Copyright (c) 2023 UltiMaker
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import argparse
  4. import os
  5. import shutil
  6. import subprocess
  7. from pathlib import Path
  8. from jinja2 import Template
  9. def prepare_workspace(dist_path, appimage_filename):
  10. """
  11. Prepare the workspace for building the AppImage.
  12. :param dist_path: Path to the distribution of Cura created with pyinstaller.
  13. :param appimage_filename: name of the AppImage file.
  14. :return:
  15. """
  16. if not os.path.exists(dist_path):
  17. raise RuntimeError(f"The dist_path {dist_path} does not exist.")
  18. if os.path.exists(os.path.join(dist_path, appimage_filename)):
  19. os.remove(os.path.join(dist_path, appimage_filename))
  20. if not os.path.exists("AppDir"):
  21. shutil.move(dist_path, "AppDir")
  22. else:
  23. print(f"AppDir already exists, assuming it is already prepared.")
  24. copy_files("AppDir")
  25. def build_appimage(dist_path, version, appimage_filename):
  26. """
  27. Creates an AppImage file from the build artefacts created so far.
  28. """
  29. generate_appimage_builder_config(dist_path, version, appimage_filename)
  30. create_appimage()
  31. sign_appimage(appimage_filename)
  32. def generate_appimage_builder_config(dist_path, version, appimage_filename):
  33. with open(os.path.join(Path(__file__).parent, "AppImageBuilder.yml.jinja"), "r") as appimage_builder_file:
  34. appimage_builder = appimage_builder_file.read()
  35. template = Template(appimage_builder)
  36. appimage_builder = template.render(app_dir = "./AppDir",
  37. icon = "cura-icon.png",
  38. version = version,
  39. arch = "x86_64",
  40. file_name = appimage_filename)
  41. with open(os.path.join(Path(__file__).parent, "AppImageBuilder.yml"), "w") as appimage_builder_file:
  42. appimage_builder_file.write(appimage_builder)
  43. def copy_files(dist_path):
  44. """
  45. Copy metadata files for the metadata of the AppImage.
  46. """
  47. copied_files = {
  48. os.path.join("..", "icons", "cura-icon.svg"): os.path.join("usr", "share", "icons", "hicolor", "scalable", "apps", "cura-icon.svg"),
  49. os.path.join("..", "icons", "cura-icon_64x64.png"): os.path.join("usr", "share", "icons", "hicolor", "64x64", "apps", "cura-icon.png"),
  50. os.path.join("..", "icons", "cura-icon_128x128.png"): os.path.join("usr", "share", "icons", "hicolor", "128x128", "apps", "cura-icon.png"),
  51. os.path.join("..", "icons", "cura-icon_256x256.png"): os.path.join("usr", "share", "icons", "hicolor", "256x256", "apps", "cura-icon.png"),
  52. os.path.join("..", "icons", "cura-icon_256x256.png"): "cura-icon.png",
  53. }
  54. # TODO: openssl.cnf ???
  55. packaging_dir = os.path.dirname(__file__)
  56. for source, dest in copied_files.items():
  57. dest_file_path = os.path.join(dist_path, dest)
  58. os.makedirs(os.path.dirname(dest_file_path), exist_ok = True)
  59. shutil.copyfile(os.path.join(packaging_dir, source), dest_file_path)
  60. def create_appimage():
  61. appimagetool = os.getenv("APPIMAGEBUILDER_LOCATION", "appimage-builder-x86_64.AppImage")
  62. command = [appimagetool, "--recipe", os.path.join(Path(__file__).parent, "AppImageBuilder.yml"), "--skip-test"]
  63. result = subprocess.call(command)
  64. if result != 0:
  65. raise RuntimeError(f"The AppImageTool command returned non-zero: {result}")
  66. def sign_appimage(appimage_filename):
  67. command = ["gpg", "--yes", "--armor", "--detach-sig", appimage_filename]
  68. result = subprocess.call(command)
  69. if result != 0:
  70. raise RuntimeError(f"The GPG command returned non-zero: {result}")
  71. if __name__ == "__main__":
  72. parser = argparse.ArgumentParser(description = "Create AppImages of Cura.")
  73. parser.add_argument("dist_path", type = str, help = "Path to where PyInstaller installed the distribution of Cura.")
  74. parser.add_argument("version", type = str, help = "Full version number of Cura (e.g. '5.1.0-beta')")
  75. parser.add_argument("filename", type = str, help = "Filename of the AppImage (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64.AppImage')")
  76. args = parser.parse_args()
  77. prepare_workspace(args.dist_path, args.filename)
  78. build_appimage(args.dist_path, args.version, args.filename)