volks73 / cargo-wix

A cargo subcommand to build Windows installers for rust projects using the WiX Toolset
https://volks73.github.io/cargo-wix
Apache License 2.0
317 stars 26 forks source link

WiX V4 support #174

Open roblabla opened 1 year ago

roblabla commented 1 year ago

WiX is currently in the process of releasing a new version, WiX V4. Its API will be totally incompatible with the current WiX version (it will have only a single command called wix that combines candle, burn, etc... - and there are also various breaking changes to the XML).

Will cargo-wix try to support WiX V4? Or should a new cargo-wix4 project be created, dedicated to WiX v4 support?

volks73 commented 1 year ago

Good question! I have been distracted with other projects, so I was not aware of WiX v4 and the major change.

I have been thinking about a "major new version" for this project for a while, a "Beta-4" or v0.4. There are several things I think could be done better, like workspaces and handling the CRT issue (which may no longer really be an issue). I have just never been sure how much of a rewrite this new version would be. Maybe the next "major version" of this project can target WiX v4, which would require some significant rewriting to support? The v0.4/Beta-4 aligns with WiX v4, by coincidence, not by planning on my part.

However, I could also see rewriting to support both WiX v3 and v4 and maybe there was some way to automatically detect which version is installed/available?

A clean slate implementation as a separate cargo-wix4 project is alluring.

None of this answers your questions. I am open to recommendations and would like to hear suggestions on how to move forward with WiX v4.

filips123 commented 1 year ago

WiX v4 has now been released. The release notes are here and there is also some documentation about upgrading from v3 to v4.

I haven't really checked everything that has changed, but I think the following changes affect cargo-wix the most:

If you would like to support both versions, there is probably some way to detect for which WiX version main.wxs is. If there isn't, there could probably just be a configuration option to let users choose which version to use. Because cargo-wix mainly only interacts with WiX when building and signing installers, it might actually be feasible to support both versions.

Another option could be to continue with the same cargo-wix project but only support WiX v4 in future versions. Although it may still be too early as WiX v4 was released less than a month ago, people will eventually have to switch to it, as WiX v3 will become unmaintained. And if you needed to publish some fixes for v3 versions, you could publish them as v0.3.X (or whatever the latest version that would support WiX would be).

roblabla commented 1 year ago

Started experimenting with v4 support in https://github.com/roblabla/cargo-wix/tree/v4 . I think I got most of it working. Here's a braindump:

Main difference was dropping linker-args (since there's now just a single command that does both compilation and link), and adding a new exts field in the Cargo.toml/commandline to provide extensions to cargo-wix so it can handle their installation through wix extension add along with passing them to wix build. Contrary to wix3, wix4 does not come pre-installed with any extensions, so you have to install WixUi/WixUtil/WixBal.

It's possible to detect whether the provided template is v3/v4 just by looking at the namespace of the top-level Wix element, which will have http://schemas.microsoft.com/wix/2006/wi for v3 and http://wixtoolset.org/schemas/v4/wxs for v4. Whether that's desirable though, is something I'm not entirely sure of. I think wix3 and wix4 interfaces are different enough that having a single project support both would lead to some awkwardness (wix4 has a built-in package manager to get extensions, it doesn't have a split compiler/linker, its XML structure is entirely different etc...).

IMO, it's better to have a separate cargo-wix4 project dedicated to supporting the new wix4 interface.

Auto-conversion through wix convert is possible, but broken in various ways. Obviously, there are some edge-cases it just doesn't know how to convert - though those cases are fairly few. However, the feature is broken in another more annoying way: It will silently fail to convert any file that doesn't specify "utf-8" encoding in its <?xml?> header. In cargo-wix, the provided template uses windows-1258 encoding instead, so wix convert will just... do nothing. It will exit without printing any output or raising any error. This makes any kind of automatic conversion a non-starter.

volks73 commented 1 year ago

Interesting! Thank you for experimenting and looking into wix4. I have not had a chance to look at wix4 at all since it was released.

Is it possible to have both wix3 and wix4 binaries installed at the same time? I think this would ultimately answer the question of a separate cargo wix and cargo wix4 command. If only one is allowed, then a separate project/sub-command makes sense because the dependencies are vastly different. If both are allowed, then possibly separate modules for v3 and v4 within this command/project with auto-detect on the namespace and a warning message if the incorrect binary is installed might be the better way to go.

However, I would actually think about renaming this project to cargo wix3 and make cargo wix always the "latest" stable version, i.e. wix4. I am concerned about projects using cargo wix and breaking those workflows.

The bit about the auto convert and its silent failing is annoying and frustrating. I would equate wix3 vs wix4 to the Python 2 vs 3 change that occurred a while ago in the Python world. It really is a major break. At least the namespace is different and can be used to detect the version.

roblabla commented 1 year ago

Is it possible to have both wix3 and wix4 binaries installed at the same time? I think this would ultimately answer the question of a separate cargo wix and cargo wix4 command.

Yes, I currently have both versions installed and there's no issue. Wix4 is installed via dotnet tool install, goes in C:\Users\%USERNAME%\.dotnet\tools, and its main binary is wix, while wix3 is installed via an MSI, goes in C:\Program Files\Wix Toolset, and uses candle/light.

erenturkm commented 1 year ago

Hi,

I understand that this is a major change of the project. However since cargo-wix is the only project to create msi installer for rust applications and the last wix3 (version 3.11.2) was released almost 4 years ago, I believe we need more clarity.

Are we talking about we are near to support V4 in couple of months, or we need to do a major rearchitecture with no timelines?

I am relatively new to rust (but seasoned developer) so, probably can not help in the second case. However I desperately need a Windows installer solution for my current project and rather not go through the Wix3 route if possible. (Still scared from dealing with customers who have waited too long to migrate .net 4.8 to core)

I can test the beta versions of the new project if you are in the first case.

roblabla commented 1 year ago

@erenturkm There hasn't been much movement. There's no real rush to migrate to wix4 - it's still a relatively new piece of software that's likely to have a lot of rough edges (see for instance the whole wix convert not working with non-utf8 charset above), and wix3 works just fine - its only real shortcoming is the lack of support for ARM64.

I've been meaning to move to wix4 at $WORK so I can properly test-drive the fork on a real codebase, but time's been short. I can't promise any timeline here.

Unless you need a feature in Wix4, I really recommend sticking to Wix3 for now. A lot of the information about Wix you can find online is incompatible with Wix4, and writing installers is hard enough as-is without the additional hurdle of having to understand the differences between the two...

volks73 commented 1 year ago

I have not had capacity to look too deep into wix4. @roblabla has done an excellent job starting the ball rolling for wix4 support. I defer to roblabla for the immediate future on all things wix4, and I agree with roblabla. There is nothing wrong with WiX v3 and WiX v4 is still very new.

I would like to add/mention, it is possible to create an installer for a Rust project without this subcommand. This subcommand is really just a wrapper around the WiX v3 tools that "maps" the project's manifest file to the XML schema of the WiX v3 candle and light to create a wxs file. This mapping only needs to be done once, and it could be done manually for WiX v4. After the mapping, the wix command for WiX v4 can be executed directly without using this subcommand at all. In many ways, this subcommand is actually a glorified batch (DOS) script (#64), :grin:.

There is nothing special about a Rust project for creating MSIs. MSIs are an extra or separate publishing step. NSIS, Innosetup, InstallShield, and WiX are all tools that could be used to create installers. All of these tools could be used with a Rust project. WiX was just the easiest (for me) to use, learn, and wrap as a subcommand.

juliusl commented 6 months ago

I was looking into what it would take to support wix4. It's actually not too bad but there are some gotchas.

Finally the command turns into this:

wix build -o installer.msi .\wix\main.wxs -ext WixToolset.UI.wixext

However, without cargo wix the above would fail which is expected because the .wxs will be missing the pre-processor variables cargo wix injects:

<?define Version = "0.1.0"?>
<?define CargoTargetBinDir = "target\release\"?>
<?define CargoTargetDir = "target"?>

After adding this to the .wxs file manually the build command will work and an msi will be created.

My takeaways are:

@volks73 would you be open to PR's that add some level of support for wix4?

volks73 commented 6 months ago

@juliusl Thank you for the investigation into WiX4 support. The information and summary are greatly appreciated.

I would be open to PR's that add support for WiX4.

slonopotamus commented 5 months ago

Meanwhile, there's WiX 5 already!

juliusl commented 3 months ago

@volks73 I've finally had time to work on this, I put up a draft PR: https://github.com/volks73/cargo-wix/pull/295

Putting it up first as a draft to get early feedback. The design adds two new flags and usage would look like this:

cargo wix --toolset modern --toolset-upgrade inplace

I still need to add and do a lot of testing, but I think I have all the important bones in the PR at the moment.

P.S @slonopotamus this should support wix5 too