Conversation
|
Cool stuff! Haven't been able to look at things in detail yet, but two remarks re platform support:
Qt 6.3+ supports Windows 10 and 11 on 21H2 or later. I don't quite understand how that's related to the detection method, though? Perhaps we should prevent installation altogether on unsupported Windows installations?
Yup. Maybe let's remove it (and display an error) with the new installer altogether? The next (non-bugfix) release is going to be 3.0.0 with Qt 6, which indeed does not support 32-bit Windows anymore. |
Yes - I meant the OS detection method, because now we rely on the logiclib extensions of |
|
The installer now builds only for 64-bit. The OS check only passes for x86_64 Windows 10 21H2 and later, and any version of Windows 11 (Windows 11 arm64 has emulation for x86 and x86_x64 while Windows 10 has only for x86). A couple more APIs are now used for dark mode - they are undocumented but they exist on all current supported Windows builds. Also, the |
|
Hi @bitraid . I'm planning on looking at this after we get the 3.0 release out. Mostly because you are maintaining the prior version already so if you say it needs a new version then I guess it does! I added it to the 4.0 milestone but I guess that would make it 3.1 really. What do you think about adding a readme file with some helpful text for other contributors in it? Your PR description has a lot of stuff in it already that I think would be useful in a readme. I do have a question that might seem impolite given your investment so far in this. The idea of you not being able to contribute your time and us having to maintain this is a bit scary. Is it normal for a project to have 2k+ lines of installer scripts for just one platform? Questions in my mind are: is there some other installer framework which has these features builtin? Is there some of this stuff (like clearing caches?) we could move into python? When I do have a look at this I'll probably go through and ask a bunch of questions (the answers of which might end up in the readme) about it and test some core stuff. But honestly we might leave a bit of testing to our end users. Maybe some question like:
|
Hi @toofar, sorry for the delayed reply. I wouldn't necessarily say that the new version is needed - I think it would add to the quality of the project, but at the same time it would probably be enough to just update the OS requirements of the current installer instead (something that should probably be done anyway for 3.0?).
Sure, we could do a readme.
I remember reading somewhere that "NSIS is not an installer engine, but rather an engine for creating installer engines". It allows for great flexibility that is not usually found elsewhere, but the scripts can become huge (have a look for example at the 7k+ lines monstrosity of firefox installer).I understand that the size increase seems scary, but on the plus side, I think the code is a little easier to read (e.g. named registers) and test (debug build). There are parts of the code though, that are too big for what they do, for example the dark mode support. I think it's a cool (and unique) feature, but it could certainly be removed (along with probably some other stuff, too) to trim down the size. Hopefully, in the near future qutebrowser could be packaged as
Sure, ask anytime. Meanwhile, I'll try to add some more comments, and maybe open a PR with an update for the current version?
NSIS doesn't create
They have been extracted from the old msi packages. Maybe those (version checks) could also be removed, since they're too old now. |
Maybe? #7804 mentions something about NSIS changes, so they would be welcome. But if we aren't building 32bit installers that's probably enough in a pinch. |
From what I see, Qt-6.5 requires Windows 10 1809 or later. I would suggest this change to the current installer: diff --git a/misc/nsis/install.nsh b/misc/nsis/install.nsh
index e7d8b4956..8bd50e808 100755
--- a/misc/nsis/install.nsh
+++ b/misc/nsis/install.nsh
@@ -430,8 +430,25 @@ SectionEnd
; Callbacks
Function .onInit
StrCpy $KeepReg 1
- !insertmacro CheckPlatform ${PLATFORM}
- !insertmacro CheckMinWinVer ${MIN_WIN_VER}
+
+; OS version check
+ ${If} ${RunningX64}
+ GetWinVer $R0 Major
+ IntCmpU $R0 10 0 _os_check_fail _os_check_pass
+ GetWinVer $R1 Build
+ ${If} $R1 >= 22000 ; Windows 11 21H2
+ Goto _os_check_pass
+ ${ElseIf} $R1 >= 17763 ; Windows 10 1809
+ ${AndIf} ${IsNativeAMD64} ; Windows 10 has no x86_64 emulation on arm64
+ Goto _os_check_pass
+ ${EndIf}
+ ${EndIf}
+ _os_check_fail:
+ MessageBox MB_OK|MB_ICONSTOP "This version of ${PRODUCT_NAME} requires a 64-bit$\r$\n\
+ version of Windows 10 1809 or later."
+ Abort
+ _os_check_pass:
+
${ifnot} ${UAC_IsInnerInstance}
!insertmacro CheckSingleInstance "Setup" "Global" "${SETUP_MUTEX}"
!insertmacro CheckSingleInstance "Application" "Local" "${APP_MUTEX}" |
|
Hmm, thanks for the thought, but the changelog says
So I guess we shouldn't be blocking that for now. The only other change I can think of is to pull out all the support for multiple architectures, and I'm not sure it's worth it given it's already queued up in this PR. I'll ask for clarification. |
If someone builds a custom |


This took a really long time, but it’s finally here: The new NSIS script - written completely from scratch, and has also undergone several major refactors. It has many new features and improvements, and the code is much more mature. There are still a few small things that need to be decided - I’ll sum them up at the end.
Major features
(current user)), and they are registered as distinct application, so both can be selected as default app./usercommand line option, which restarts the uninstaller unelevated, and is used when called from the system settings. This takes care of the bug on older versions of Windows that elevate per-user uninstalls, and also makes sure that on per-machine uninstalls, theClear CacheandClear Configoptions are for the user that run the uninstall (in case a different account was used for elevation - something that happens before the uninstaller is executed). This option is also available for the installer, and can be used for example, when it is started from an elevated prompt, but needs to install for the current (standard) user./{DesktopIcon, StartMenuIcon, RegisterBrowser, ClearCache, ClearConfig}[=off]. There is also/InstallDiras a/Dalternative that doesn’t have to be the last parameter and accepts quotes as usual, and/Silentas a more descriptive/Salternative which is also not case sensitive.Clear CacheandClear Configcomponents are only available if the directories exist, and are also available for the installer. A confirmation is requested ifClear Configis selected.\.\and\..\, converts/to\while allowing only one, converts short names to long names, and also disallows the selection of some paths (the root of the drive, directly intoProgram Files, anywhere insideWindows). On fresh installs (or upgrade to new directory), if the selected directory exists and contains files, a message box informs the user and asks for confirmation (unless it only contains the default cache directory, which is the case with the default path for per-user installations)./Logoption. It can accept as parameter the path of the log file, or an existing directory where the log will be saved with the default name (installer name +.log). If no parameter is provided, the log is created with the default name at the same directory as the.exe. On upgrades, both the installer and uninstaller write at the same log file.the detection is done through registry, andthe colors are hardcoded. Some things, like message boxes and the "Browse Folder" dialog, don't have dark colors.Building the installer
The script uses PowerShell to generate a
.nshfile containing macros that can pass every file, its calculated hash, and every folder of the release, to any other macro or instruction. It also downloads the plugins (NsisMultiUser, UAC, StdUtils), and (if required) downloads and extracts the WiX binaries. The installer can also be built under Linux (with the POSIX build of makensis) if there is PowerShell Core installed (for the MSI package it also requires wine, but I haven’t test that).Passing the script form its default location without setting any defines, builds both x86 and x64 for the version that gets from
__init__.py. The most important configuration defines are the following:ARCH: Set the targeted CPU architecture. Can be either 'x86' or 'x64'. If left undefined, both architectures are built.VERSION: Set the release version number.MSI: Enable the creation of MSI wrappers. If defined empty, the WiX binaries are expected in$path. If the value is an http(s) link, it treats it as a link to the binaries.zipfile - if only the protocol is defined, it uses a predefined link for the.zipdownload. Any other value is treated as the local path to the WiX binaries.SIGN: If defined it signs the installer and uninstaller executables, and (if created) the.msipackage. It accepts the command string as its value, with%1being replaced by the target file. If defined empty, it uses the predefined stringsigntool.exe sign /a /tr http://timestamp.digicert.com /td sha256 /fd sha256 "%1". Might come useful for Code signing on Windows #7249.DEBUG: If defined, a debug build of the setup will be created. Running the installer/uninstaller creates a debug log file in the same directory that the installer was created, or in a directory that is set as a value to the define.Running the installer
Command line options for install:
Command line options for uninstall using the installer:
Command line options for uninstaller:
Using the MSI:
The
.msiis intended for system administrators and use with deployment tools like Active Directory or Microsoft System Center Configuration Manager. They run unattended and the installation is performed for all users. An MSI database editor like Orca can be used to create transforms (or make direct changes). These public properties are provided for configuration:INSTALL_PATH: Set the installation directory. Must be an absolute path.DESKTOP_ICON: Create Desktop shortcut icon. Can beonoroff, default inon.START_MENU_ICON: Create Start Menu shortcut icon. Can beonoroff, default inon.REGISTER_BROWSER: Register the browser with Windows. Can beonoroff, default inon.LOG: The path of the log file or the log directory, default is\\.\nul.They can also be set from command line, for example:
Reviewing the code
The code is structured in the following way:
qutebrowser.nsi: The main script. It configures the plugins, has the installer and uninstaller Sections, and sources the rest of the files.config.nsh: Configures the setup build and provides a macro with the compile time commands.commands.nsh: Contains commands with operations that are repeated at different parts of the code, or are shared between the installer and uninstaller. The code of the functions is defined by macros, and imported for both installer and uninstaller for shared commands.callbacks.nsh: Contains the callback functions. Some functions are shared by the installer and uninstaller, that's why it is sourced twice, with a different function prefix each time.language-english.nsh: The English language strings. Where possible, it reuses strings from NSIS MUI. To add a new language, copy this file, change the language name and translate the strings. Then include the new file from the main script. Keep in mind though, that although MUI supports many languages, there are also a few strings from MultiUser plugin, which are only translated to Bulgarian and German (for other languages, they are displayed in English).Things that might need changes
The script is designed to download the 3rd party files to a temporary directory, build both architectures if needed, and remove the directory. But nowbuild_release.pybuilds each installer separately, so it downloads the files twice. This could be overcomed without actual code changes, by settingKEEP_SCRATCHDIRfor the first build andNO_DOWNLOADSfor the second, while setting for both a temporary path inSCRATCHDIR. Or maybe it's not so important since the 32-bit build is going to be dropped?If the required versions of Win10/11 are going to be from a specific build number and above, a new detection method must be written.Maybe the message when the installer is started under 32-bit should be different, if it's not going to be a 32-bit version.DARK_BGCOLOR_0=0,DARK_BGCOLOR_1=0makes it look more like what Windows 10 uses.