Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorj.spijker@ultimaker.com <jelle spijker>2022-07-01 07:18:43 +0300
committerJelle Spijker <j.spijker@ultimaker.com>2022-07-01 07:18:43 +0300
commit721aff425564f30055f6149b8ac1ed8774e6481c (patch)
treed3e5de3768df535332fc260f58c77e1883e3c464 /packaging
parentdc8c9bb2763c2eae2e39edf12597255c44beb98f (diff)
Ported nsis scripts and resource from cura-build-environment
Contributes to CURA-9365
Diffstat (limited to 'packaging')
-rw-r--r--packaging/NSIS/Ultimaker-Cura.nsi.jinja194
-rw-r--r--packaging/NSIS/fileassoc.nsh134
-rw-r--r--packaging/NSIS/nsis-configurator.py78
3 files changed, 406 insertions, 0 deletions
diff --git a/packaging/NSIS/Ultimaker-Cura.nsi.jinja b/packaging/NSIS/Ultimaker-Cura.nsi.jinja
new file mode 100644
index 0000000000..465575e220
--- /dev/null
+++ b/packaging/NSIS/Ultimaker-Cura.nsi.jinja
@@ -0,0 +1,194 @@
+# Copyright (c) 2022 Ultimaker B.V.
+# Cura's build system is released under the terms of the AGPLv3 or higher.
+
+!define APP_NAME "{{ app_name }} {{ version_major }}.{{ version_minor }}.{{ version_patch }}"
+!define COMP_NAME "{{ company }}"
+!define WEB_SITE "{{ web_site }}"
+!define VERSION "{{ version_major }}.{{ version_minor }}.{{ version_patch }}.{{ version_build }}"
+!define COPYRIGHT "Copyright (c) {{ year }} {{ company }}"
+!define DESCRIPTION "Application"
+!define LICENSE_TXT "{{ cura_license_file }}"
+!define INSTALLER_NAME "{{ destination }}"
+!define MAIN_APP_EXE "{{ main_app }}"
+!define INSTALL_TYPE "SetShellVarContext current"
+!define REG_ROOT "HKCU"
+!define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${MAIN_APP_EXE}"
+!define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
+
+!define REG_START_MENU "Start Menu Folder"
+
+;Require administrator access
+RequestExecutionLevel admin
+
+var SM_Folder
+
+######################################################################
+
+VIProductVersion "${VERSION}"
+VIAddVersionKey "ProductName" "${APP_NAME}"
+VIAddVersionKey "CompanyName" "${COMP_NAME}"
+VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
+VIAddVersionKey "FileDescription" "${DESCRIPTION}"
+VIAddVersionKey "FileVersion" "${VERSION}"
+
+######################################################################
+
+SetCompressor {{ compression_method }}
+Name "${APP_NAME}"
+Caption "${APP_NAME}"
+OutFile "${INSTALLER_NAME}"
+BrandingText "${APP_NAME}"
+InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" ""
+InstallDir "$PROGRAMFILES64\${APP_NAME}"
+
+######################################################################
+
+!include "MUI2.nsh"
+!include fileassoc.nsh
+
+!define MUI_ABORTWARNING
+!define MUI_UNABORTWARNING
+
+!define MUI_ICON "{{ cura_icon }}"
+
+!define MUI_WELCOMEFINISHPAGE_BITMAP "{{ cura_banner_img }}"
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "{{ cura_banner_img }}"
+
+!insertmacro MUI_PAGE_WELCOME
+
+!ifdef LICENSE_TXT
+!insertmacro MUI_PAGE_LICENSE "${LICENSE_TXT}"
+!endif
+
+!insertmacro MUI_PAGE_DIRECTORY
+
+!ifdef REG_START_MENU
+!define MUI_STARTMENUPAGE_NODISABLE
+!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}"
+!insertmacro MUI_PAGE_STARTMENU Application $SM_Folder
+!endif
+
+!insertmacro MUI_PAGE_INSTFILES
+
+# Set up explorer to run Cura instead of directly, so it's not executed elevated (with all negative consequences that brings for an unelevated user).
+!define MUI_FINISHPAGE_RUN "$WINDIR\explorer.exe"
+!define MUI_FINISHPAGE_RUN_PARAMETERS "$INSTDIR\${MAIN_APP_EXE}"
+!insertmacro MUI_PAGE_FINISH
+
+!insertmacro MUI_UNPAGE_CONFIRM
+
+!insertmacro MUI_UNPAGE_INSTFILES
+
+!insertmacro MUI_UNPAGE_FINISH
+
+!insertmacro MUI_LANGUAGE "English"
+
+######################################################################
+
+Section -MainProgram
+${INSTALL_TYPE}
+SetOverwrite ifnewer
+{% for out_path, files in mapped_out_paths.items() %}SetOutPath "{{ out_path }}"{% for file in files %}
+File "{{ file[0] }}"{% endfor %}
+{% endfor %}SectionEnd
+
+######################################################################
+
+Section -Extension_Reg
+!insertmacro APP_ASSOCIATE "stl" "Cura.model" "Standard Tessellation Language (STL) files" "$INSTDIR\${MAIN_APP_EXE},0" "Open with {{ app_name }}" "$INSTDIR\${MAIN_APP_EXE} $\"%1$\""
+!insertmacro APP_ASSOCIATE "3mf" "Cura.project" "3D Manufacturing Format (3MF) files" "$INSTDIR\${MAIN_APP_EXE},0" "Open with {{ app_name }}" "$INSTDIR\${MAIN_APP_EXE} $\"%1$\""
+SectionEnd
+
+Section -Icons_Reg
+SetOutPath "$INSTDIR"
+WriteUninstaller "$INSTDIR\uninstall.exe"
+
+!ifdef REG_START_MENU
+!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+CreateDirectory "$SMPROGRAMS\$SM_Folder"
+CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}"
+CreateShortCut "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe"
+
+!ifdef WEB_SITE
+WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}"
+CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url"
+!endif
+!insertmacro MUI_STARTMENU_WRITE_END
+!endif
+
+!ifndef REG_START_MENU
+CreateDirectory "$SMPROGRAMS\{{ app_name }}"
+CreateShortCut "$SMPROGRAMS\{{ app_name }}\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}"
+CreateShortCut "$SMPROGRAMS\{{ app_name }}\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe"
+
+!ifdef WEB_SITE
+WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}"
+CreateShortCut "$SMPROGRAMS\{{ app_name }}\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url"
+!endif
+!endif
+
+WriteRegStr ${REG_ROOT} "${REG_APP_PATH}" "" "$INSTDIR\${MAIN_APP_EXE}"
+WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayName" "${APP_NAME}"
+WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" "$INSTDIR\uninstall.exe"
+WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayIcon" "$INSTDIR\${MAIN_APP_EXE}"
+WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayVersion" "${VERSION}"
+WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "Publisher" "${COMP_NAME}"
+
+!ifdef WEB_SITE
+WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "URLInfoAbout" "${WEB_SITE}"
+!endif
+SectionEnd
+
+######################################################################
+
+Section Uninstall
+${INSTALL_TYPE}{% for files in mapped_out_paths.values() %}{% for file in files %}
+Delete "{{ file[1] }}"{% endfor %}{% endfor %}{% for rem_dir in rmdir_paths %}
+RmDir "{{ rem_dir }}"{% endfor %}
+
+# FIXME: dirty solution, but for some reason these directories aren't removed
+RmDir "$INSTDIR\share\cura\resources\scripts"
+RmDir "$INSTDIR\share\cura\resources"
+RmDir "$INSTDIR\share\cura"
+RmDir "$INSTDIR\share\uranium\resources\scripts"
+RmDir "$INSTDIR\share\uranium\resources"
+RmDir "$INSTDIR\share\uranium"
+RmDir "$INSTDIR\share"
+
+Delete "$INSTDIR\uninstall.exe"
+!ifdef WEB_SITE
+Delete "$INSTDIR\${APP_NAME} website.url"
+!endif
+
+RmDir "$INSTDIR"
+
+!ifdef REG_START_MENU
+!insertmacro MUI_STARTMENU_GETFOLDER "Application" $SM_Folder
+Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk"
+Delete "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk"
+!ifdef WEB_SITE
+Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk"
+!endif
+RmDir "$SMPROGRAMS\$SM_Folder"
+!endif
+
+!ifndef REG_START_MENU
+Delete "$SMPROGRAMS\{{ app_name }}\${APP_NAME}.lnk"
+Delete "$SMPROGRAMS\{{ app_name }}\Uninstall ${APP_NAME}.lnk"
+!ifdef WEB_SITE
+Delete "$SMPROGRAMS\{{ app_name }}\${APP_NAME} Website.lnk"
+!endif
+RmDir "$SMPROGRAMS\{{ app_name }}"
+!endif
+
+!insertmacro APP_UNASSOCIATE "stl" "Cura.model"
+!insertmacro APP_UNASSOCIATE "3mf" "Cura.project"
+
+DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
+DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
+SectionEnd
+
+######################################################################
diff --git a/packaging/NSIS/fileassoc.nsh b/packaging/NSIS/fileassoc.nsh
new file mode 100644
index 0000000000..cb0fb2fe65
--- /dev/null
+++ b/packaging/NSIS/fileassoc.nsh
@@ -0,0 +1,134 @@
+; fileassoc.nsh
+; File association helper macros
+; Written by Saivert
+;
+; Improved by Nikku<https://github.com/nikku>.
+;
+; Features automatic backup system and UPDATEFILEASSOC macro for
+; shell change notification.
+;
+; |> How to use <|
+; To associate a file with an application so you can double-click it in explorer, use
+; the APP_ASSOCIATE macro like this:
+;
+; Example:
+; !insertmacro APP_ASSOCIATE "txt" "myapp.textfile" "Description of txt files" \
+; "$INSTDIR\myapp.exe,0" "Open with myapp" "$INSTDIR\myapp.exe $\"%1$\""
+;
+; Never insert the APP_ASSOCIATE macro multiple times, it is only ment
+; to associate an application with a single file and using the
+; the "open" verb as default. To add more verbs (actions) to a file
+; use the APP_ASSOCIATE_ADDVERB macro.
+;
+; Example:
+; !insertmacro APP_ASSOCIATE_ADDVERB "myapp.textfile" "edit" "Edit with myapp" \
+; "$INSTDIR\myapp.exe /edit $\"%1$\""
+;
+; To have access to more options when registering the file association use the
+; APP_ASSOCIATE_EX macro. Here you can specify the verb and what verb is to be the
+; standard action (default verb).
+;
+; Note, that this script takes into account user versus global installs.
+; To properly work you must initialize the SHELL_CONTEXT variable via SetShellVarContext.
+;
+; And finally: To remove the association from the registry use the APP_UNASSOCIATE
+; macro. Here is another example just to wrap it up:
+; !insertmacro APP_UNASSOCIATE "txt" "myapp.textfile"
+;
+; |> Note <|
+; When defining your file class string always use the short form of your application title
+; then a period (dot) and the type of file. This keeps the file class sort of unique.
+; Examples:
+; Winamp.Playlist
+; NSIS.Script
+; Photoshop.JPEGFile
+;
+; |> Tech info <|
+; The registry key layout for a global file association is:
+;
+; HKEY_LOCAL_MACHINE\Software\Classes
+; <".ext"> = <applicationID>
+; <applicationID> = <"description">
+; shell
+; <verb> = <"menu-item text">
+; command = <"command string">
+;
+;
+; The registry key layout for a per-user file association is:
+;
+; HKEY_CURRENT_USER\Software\Classes
+; <".ext"> = <applicationID>
+; <applicationID> = <"description">
+; shell
+; <verb> = <"menu-item text">
+; command = <"command string">
+;
+
+!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
+ ; Backup the previously associated file class
+ ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_ASSOCIATE_EX EXT FILECLASS DESCRIPTION ICON VERB DEFAULTVERB SHELLNEW COMMANDTEXT COMMAND
+ ; Backup the previously associated file class
+ ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
+ StrCmp "${SHELLNEW}" "0" +2
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}\ShellNew" "NullFile" ""
+
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" `${DEFAULTVERB}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_ASSOCIATE_ADDVERB FILECLASS VERB COMMANDTEXT COMMAND
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_ASSOCIATE_REMOVEVERB FILECLASS VERB
+ DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}\shell\${VERB}`
+!macroend
+
+
+!macro APP_UNASSOCIATE EXT FILECLASS
+ ; Backup the previously associated file class
+ ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
+ WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
+
+ DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
+!macroend
+
+!macro APP_ASSOCIATE_GETFILECLASS OUTPUT EXT
+ ReadRegStr ${OUTPUT} SHELL_CONTEXT "Software\Classes\.${EXT}" ""
+!macroend
+
+
+; !defines for use with SHChangeNotify
+!ifdef SHCNE_ASSOCCHANGED
+!undef SHCNE_ASSOCCHANGED
+!endif
+!define SHCNE_ASSOCCHANGED 0x08000000
+!ifdef SHCNF_FLUSH
+!undef SHCNF_FLUSH
+!endif
+!define SHCNF_FLUSH 0x1000
+
+!macro UPDATEFILEASSOC
+; Using the system.dll plugin to call the SHChangeNotify Win32 API function so we
+; can update the shell.
+ System::Call "shell32::SHChangeNotify(i,i,i,i) (${SHCNE_ASSOCCHANGED}, ${SHCNF_FLUSH}, 0, 0)"
+!macroend \ No newline at end of file
diff --git a/packaging/NSIS/nsis-configurator.py b/packaging/NSIS/nsis-configurator.py
new file mode 100644
index 0000000000..c8986fb118
--- /dev/null
+++ b/packaging/NSIS/nsis-configurator.py
@@ -0,0 +1,78 @@
+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))
+