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

proposal: cmd/go: create manifest when building for Windows #44466

Closed
networkimprov opened this issue Feb 20, 2021 · 17 comments
Closed

proposal: cmd/go: create manifest when building for Windows #44466

networkimprov opened this issue Feb 20, 2021 · 17 comments

Comments

@networkimprov
Copy link

Quoting @jstarks from #17835 (comment):

Various Win32 API behavior is tweaked according to the contents of the manifest. We've already identified the long path behavior as one case, but there is various compatibility-related behavior keyed off the more generic supportedOS element:

  • GetVersion only reports the correct version if you advertise Windows 8+ support.
  • The heap applies some extra optimizations to limit commit use if you advertise Windows 10+ support.
  • The system is more aggressive about faulting on invalid handle use if you advertise Windows 10+ support.
  • CreateFile and GetOverlappedResult have stricter behavior if you advertise Windows 10+ support.

Regardless what is decided about the long path bit, it may be in Go's interest to make setting these easy or automatic rather than rely on each application to construct and link a manifest manually.

[End quote]

Therefore I propose:

  • Build-time recognition of a manifest source file for GOOS=windows.
  • Automatic generation of a manifest (when none found) with the features above.
  • Issue an error if it finds a manifest without all those features. (And provide a way to suppress this?)
  • Allow user modification of a generated manifest (e.g. to include icon, etc).

Happy to amend the proposal if ppl object to any of the above, or need more.

cc @alexbrainman @zx2c4 @eliasnaur @andydotxyz @mattn @rasky
@gopherbot add OS-Windows

@ianlancetaylor
Copy link
Contributor

Sorry for the dumb question, but what is a manifest and why do we want one? A web search was not obviously helpful.

@andydotxyz
Copy link
Contributor

  • Issue an error if it finds a manifest without all those features. (And provide a way to suppress this?)

I’m not too sure that I agree a compile error should be generated if a manually provided manifest does not include entries you recommend... if one is added we could assume the developer knows what they are doing.

@andydotxyz
Copy link
Contributor

The automatically added manifest for Fyne is at https://github.com/fyne-io/fyne/blob/ec966e729738083602e632c4092dfc35be65ed6f/cmd/fyne/internal/templates/data/app.manifest, assuming we are talking about the same thing.

@rasky
Copy link
Member

rasky commented Feb 20, 2021

Sorry for the dumb question, but what is a manifest and why do we want one? A web search was not obviously helpful.

A manifest is a XML document embedded in the binary that informs the kernel about properties of the binary. The reasons why Go might want to generate one by default is those listed by Liam in the comment above. FWIW, I agree that Go should generate a default manifest (for both internal and external linking).

@zx2c4
Copy link
Contributor

zx2c4 commented Feb 20, 2021

I'm not sure this is a rabbit hole we want to go down. There are many tools that create Windows file resources -- windres, llvm-rc, and three or four I've seen that are written in pure Go -- that Go can readily digest, as these are just COFF objects with a .rsrc section in .syso files.

The topic of creating resources is complicated and flexible, with pretty large degrees of complexity. This proposal concerns XML manifests, but the proposal contains errors of understanding in what the XML manifest actually supplies, when it mentions:

Allow user modification of a generated manifest (e.g. to include icon, etc).

Icons aren't in the manifest; icons go in the resource. The manifest goes in the resource. The version information goes in the resource. All manner of other things can go in the resource.

So what are you proposing? That Go's build tools incorporate ways of making custom resource files, with all sorts of things like icons and XML manifests and files and version info and whatever else? Or that Go's build tools generate a resource with a fixed static non-editable manifest, and nothing else?

In other words, it would be useful to know what you actually have in mind, because that leads us in very different directions.

Whether Go grows a full-blown resource assembler and XML manifest generator embedded in that, or if Go just starts adding a default manifest, uneditable, in some fixed resource, won't change the fact that people are still going to prefer to provide their own resource files (in a .syso file, as they do now), generated by a tool that's more customizable or more desirable than whatever we bake into Go.

That, and the misunderstandings of the proposal in the first place, make me think we shouldn't bake this into Go.

And I'll note that Go doesn't support creating .app bundles and generating plists for macOS apps either; these are left for platform tooling.

So rather than this, what if we supply a good alternative. If you don't like windres or the various Go tools, we could write a little tool called x/sys/windows/rsrcgen, which would be invokable from lines like //go:generate go run golang.org/x/sys/windows/rsrcgen -o rsrc.syso ... that would have the various aspects of customization that you desire.

@networkimprov
Copy link
Author

networkimprov commented Feb 20, 2021

Apologies for my incomplete understanding, I haven't yet started using manifests or resources in my Windows apps, tho I plan to.

EDIT: doesn't the manifest reference a resource icon?

The proposal is based entirely on @jstarks recommendations for a default manifest, which I quoted. I'd guess that letting users read & edit a generated manifest would be preferable to constructing an implicit one if none exists.

Jason's x/sys/windows/rsrcgen concept also sounds valuable, but would it address the need for a default manifest? I agree that Go doesn't need a general-purpose Windows & MacOS resource toolkit.

@zx2c4
Copy link
Contributor

zx2c4 commented Feb 20, 2021

EDIT: doesn't the manifest reference a resource icon?

No, not that I'm aware of. Typically the icon of an .exe is the first ID_ICON resource of the resource section. So you generally have something like this in a .rc file:

#include <windows.h>

#pragma code_page(65001)

LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml
7 ICON appicon.ico

VS_VERSION_INFO VERSIONINFO
FILEVERSION    1, 0, 0, 0
PRODUCTVERSION 1, 0, 0, 0
FILEOS         VOS_NT_WINDOWS32
FILETYPE       VFT_APP
FILESUBTYPE    VFT2_UNKNOWN
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK 040904b0
    BEGIN
      VALUE "CompanyName", "Some Company"
      VALUE "FileDescription", "some file description"
      VALUE "FileVersion", "1.0.0.0"
      VALUE "InternalName", "some-name"
      VALUE "LegalCopyright", "Copyright © 2021 Somebody."
      VALUE "OriginalFilename", "some-name.exe"
      VALUE "ProductName", "Some Name"
      VALUE "ProductVersion", "1.0.0.0"
      VALUE "Comments", "https://www.golang.org/some-webpage/"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x409, 0x4b0
  END
END

That highly customizable file references the app icon as well as the manifest.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="some-name" type="win32" />
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <!-- Windows 10 -->
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
        </application>
    </compatibility>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
        </dependentAssembly>
    </dependency>
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
        <windowsSettings>
            <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
            <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware>
        </windowsSettings>
    </application>
</assembly>

That even more highly customizable XML manifest then contains information about what Windows version behaviors it should have, which variety of HiDPI mode it wants to use, which DLL versions it wants, and a million other fine nobs for controlling the binary's behavior.

@rsc
Copy link
Contributor

rsc commented Mar 10, 2021

It sounds like @zx2c4 has suggested ways to get manifests without go command support, and @networkimprov doesn't have a use for it yet.

@rsc
Copy link
Contributor

rsc commented Mar 10, 2021

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@rsc rsc moved this from Incoming to Active in Proposals (old) Mar 10, 2021
@networkimprov
Copy link
Author

A Windows Kernel Team Lead suggested that Go enable certain Windows features by default in a manifest.

In Visual Studio, "By default the project properties of new projects are set to generate a manifest file."
https://docs.microsoft.com/en-us/cpp/build/manifest-generation-in-visual-studio?view=msvc-160

I need a manifest for the next release of the mnm client app, which supports Windows, MacOS, and Linux. I hadn't created one because I didn't realize it was recommended/necessary.

Folks tend to assume that cross-platform tools like Go follow best practices on each supported platform.

@zx2c4
Copy link
Contributor

zx2c4 commented Mar 10, 2021

mingw won't make you a manifest either. And neither will microsoft's command line compiler or clang's.

Visual Studio will set you up for that, because it's a full blown IDE with templates and stuff of best practices.

I see Go's tooling more like mingw and less like an IDE.

@networkimprov
Copy link
Author

From a quick search, I gather that the Java and Python runtimes for Windows include a manifest.

Go is easy to use, and mostly does the right thing behind the scenes. It may not be an IDE, but it's a lot more than a compiler.

@zx2c4
Copy link
Contributor

zx2c4 commented Mar 10, 2021

Java.exe executes jar archives. Python.exe executes .py files and module directories. The comparison doesn't hold.

@networkimprov
Copy link
Author

I raised Java & Python because they are closer to Go's market than C compilers.

@rsc
Copy link
Contributor

rsc commented Mar 24, 2021

It sounds like there is not a pressing need for this and the most closely analogous tools do not provide it, so it seems like we should not do this.

@rsc
Copy link
Contributor

rsc commented Mar 24, 2021

Based on the discussion above, this proposal seems like a likely decline.
— rsc for the proposal review group

@rsc rsc moved this from Active to Likely Decline in Proposals (old) Mar 24, 2021
@rsc
Copy link
Contributor

rsc commented Apr 1, 2021

No change in consensus, so declined.
— rsc for the proposal review group

@rsc rsc moved this from Likely Decline to Declined in Proposals (old) Apr 1, 2021
@rsc rsc closed this as completed Apr 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

No branches or pull requests

7 participants