-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Support application manifests on Windows #721
Comments
Technically, manifest is just part of resource if embedded, and such resource is compiled by system linker.
There is other way to embed manifest: register it in resource file ( However, it may not be convenient to manage manifest and resource file just to set UAC. Now my personal thought. I don't think rustc should handle manifest or resource in general. I think It's not job of rustc to handle version/dependency issues as well - it's cargo job. I have no idea if it's good for cargo to embed manifest or not. |
(@vadimcn: I'm curious if the gdb crash in rust-lang/rust#11207 was specifically due to |
My only reservation about shipping a pre-built manifest.o was that currently rustc contains no logic for searching for .o files. Adding it just for the sake of Windows manifests would be a bit of overkill, IMO, when it isn't that hard to run the |
If we want to claim we properly support Windows then Cargo will need to be able to generate manifests and give them to rustc so it can link them in. Definitely something that should be worked on post 1.0. As for |
Although I agree that Cargo ought to have a lot of involvement with manifests, the problem is that, for the application manifest in particular, the version numbers of dependencies are supposed to match those of the binaries linked against at compile time. The job of compiler/linker is handled by rustc, not by Cargo. As such I think it is preferrable for rustc to handle manifest generation whilst providing support for Cargo to control the process. With some simple controls in Rust it should be easy to build an app with slightly customised manifest (e.g. specify a version for your app), without requiring you to build using Cargo. N.B. if Cargo generates the entire manifest file by itself this implies it has to handle all aspects of the manifest, not just versioning, and since the manifest may change program behaviours, compiling using Cargo becomes the only option. Also regardless of how it is implemented users should still be able to add their own custom parts to the manifest somehow or other. User providing their own complete manifest file I think is highly undesirable when you want Cargo to control the versioning. Regarding a default manifest, I think there should indeed be defaults for the manifest but there is not one single default manifest that can be applied to all applications. For one, you'd most likely want a different manifest for 64-bit vs 32-bit, but for a less trivial example, I believe applications should default to requiring version 6 of COMCTL32.dll, but if the application does not use COMCTL32.dll then this should clearly not be in the manifest. I should note that the main purpose of this discussion is not to solve the UAC problem nor to provide default manifests to applications. Rather it is about how Rust might be able to provide easy access for the user to the (limited) functionality available in manifests and how Rust/Cargo can integrate with Windows for the main purpose of handling versions/dependencies. Good defaults, compatibility and removal of the UAC issue are just things that should come out of this process 'for free' and solutions that only solve these problems (especially things such as |
What's the status on this? |
@nabijaczleweli Absolutely zero progress. |
@DeadNumbers That's neat, I used this technique instead, though. |
@nabijaczleweli - That link is dead, but I assume your repo at https://github.com/nabijaczleweli/cargo-update shows the technique |
Yeah, Katt must've killed his repo.
|
Could this be done 'magically' by cargo when it sees a .manifest file in the right location, e.g. at Then it could simply pass the option /MANIFESTINPUT, with that manifest file, to Although it does have a Of course if cargo could install arbitrary files besides the binaries themselves rust-lang/cargo#2729 then that might help with this too, with |
This is required in order to use the new (added in 2019) UTF-8 code page on Windows. While I think that it would also be nice to have a higher-level Cargo flag for that, embedding manifests is the first step. |
One thing worth mentioning is that the manifest can be placed side-by-side with the executable as a workaround for now (e.g. ferris.exe.manifest), though not automatically rust-lang/cargo#2729. I'd also like to see the solution be generalized enough to support the embed of icons and other resources too. |
@riverar could you clarify the part here ? |
Currently Rust has no support for adding manifests to Windows executables (.exe and .dll) despite some previous failed attempts (see rust-lang/rust#11207).
Application manifests are essentially just an XML resource which is embedded in the executable and is read by Windows to establish how the executable should be run and which DLLs it depends on. There are also other types of manifests which follow the same basic schema but have slightly different purposes, e.g. you can publish configuration files to install on the system which specify that a particular version of a DLL installed is backwards compatible and should be used in place of a whole range of previous version numbers.
Manifests may be useful for several reasons in Rust:
There is another significant feature which should NOT be used by default, which is that you can specify which OS version behaviours are supported by your application, which effectively requests certain APIs to behave differently. The reason this is bad is that it is impossible to know if anything that plugs in to your app (e.g. shell extensions, which come in through e.g. common file dialog) also supports these behaviours, so it is generally not safe to turn them on. Even so, for flexibility it would be good to allow users to explicitly request these behaviours.
I believe that the scope and format of these application manifests is sufficiently limited (particularly parts most relevant to Rust) that the Rust ecosystem ought to have the ability to generate these by itself with the help of Rust language attributes to specify particular items/settings to go into the manifest. Having some sane approach to version numbering (which ties into Cargo somehow) would be massively beneficial and avoid all sorts of problems with incompatible binaries. The version numbers for manifests are required to have four parts 0-65535 (without exception) which Microsoft expliclty labels as major.minor.build.revision in the documentation, and changes in the last two are not to break backwards compatibility, which would generally be done by incrementing the major version rather than minor. This I find to be a good link on the motivations behind the versioning system on Windows and there might be no reason why Rust couldn't implement such automatic revision number stepping on top of a similar version attribute.
Likely people will want to override whatever manifest Rust provides (or disable it completely) and this should be catered for. However, it could potentially be useful to have an option for some sort of hybrid approach where Rust can change certain fields such as version number from an existing manifest file. N.B. application manifests are always called filename.exe.manifest or filename.dll.manifest so they could always simply be detected from the filesystem rather than specified on the command line or in an attribute (though being able to specify an alternative manifest path via an attribute may be another very useful feature).
As a demonstration of most of the things I've said, and to demonstrate how simple the XML is, I have prepared an example, which in this case would normally be called helloworld.exe.manifest:
This shows providing version number and description of your app, referencing DLLs by assembly name and version which may be Rust built or on the system, referencing a private DLL which must match the expected file using SHA1 hash, activating XP styles by requesting version 6 of common controls, telling UAC that no special privileges are required (even if the app was called setup.exe) and indicating that your app is DPI aware and that the printer driver should run in a separate process (so it doesn't crash your app if it is faulty). If your app were code signed it would have a public key token as COMCTL32.dll does.
I think there's still a lot of work to do on reconciling differences with how Rust is currently and how these features could possibly be implemented, but I think once Rust (and Cargo too most likely) is capable of all the things above and can generate the manifest mostly by itself, things are looking pretty strong on Windows.
The text was updated successfully, but these errors were encountered: