Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement .msi support for Windows targets #116

Open
John-Nagle opened this issue Jun 9, 2022 · 11 comments
Open

Implement .msi support for Windows targets #116

John-Nagle opened this issue Jun 9, 2022 · 11 comments

Comments

@John-Nagle
Copy link

Windows support is still unavailable, after four years.

Anyone doing that?

Discussion: https://internals.rust-lang.org/t/cross-platform-bundling/16773

Useful crate for reading and writing .msi files: "rust-msi".

I'd like to have minimal .msi support - install, uninstall, maybe upgrade. No registry keys, no signing. Enough that a cross-plaform program can be made a first-class Windows application without difficulty.

(It's sort of possible to do this with the Wix or Tauri toolchains, but those are whole systems that bypass or wrap Cargo. There used to be "tauri-bundler", but it's been discontinued, and it relies on "candle.exe" and "flame.exe" from Wix, which are also being discontinued as those systems become more monolithic.)

@mdsteele
Copy link
Collaborator

I'm not aware of anyone currently working on this. PRs would be very welcome!

A while back I took an initial stab in src/bundle/msi_bundle.rs at using the msi crate to create a minimal installer, but I lacked the background knowledge to know exactly which tables need to be populated and how, and I don't have a Windows machine readily available for testing, so of course I didn't get very far.

If someone wants to try getting MSI bundling working, the code currently in msi_bundle.rs should give some idea of how to go about using the msi crate to populate the installer tables, but don't hesitate to completely rewrite what's already in there if needed.

@John-Nagle
Copy link
Author

but I lacked the background knowledge to know exactly which tables need to be populated and how, and I don't have a Windows machine readily available for testing, so of course I didn't get very far.

That's where I am. I took a look at this, and it clearly requires a lot of Microsoft-specific knowledge. A minimal bundler, just taking the info from Cargo.toml and generating a .msi file, would be very useful, and probably not too hard for someone who works in the Microsoft ecosystem. There are lots of other things you can do in a .msi file, most of which are not essential to making cross-platform Rust programs.

@JessicaTegner
Copy link

JessicaTegner commented Feb 17, 2023

hi
I can't help but notice that there is an inconsistency in what we want here.

On MacOS, we get an .app bundle, which is essentially just a folder, while as on Windows (and for that matter also linux) we want, or are already getting a package like format.

What is the end goal? To "just" get a package format? In that case, #113 would probably also need to be implemented to be consistent throughout platforms.
If we "only" want a folder that another tool can then package up as needed (fx: zip, tar etc) we would need to rethink Windows support and change how Linux are done.

In any case, my primary OS is Windows and I have some experience on the MS side, so I would be happy to give this a stap, just wondering which way we are going.

@John-Nagle
Copy link
Author

The goal is to create a file in the format which most users of the platform would consider a normal application to be installed.

@JessicaTegner
Copy link

But that can be anything, as there's no singular truth to what format to expect for a Windows installer.

It can be a .msi, an .exe, made with Wix,, MSI, NSIS, 7ZIP or any other number of tools.

@mdsteele
Copy link
Collaborator

I think there's room for supporting multiple packaging options for a given OS (selectable via command-line flag). The main reason for wanting to support MSI installers in particular (rather than just a plain .exe) is to allow for bundling resources/libraries that the main executable depends on. But if someone wants to try implementing a different Windows packaging scheme instead of (or in addition to) MSI, that would be great too.

@John-Nagle
Copy link
Author

The general idea is to have a distribution format which which non-technical Windows users are comfortable. This excludes raw .exe and .zip. It should be something that doesn't generate scary security warning messages on installation. Ideally, something you could submit to the Windows app store.

@JessicaTegner
Copy link

maybe it's worth taking a look at https://github.com/tauri-apps/tauri/tree/dev/tooling/bundler since it's based on this.
In addition, they seem to be using WIX (an easier to use, xml version of msi).
It sitll produces MSI, but has a toolset to easily generate them based on a xml configuration file.

@John-Nagle
Copy link
Author

maybe it's worth taking a look at https://github.com/tauri-apps/tauri/tree/dev/tooling/bundler since it's based on this.

That's not cross platform. You can only build Windows executables on Windows. It uses DLLs from an old version of Wix.
See https://github.com/tauri-apps/tauri/blob/dev/tooling/bundler/src/bundle/windows/msi.rs

If you're running on Windows, you can use a Microsoft tool to do this.

The goal here is to be able to generate installables for all the Rust-supported desktop platforms without having one of each on your desk. Rust can generate executables, but the last step, the installer, isn't portable yet.

@avsaase
Copy link

avsaase commented Mar 17, 2023

I've been following this issue for a while so I'll give my 2c.

The compilation step is already not completely cross platform because you cannot cross-compile for MacOS. So in practice if you want to support all platforms you're already working with multiple machines or something like GitHub Actions.

For a side project I'm using cargo-bundle for the Mac app bundle and cargo-wix for the Windows msi installer. The latter is not really maintained anymore and requires quite a bit of fiddling with xml files. It would already be a huge win if all the configuration of the bundling/installer compilation could be handled by cargo-bundle, even if the process is not cross platform.

@JessicaTegner
Copy link

Just chiming in again with the following. What do you think @burtonageo

We could implement a NSIS package option for Windows Target as was briefly talked about in tauri-apps/tauri#6474 as WIX is a pain to work with.
And before we restart the whole cross platform support thing, which we all agree is a valid point, it looks like NSIS (makensis) can be installed from homebrew or macports.
I know it's not pure, without external dependencies, but I feel this is the best solution from the simple fact that it's 10x easier to implement, customize, theme and it comes with everything that MSI/WIX comes with and much, much more.

And bonus point: I feel if we ask nicely, we could get the tauri people to assist on this, since they already have it done (and are also pushing people toward that for the same reasons)

SomeoneToIgnore added a commit to zed-industries/zed that referenced this issue Mar 7, 2024
Changes Zed CI to build and upload Linux nightly bundles.

* `todo!(linux)` are replaced with `TODO linux` to make `todo!`-based
workflows more convenient
* renames `run-build-dmg` label into `run-bundling`, also renames a few
GH Actions entries to be more generic
* make another upload path for Linux, which keeps a separate file with SHA to version the nightly artifact.
* adds a `*.deb` package building with a couple of caveats, marked with
new `TODO linux` entries:

1. `cargo-bundle` is not very flexible, so it generates artifacts with
the structure and names that we're unable to alter before/during the
generation.
For that, a set of extra steps is made by repacking the *.deb package —
this is not very portable between different Linux distros, so later one
needs to find a way to combine multiple package types in this script.

2. `cargo-bundle` is not able to properly generate the *.msi bundle
despite declaring it in the features:
burtonageo/cargo-bundle#116
Windows needs to invent its own way of bundling or fix the tool.

3. Both `cli` and `zed` binaries are added into the archive under
`/usr/local/bin/` path with their `-$channel` suffix
(-nightly/-preview/-dev/-stable) and a `/usr/local/bin/zed ->
/usr/local/bin/cli-nightly` symlink is made to make CLI work as Zed
launcher:
```
~/work/zed kb/linux-nightly:origin/kb/linux-nightly*​ ❯ dpkg -c target/zed_amd64.deb 
drwxr-xr-x allaptop/allaptop 0 2024-03-06 00:53 ./
drwxr-xr-x allaptop/allaptop 0 2024-03-06 00:53 ./usr/
drwxr-xr-x allaptop/allaptop 0 2024-03-06 00:53 ./usr/local/
drwxr-xr-x allaptop/allaptop 0 2024-03-06 00:53 ./usr/local/bin/
-rwxr-xr-x allaptop/allaptop 8746832 2024-03-06 00:53 ./usr/local/bin/cli-nightly
-rwxr-xr-x allaptop/allaptop 689078560 2024-03-06 00:53 ./usr/local/bin/zed-nightly
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/applications/
-rw-r--r-- allaptop/allaptop       153 2024-03-06 00:53 ./usr/share/applications/zed.desktop
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/icons/
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/icons/hicolor/
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/icons/hicolor/1024x1024@2x/
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/icons/hicolor/1024x1024@2x/apps/
-rw-r--r-- allaptop/allaptop    716288 2024-03-06 00:53 ./usr/share/icons/hicolor/1024x1024@2x/apps/zed.png
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/icons/hicolor/512x512/
drwxr-xr-x allaptop/allaptop         0 2024-03-06 00:53 ./usr/share/icons/hicolor/512x512/apps/
-rw-r--r-- allaptop/allaptop    239870 2024-03-06 00:53 ./usr/share/icons/hicolor/512x512/apps/zed.png
lrwxrwxrwx allaptop/allaptop         0 2024-03-06 00:53 ./usr/local/bin/zed -> /usr/local/bin/cli-nightly
```

But the CLI does not work under Linux yet and there's no way to install
that CLI from Zed now; Zed binary itself is not able to open
`file/location:12:34`-like things and set up the env properly, but is
able to start or open a directory.

So, this structure can be considered temporary and changed, if needed.

4. Zed Nightly on Linux does not know how to update itself, so all
nightly publishing is not picked up automatically.

5. Rust cache from `main` builds does not get shared between CI jobs,
due to being run in a different CI job that forms a different CI key, so
```
      - name: Cache dependencies
        uses: swatinem/rust-cache@v2
        with:
          save-if: ${{ false }}
```
would not work.
This makes Linux bundling jobs long.

Release Notes:

- N/A
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants