I've finally found a reasonably good way to build installable Windows executables cross-platform, from Linux. (The Rust ecosystem can generate an executable cross-platform, but not package it with its assets for installation.) I'm using Inno Setup under Wine. This is open source, and doesn't require Microsoft Visual Studio. It makes a rather classic installer. The program was originally released in 1997 and is still updated, so it looks a bit last-cen.
You create a script file (there's a "wizard" to help with this) and run the "compiler" to create an executable installer containing whatever files your program needs. This is reasonably straightforward. Here's an example of a script file:
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "Sharpview"
#define MyAppVersion "0.3.0"
#define MyAppPublisher "Animats"
#define MyAppURL "https://www.animats.com/viewer/"
#define MyAppExeName "sharpview.exe"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools Generate GUID inside the IDE.)
AppId={{39CDF42B-68F3-49C9-B505-8D4EFB6C151A}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DisableProgramGroupPage=yes
InfoBeforeFile=Z:\home\john\projects\sl\SL-test-viewer\sharpview\src\assets\docs\preinstall.txt
InfoAfterFile=Z:\home\john\projects\sl\SL-test-viewer\sharpview\src\assets\docs\postinstall.txt
; Remove the following line to run in administrative install mode (install for all users.)
PrivilegesRequired=lowest
OutputBaseFilename=sharpviewsetup
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "Z:\home\john\projects\sl\SL-test-viewer\target\x86_64-pc-windows-gnu\release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "Z:\home\john\projects\sl\SL-test-viewer\sharpview\src\assets\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
This is simple, but has many absolute path names. Under Wine, the "Z drive" is the Linux file system, so filenames such as Z:\home\john\projects\sl\SL-test-viewer\sharpview\src\assets\docs\preinstall.txt
are how Wine emulating Windows gets files from outside the Windows world.
Most of the info needed is available in Cargo.toml files. So someone into Cargo tooling might be interested in creating a Cargo build tool to generate these things. All the tool needs to do is put all the necessary Cargo info into #define statements in a generated file, and have an #include in the main Inno script to use it, then execute the Inno "compiler" under Wine.
So that's a way to generate Windows applications without using any Microsoft products.