diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index a4adf07945..a95f6a60cc 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -183,8 +183,7 @@ jobs: - name: Create the Windows exe installer (Powershell) if: ${{ github.event.inputs.installer == 'true' && runner.os == 'Windows' }} run: | - python ..\cura_inst\packaging\NSIS\nsis-configurator.py ".\Ultimaker-Cura" "..\cura_inst\packaging\NSIS\Ultimaker-Cura.nsi.jinja" "Ultimaker Cura" "Ultimaker-Cura.exe" "$Env:CURA_VERSION_MAJOR" "$Env:CURA_VERSION_MINOR" "$Env:CURA_VERSION_PATCH" "$Env:CURA_VERSION_BUILD" "Ultimaker B.V." "https://ultimaker.com" "..\cura_inst\packaging\cura_license.txt" "LZMA" "..\cura_inst\packaging\NSIS\cura_banner_nsis.bmp" "..\cura_inst\packaging\icons\Cura.ico" "Ultimaker-Cura-$Env:CURA_VERSION_FULL-${{ matrix.os_id }}-${{ runner.arch }}.exe" - makensis /V2 /P4 Ultimaker-Cura.nsi + python ..\cura_inst\packaging\NSIS\create_windows_installer.py ../cura_inst . "Ultimaker-Cura-$Env:CURA_VERSION_FULL-${{ matrix.os_id }}-${{ runner.arch }}.exe" working-directory: dist - name: Create the Linux AppImage (Bash) diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja index ecc5a52fe1..b7a50674ed 100644 --- a/packaging/NSIS/Ultimaker-Cura.nsi.jinja +++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja @@ -25,7 +25,7 @@ var SM_Folder ###################################################################### VIProductVersion "${VERSION}" -VIAddVersionKey "ProductName" "${APP_NAME}" +VIAddVersionKey "ProductName" "{{ app_name }}" VIAddVersionKey "CompanyName" "${COMP_NAME}" VIAddVersionKey "LegalCopyright" "${COPYRIGHT}" VIAddVersionKey "FileDescription" "${DESCRIPTION}" @@ -64,7 +64,7 @@ InstallDir "$PROGRAMFILES64\${APP_NAME}" !ifdef REG_START_MENU !define MUI_STARTMENUPAGE_NODISABLE -!define MUI_STARTMENUPAGE_DEFAULTFOLDER "{{ app_name }}" +!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${APP_NAME}" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${REG_ROOT}" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${UNINSTALL_PATH}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${REG_START_MENU}" diff --git a/packaging/NSIS/create_windows_installer.py b/packaging/NSIS/create_windows_installer.py new file mode 100644 index 0000000000..6bfc729bb0 --- /dev/null +++ b/packaging/NSIS/create_windows_installer.py @@ -0,0 +1,80 @@ +# Copyright (c) 2022 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. +import os +import argparse # Command line arguments parsing and help. +import subprocess + +import shutil +import sys +from datetime import datetime + +from pathlib import Path + +from jinja2 import Template + + +def generate_nsi(source_path: str, dist_path: str, filename: str): + dist_loc = Path(dist_path) + source_loc = Path(source_path) + instdir = Path("$INSTDIR") + dist_paths = [p.relative_to(dist_loc.joinpath("Ultimaker-Cura")) for p in sorted(dist_loc.joinpath("Ultimaker-Cura").rglob("*")) if p.is_file()] + mapped_out_paths = {} + for dist_path in dist_paths: + if "__pycache__" not in dist_path.parts: + out_path = instdir.joinpath(dist_path).parent + if out_path not in mapped_out_paths: + mapped_out_paths[out_path] = [(dist_loc.joinpath("Ultimaker-Cura", dist_path), instdir.joinpath(dist_path))] + else: + mapped_out_paths[out_path].append((dist_loc.joinpath("Ultimaker-Cura", dist_path), instdir.joinpath(dist_path))) + + rmdir_paths = set() + for rmdir_f in mapped_out_paths.values(): + for _, rmdir_p in rmdir_f: + for rmdir in rmdir_p.parents: + rmdir_paths.add(rmdir) + + rmdir_paths = sorted(list(rmdir_paths), reverse = True)[:-2] + + jinja_template_path = Path(sys.argv[2]) + with open(jinja_template_path, "r") as f: + template = Template(f.read()) + + nsis_content = template.render( + app_name = "Ultimaker Cura", + main_app = "Ultimaker-Cura.exe", + version_major = os.environ.get("CURA_VERSION_MAJOR"), + version_minor = os.environ.get("CURA_VERSION_MINOR"), + version_patch = os.environ.get("CURA_VERSION_PATCH"), + version_build = os.environ.get("CURA_VERSION_BUILD"), + company = "Ultimaker B.V.", + web_site = "https://ultimaker.com", + year = datetime.now().year, + cura_license_file = str(source_loc.joinpath("packaging", "cura_license.txt")), + compression_method = "LZMA", # ZLIB, BZIP2 or LZMA + cura_banner_img = str(source_loc.joinpath("packaging", "NSIS", "cura_banner_nsis.bmp")), + cura_icon = str(source_loc.joinpath("packaging", "icons", "Cura.ico")), + mapped_out_paths = mapped_out_paths, + rmdir_paths = rmdir_paths, + destination = filename + ) + + with open(dist_loc.joinpath("Ultimaker-Cura.nsi"), "w") as f: + f.write(nsis_content) + + shutil.copy(source_loc.joinpath("packaging", "NSIS", "fileassoc.nsh"), dist_loc.joinpath("fileassoc.nsh")) + + +def build(dist_path: str): + dist_loc = Path(dist_path) + command = ["makensis", "/V2", "/P4", str(dist_loc.joinpath("Ultimaker-Cura.nsi"))] + subprocess.run(command) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description = "Create Windows exe installer of Cura.") + parser.add_argument("source_path", type=str, help="Path to Conan install Cura folder.") + parser.add_argument("dist_path", type=str, help="Path to Pyinstaller dist folder") + parser.add_argument("filename", type = str, help = "Filename of the exe (e.g. 'Ultimaker-Cura-5.1.0-beta-Windows-X64.exe')") + args = parser.parse_args() + generate_nsi(args.source_path, args.dist_path, args.filename) + build(args.dist_path) diff --git a/packaging/NSIS/nsis-configurator.py b/packaging/NSIS/nsis-configurator.py deleted file mode 100644 index c8986fb118..0000000000 --- a/packaging/NSIS/nsis-configurator.py +++ /dev/null @@ -1,78 +0,0 @@ -import shutil -import sys -from datetime import datetime - -from pathlib import Path - -from jinja2 import Template - -if __name__ == "__main__": - """ - - dist_loc: Location of distribution folder, as output by pyinstaller - - nsi_jinja_loc: Jinja2 template to use - - app_name: Should be "Ultimaker Cura". - - main_app: Name of executable, e.g. Ultimaker-Cura.exe? - - version_major: Major version number of Semver (e.g. 5). - - version_minor: Minor version number of Semver (e.g. 0). - - version_patch: Patch version number of Semver (e.g. 0). - - version_build: A version number that gets manually incremented at each build. - - company: Publisher of the application. Should be "Ultimaker B.V." - - web_site: Website to find more information. Should be "https://ultimaker.com". - - cura_license_file: Path to a license file in Cura. Should point to packaging/cura_license.txt in this repository. - - compression_method: Compression algorithm to use to compress the data inside the executable. Should be ZLIB, ZBIP2 or LZMA. - - cura_banner_img: Path to an image shown on the left in the installer. Should point to packaging/cura_banner_nsis.bmp in this repository. - - icon_path: Path to the icon to use on the installer - - destination: Where to put the installer after it's generated. -` """ - for i, v in enumerate(sys.argv): - print(f"{i} = {v}") - dist_loc = Path(sys.argv[1]) - instdir = Path("$INSTDIR") - dist_paths = [p.relative_to(dist_loc) for p in sorted(dist_loc.rglob("*")) if p.is_file()] - mapped_out_paths = {} - for dist_path in dist_paths: - if "__pycache__" not in dist_path.parts: - out_path = instdir.joinpath(dist_path).parent - if out_path not in mapped_out_paths: - mapped_out_paths[out_path] = [(dist_loc.joinpath(dist_path), instdir.joinpath(dist_path))] - else: - mapped_out_paths[out_path].append((dist_loc.joinpath(dist_path), instdir.joinpath(dist_path))) - - rmdir_paths = set() - for rmdir_f in mapped_out_paths.values(): - for _, rmdir_p in rmdir_f: - for rmdir in rmdir_p.parents: - rmdir_paths.add(rmdir) - - rmdir_paths = sorted(list(rmdir_paths), reverse = True)[:-2] - - jinja_template_path = Path(sys.argv[2]) - with open(jinja_template_path, "r") as f: - template = Template(f.read()) - - nsis_content = template.render( - app_name = sys.argv[3], - main_app = sys.argv[4], - version_major = sys.argv[5], - version_minor = sys.argv[6], - version_patch = sys.argv[7], - version_build = sys.argv[8], - company = sys.argv[9], - web_site = sys.argv[10], - year = datetime.now().year, - cura_license_file = Path(sys.argv[11]), - compression_method = sys.argv[12], # ZLIB, BZIP2 or LZMA - cura_banner_img = Path(sys.argv[13]), - cura_icon = Path(sys.argv[14]), - mapped_out_paths = mapped_out_paths, - rmdir_paths = rmdir_paths, - destination = Path(sys.argv[15]) - ) - - with open(dist_loc.parent.joinpath(jinja_template_path.stem), "w") as f: - f.write(nsis_content) - - shutil.copy(Path(__file__).absolute().parent.joinpath("fileassoc.nsh"), dist_loc.parent.joinpath("fileassoc.nsh")) - icon_path = Path(sys.argv[14]) - shutil.copy(icon_path, dist_loc.joinpath(icon_path.name)) -