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

Open
networkimprov opened this issue Feb 20, 2021 · 7 comments
Open

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

networkimprov opened this issue Feb 20, 2021 · 7 comments
Projects
Milestone

Comments

@networkimprov
Copy link

@networkimprov networkimprov commented Feb 20, 2021

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

@ianlancetaylor ianlancetaylor 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.

@andydotxyz
Copy link
Contributor

@andydotxyz andydotxyz commented Feb 20, 2021

  • 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

@andydotxyz andydotxyz commented Feb 20, 2021

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 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 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 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 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Proposals
Incoming
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants