Inject windows manifest into binary built by "go build"

503 views
Skip to first unread message

Augusto Roman

unread,
Sep 15, 2020, 11:41:45 AM9/15/20
to golang-nuts
I’m trying to embed windows manifest information into an exe. I’ve generated the resource.syso file using goversioninfo and it works fine when that file is in the target package. But now I want to do something slightly different: I want to use go build module/package/cmd/binary with a locally-generated resource.syso. Is there a way to force the go linker to include the local manifest file? Or somehow inject the manifest into a built exe? Currently I have two workarounds that I’m trying to avoid:
  1. The main package of the target binary is incredibly thin and I duplicate the main package locally and compile with the generated syso file.
  2. I can use modcacherw to allow modifications of the imported module package and modify the source folder of the binary and inject the syso file.
Any way to make go build just link in the file?

- Augusto

Alex

unread,
Sep 15, 2020, 5:27:26 PM9/15/20
to golang-nuts
> Is there a way to force the go linker to include the local manifest file? 
A syso file is the way. 

> Or somehow inject the manifest into a built exe?
Readup on mt.exe, I haven't used it on go programs but it might work.

Tho I'm not quite sure what you're trying to do and what the problem is. 
What do you mean by "locally-generated resource.syso" and how is it different from a syso file generated by goversioninfo?
Do you have a package that contains a syso manifest file checked into version control and you want to override it's contents on your system somehow?

Augusto Roman

unread,
Sep 17, 2020, 11:14:36 AM9/17/20
to golang-nuts
Thanks for the reply. Yes, I want to override the manifest for a particular build of the binary.

I have two modules:
2. foo.com/repo2 which will build and package the-binary with specific version and manifest information. I'd like to generate a resource.syso file in repo2 while building foo.com/repo1/cmd/the-binary.

For various unfortunate reasons, repo1 cannot have a checked-in resource.syso file that is consistent. It's possible that repo2 will want to build with multiple distinct syso manifests during a single build.

We can override version information in the binary itself using `-ldflags "-X main.version=$(VERSION)"` in repo2, but I can't figure out a way to do the same with the manifest contents.

Existing workarounds are:
1. We duplicate the main package in repo2, so that foo.com/repo2/cmd/the-binary basically defers to foo.com/repo1/cmd/the-binary/restOfMain. Then we can build the repo2 main package. This is annoying but works. Unfortunately, it means potential deviation from repo1 binaries.
2. We modify foo.com/repo1/cmd/the-binary in the go mod cache, overwriting the resource.syso file for each build.  Nobody like making the mod cache rw.

I was hoping for some equivalent of the ldflags symbol modification for the resource.syso file.

Alex

unread,
Sep 17, 2020, 11:26:25 AM9/17/20
to golang-nuts
Yeah looks like mt.exe would be the most painless method assuming it works.

Augusto Roman

unread,
Sep 17, 2020, 6:19:02 PM9/17/20
to golang-nuts
Thanks!  I'll look more into that. Unfortunately, we're not building on a windows machine. :-(  Might still be able to make something work, though.

Alex

unread,
Sep 17, 2020, 6:26:52 PM9/17/20
to golang-nuts
ohh, then you can look into windres which comes with mingw. 
It can create a C object file (from a .rc file that then references the manifest) which you then should be able to link into using the apporiate flags through cgo

Reply all
Reply to author
Forward
0 new messages