# How-to guides ## Control which kind of installer gets generated Constructor is currently limited to generating installers for the platform on which it is running. In other words, if you run constructor on a Windows computer, you can only generate Windows installers. This is largely because OS-native tools are needed to generate the Windows `.exe` files and macOS `.pkg` files. There is a key in `construct.yaml`, `installer_type`, which dictates the type of installer that gets generated. This is primarily only useful for macOS, where you can generate either `.pkg` or `.sh` installers. When not set in `construct.yaml`, this value defaults to `.sh` on Unix platforms, and `.exe` on Windows. Using this key is generally done with selectors. For example, to build a `.pkg` installer on MacOS, but fall back to default behavior on other platforms: ```yaml installer_type: pkg #[osx] ``` See [`installer_type`](construct-yaml.md#installer_type) for more details. ## Customization and branding Graphical installers (`.pkg` on macOS and `.exe` on Windows) support some level of branding and customization. Logos, backgrounds and banners: - Refer to [`welcome_image`](construct-yaml.md#welcome_image) and [`icon_image`](construct-yaml.md#icon_image). Windows also supports [`header_image`](construct-yaml.md#header_image). - Alternatively, a text-based image can be autogenerated from text if you set [`welcome_image_text`](construct-yaml.md#welcome_image_text) and [`header_image_text`](construct-yaml.md#header_image_text), respectively. The color of such text can be provided via [`default_image_color`](construct-yaml.md#default_image_color). Messages and texts. You can specify these via `*_file` (a path is expected) or `_text` (raw string expected). - [`welcome_file`](construct-yaml.md#welcome_file) and [`welcome_text`](construct-yaml.md#welcome_text): The text that is shown in the first page of the installer. - [`readme_file`](construct-yaml.md#readme_file) and [`readme_text`](construct-yaml.md#readme_text): Optional text to be displayed on an extra page before the license. macOS only. - [`conclusion_file`](construct-yaml.md#conclusion_file) and [`conclusion_text`](construct-yaml.md#conclusion_text): The text to be shown at the end of the installer, on success. On Windows, you can also add extra pages to the installer. This is an advanced option, so your best bet is to check the examples in the source repository at `examples/customized_welcome_conclusion`. ## Signing and notarization ```{seealso} Example of a CI pipeline implementing: - [Signing on Windows](https://github.com/napari/packaging/blob/6f5fcfaf7b/.github/workflows/make_bundle_conda.yml#L390) - [Signing](https://github.com/napari/packaging/blob/6f5fcfaf7b/.github/workflows/make_bundle_conda.yml#L349) and [notarization](https://github.com/napari/packaging/blob/6f5fcfaf7b/.github/workflows/make_bundle_conda.yml#L459) on macOS ``` ### Signing EXE installers Windows can trigger SmartScreen alerts for EXE installers, signed or not. It does help when they are signed, though. [Read this SO answer about SmartScreen reputation for more details](https://stackoverflow.com/questions/48946680/how-to-avoid-the-windows-defender-smartscreen-prevented-an-unrecognized-app-fro/66582477#66582477). `constructor` supports the following tools to sign installers: * [SignTool](https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool) * [AzureSignTool](https://github.com/vcsjones/AzureSignTool) The signtool that is used can be set in the `construct.yaml` file via the [`windows_signing_tool`](construct-yaml.md#windows_signing_tool) key. If the [`signing_certificate`](construct-yaml.md#signing_certificate) key is set, `windows_signing_tool` defaults to `signtool`. For each tool, there are environment variables that may need to be set to configure signing. #### Environment variables for SignTool | Variable | Description | CLI flag | Default | |---------------------------------------------|----------------------------------------------------------------|----------|------------------------------| | `CONSTRUCTOR_PFX_CERTIFICATE_PASSWORD` | Password for the `pfx` certificate file. | `/p` | Empty | | `CONSTRUCTOR_SIGNTOOL_PATH` | Path to `signtool.exe`. Needed if `signtool` is not in `PATH`. | N/A | `signtool` | | `CONSTRUCTOR_SIGNTOOL_FILE_DIGEST` | Digest algorithm for creating the file signatures. | `/fd` | `sha256` | | `CONSTRUCTOR_SIGNTOOL_TIMESTAMP_SERVER_URL` | URL to the RFC 3161 timestamp server. | `/tr` | http://timestamp.sectigo.com | | `CONSTRUCTOR_SIGNTOOL_TIMESTAMP_DIGEST` | Digest algorithm for the RFC 3161 time stamp. | `/td` | `sha256` | #### Environment variables for AzureSignTool | Variable | Description | CLI flag | Default | |----------------------------------------|---------------------------------------------------------------------------------------------|----------|------------------------------| | `AZURE_SIGNTOOL_FILE_DIGEST` | Digest algorithm for creating the file signatures. | `-fd` | `sha256` | | `AZURE_SIGNTOOL_KEY_VAULT_ACCESSTOKEN` | An access token used to authenticate to Azure. | `-kva` | Empty | | `AZURE_SIGNTOOL_KEY_VAULT_CERTIFICATE` | The name of the certificate in the key vault. | `-kvc` | Empty | | `AZURE_SIGNTOOL_KEY_VAULT_CLIENT_ID` | The client ID used to authenticate to Azure. Required for authentication with a secret. | `-kvi` | Empty | | `AZURE_SIGNTOOL_KEY_VAULT_SECRET` | The client secret used to authenticate to Azure. Required for authentication with a secret. | `-kvs` | Empty | | `AZURE_SIGNTOOL_KEY_VAULT_TENANT_ID` | The tenant ID used to authenticate to Azure. Required for authentication with a secret. | `-kvt` | Empty | | `AZURE_SIGNTOOL_KEY_VAULT_URL` | The URL of the key vault with the certificate. | `-kvu` | Empty | | `AZURE_SIGNTOOL_PATH` | Path to `AzureSignTool.exe`. Needed if `azuresigntool` is not in `PATH`. | N/A | `azuresigntool` | | `AZURE_SIGNTOOL_TIMESTAMP_SERVER_URL` | URL to the RFC 3161 timestamp server. | `-tr` | http://timestamp.sectigo.com | | `AZURE_SIGNTOOL_TIMESTAMP_DIGEST` | Digest algorithm for the RFC 3161 time stamp. | `-td` | `sha256` | :::{note} If neither `AZURE_SIGNTOOL_KEY_VAULT_ACCESSTOKEN` nor `AZURE_SIGNTOOL_KEY_VAULT_SECRET` are set, `constructor` will use a Managed Identity (`-kvm` CLI option). ::: ### Signing and notarizing PKG installers In the case of macOS, users might get warnings for PKGs if the installers are not signed _and_ notarized. However, once these two requirements are fulfilled, the warnings disappear instantly. `constructor` offers some configuration options to help you in this process: You will need to provide two identity names. One for the PKG signature (via [`signing_identity_name`](construct-yaml.md#signing_identity_name)), and one to pass the notarization (via [`notarization_identity_name`](construct-yaml.md#notarization_identity_name)). These can be obtained in the [Apple Developer portal](https://developer.apple.com/account/). Once signed, you can notarize your PKG with Apple's `notarytool`. ## Create shortcuts On Windows, `conda` supports `menuinst 1.x` shortcuts. If a package provides a certain JSON file under `$PREFIX/Menu`, `conda` will process it to create the specified menu items. This happens by default for _all packages_. If you only want this to happen for certain packages, use the [`menu_packages`](construct-yaml.md#menu_packages) key. Starting with `conda` 23.11, `menuinst 2.x` is supported, which means you can create shortcuts in all platforms (Linux, macOS and Windows). The JSON document format is slightly different, so make sure to check the [menuinst documentation](https://conda.github.io/menuinst/). Your installer will need to be created with `conda-standalone 23.11` or above. `micromamba` does not currently support `menuinst 2.x` style shortcuts (only `1.x` on Windows). To learn more about `menuinst`, visit [`conda/menuinst`](https://github.com/conda/menuinst). ## Find out the used constructor version Recent constructor versions (>=3.4.2) burn-in their version into created installers in order to be able to trace back bugs in created installers to the constructor code base. The burned-in version can be retrieved in different ways depending on the installer type: - For `.sh` intallers (via cli): `head $installer.sh | grep "Created by constructor"` - For `.exe` installers (via Windows Explorer): `$installer.exe` → Properties → Details → Comments, or (via cli) `exiftool $installer.exe` - For `.pkg` installers (via cli on macOS): `xar -xf $installer.pkg -n run_installation.pkg/Scripts; zgrep -a "Created by constructor" run_installation.pkg/Scripts` or `pkgutil --expand $installer.pkg extracted; grep "Created by constructor" extracted/run_installation.pkg/Scripts/postinstall` ## Uninstall `constructor`-generated installations :::{note} Many `constructor` installers ship `conda` (Miniconda, Miniforge, etc), and offer the user to _initialize_ the installation. This adds further changes to the system configuration. These changes won't be reverted by simply deleting the installation directory. If you want to revert these changes, you can execute this command _before_ deleting the installation directory. ```bash $ conda init --reverse --all ``` Use the `--dry-run` flag if you want to check what things will be reverted before actually doing it. ::: ### Windows On Windows, `constructor`-generated installations include an uninstaller executable, which is also exposed in the Control Panel menu "Add or remove programs". The uninstaller executable is located in the installation directory, and is named `Uninstall-.exe`. Once opened, the uninstaller will guide the user through the uninstallation process. It will also remove the installation directory, and the uninstaller executable itself. In certain cases, some dangling files might be left behind, but these will be removed in the next reboot. If you want to perform the uninstallation steps manually, you can: 1. Remove the installation directory. Usually this is a directory in your user's home directory (user installs), or under `C:\Program Files` for system-wide installations. 2. In some installations, remove the entries added to the registry. System installs will use `HKEY_LOCAL_MACHINE` as the top level key; user installs will use `HKEY_CURRENT_USER`. You might find these items: - Uninstaller information: `TOP_LEVEL_KEY\Software\Microsoft\Windows\CurrentVersion\Uninstall\`. - Python information: `TOP_LEVEL_KEY\Software\Python\PythonCore\`. Verify that these entries correspond to the installation directory you removed in step 1. - PATH modifications. You'll need to remove the entries corresponding to the installation directory, but leave the other locations intact. This is better handled via the UI available in the Control Panel (follow [these instructions](https://docs.oracle.com/en/database/oracle/machine-learning/oml4r/1.5.1/oread/creating-and-modifying-environment-variables-on-windows.html)). The actual registry keys (in case you are curious) are located in: - System install: `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PATH`. - User install: `HKEY_CURRENT_USER\Environment\PATH` 3. In some installations, remove the associated shortcuts under `%APPDATA%\Microsoft\Windows\Start Menu\Programs\` (user installs) or `%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\` (system installs). You can enter these paths directly in the Windows Explorer address bar to open them. ### macOS and Linux Remove the installation directory. Usually this is a directory in your user's home directory (user installs), or under `/opt` for system-wide installations.