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

Any chance of supporting VERSION_INFO in addition to app.manifest? #10

Open
DavidR91 opened this issue Jun 17, 2015 · 16 comments
Open

Any chance of supporting VERSION_INFO in addition to app.manifest? #10

DavidR91 opened this issue Jun 17, 2015 · 16 comments
Labels
enhancement help wanted Just jump in! — mentoring provided :)

Comments

@DavidR91
Copy link

I really need to have an icon, a manifest and version details

Currently I'm caught between this project and https://github.com/josephspurrier/goversioninfo - which does icons and versions, but not manifests

Would it be possible to add VERSION_INFO support to rsrc? Even if it's just specifying a chunk of pre-generated binary output from another tool?

@akavel
Copy link
Owner

akavel commented Jun 17, 2015

Yes, it would sure be possible - and I'd totally be happy to take such a contribution! Myself, I don't have plans to write that at the moment, however; from looking at goversioninfo, it seems non-trivial, and I don't have much motivation as of now (although, now that I've said that, I'm starting to feel some itching...). (If you're interested yourself, have a look at the description of VS_VERSIONINFO structure in MSDN. That's what I sent to josephspurrier when he contacted me originally, asking about the same.)

As to goversioninfo: from what I know, this project is heavily based on rsrc, but apparently in a non-compatible, "write from scratch while copying fragments from rsrc" way, and under a different license (APACHE) instead of a regular fork and contributing back to rsrc. My chosen license kinda allows that (although I haven't checked if the copyright messages were left where they should be left), so I can't complain much. But what's important here (and why I had to say that), is that I can't take back from him without changing my license. And that I'm not very eager to do.

Now, I don't know why he decided to drop the manifest functionality, as I understand from what you said; but if you like to go further "his way", you could try to have a look at func WriteSyso in goversioninfo.go; then compare it to func run in rsrc.go. They're... how to say that... "similar enough", that you should probably be able to patch the goversioninfo.go with a few more lines from rsrc.go that would bring the functionality there.

Does this advance the situation for you? Happy to hear you're interested in it and find it useful!

_edit:_ by the way, if you're coding in Go on Windows, and doing WinAPI calls, have you seen my winq package? It aims to really make that easier...

@josephspurrier
Copy link

I just talked with @tgulacsi and he is fine with me changing the license from Apache to MIT on https://github.com/josephspurrier/goversioninfo - I'll make sure his contributions are not overlooked. Let me know if you have any suggestions on how to change the structure to work with rsrc.

@akavel
Copy link
Owner

akavel commented Feb 26, 2016

@josephspurrier That's great!

I must admit I can't wrap my head around the current organisation of the code in goversioninfo, so I'm thinking how one could try splitting it into somewhat smaller phases/commits, to make it more approachable for me and kinda MVP-ish with regards to integration in rsrc. The one and only idea I have for now, is that I'd like trying to start with implementing just some basic "number-ish" values — e.g. "File Version" & "Product Version". That would hopefully help me understand the initial requirements for embedding VS_VERSIONINFO in COFF; hopefully maybe strings and other stuff (?) could be then added in a later phase (with any additional complexity they may possibly bring). Can you possibly help me understand which of the structures & funcs/fragments in goversioninfo are still unavoidable if one would want to add only File Version & Product Version to the .syso?

I'd really like if I managed to understand the stuff before starting to think how to best structure it for merging into rsrc.

@josephspurrier
Copy link

I'm thinking it may be easier than we think to integrate the rsrc and goversioninfo. As far as the requirements go, I'm thinking it's best to leave everything in. It will probably be more work to strip it down as opposed to integrate it as is. I'll do a pull request and you can see if it makes more sense to you.

@akavel
Copy link
Owner

akavel commented Mar 1, 2016

It may be more work to split it to smaller chunks, but I can't deny it's not easy for me either when I have a perspective of integrating some code I have trouble understanding into the tool, and then living with having to maintain it for better or worse indefinitely... Especially given that this whole thing is just a hobby project for me, so I don't really have much time and resources when I can work on it. Just to explain the reasons behind what I say.

@josephspurrier
Copy link

I understand what you're saying. I'll do my best to explain it. I'll go as fundamental as I can so others following this can understand as well. Please correct me if anything is incorrect. I'll post a second note after this.

Typically, when you are developing an app in C++, you would use a resource script file (.rc) with this format for including version information in your application:

1       VERSIONINFO
FILEVERSION     1,0,0,0
PRODUCTVERSION  1,0,0,0
FILEOS          0X40004
FILETYPE        0X1
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904B0"
        BEGIN
            VALUE "FileVersion", "v1.0.0.0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
            VALUE "Translation", 0x0409, 0x04B0
    END
END

In C++, the resource compiler is used to convert the resource script file (.rc) to an object file (.o) - http://www.willus.com/mingw/colinp/win32/tools/rc.html. The linker is then used to convert the object files into applications or DLLs - http://www.willus.com/mingw/colinp/win32/tools/link.html. Those object files use the COFF format (there are a couple variations of COFF) - http://www.theparticle.com/cs/bc/os/elfpecoff.html.

In Go, there are system object files (.syso) which are also in the COFF format that are automatically picked up by Go when you run: go build. The rsrc tool makes it easy to generate the .syso file with icons and manifest.

GoVersionInfo uses rsrc to convert a json with Windows version information into a .syso.

@josephspurrier
Copy link

I recently just found out you can duplicate all the work we've done with a file called windres.exe which is available in MinGW.

If you create a file called resource.rc and paste this in:

7 ICON "icon.ico"

1       VERSIONINFO
FILEVERSION     1,0,0,0
PRODUCTVERSION  1,0,0,0
FILEOS          0X40004
FILETYPE        0X1
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904B0"
        BEGIN
            VALUE "FileVersion", "v1.0.0.0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
            VALUE "Translation", 0x0409, 0x04B0
    END
END

You can then run this command, it will create a .syso than can be picked up by Go build:
windres -i resource.rc -O coff -o resource.syso

Was there any reason why we didn't use this in the first place?

@akavel
Copy link
Owner

akavel commented Mar 3, 2016

As to windres, I'm fully aware of it — actually, I typically use windres output as a reference guide when debugging issues in rsrc output. My reason for creating rsrc was to make the process easier for people. So that Go programmers wouldn't have to download and install full MinGW/GCC suite and learn the weird windres syntax just to embed a single icon and/or manifest in their Windows app. Instead, they can now just go get rsrc, run it with simple options, and be done, also regardless of what OS they're developing on. And the other reason was that I was curious to test if the hack described by Minux (about syso files) would really work.

So, I'm afraid I must say those two most recent comments above don't really help me in anything. I'd much rather prefer to learn and understand technical details of the VERSIONINFO layout & requirements, so that I could remove as much effort as possible from the end user, and hide it inside the app instead. Or, for starters, at least how to use the goversioninfo package (what exactly input to provide) to do that.

@josephspurrier
Copy link

Ah, thanks for that information. I originally believed your application was only way to embedded resources in a Go application, but now I understand your motivation behind the creation of rsrc.

I'll have to write up some information about the VERSIONINFO layout when I have some time.

@akavel
Copy link
Owner

akavel commented Mar 4, 2016

Ah, yes, resources; I must admit I've already forgotten about that, given that this part is defunct now. So, you're right in that it was there from very early on. I don't really remember now which part was the first one. Still, I think what I wrote above applies this way or the other.

@josephspurrier
Copy link

I just updated my application so the algorithm should be much better I was modeling it after the output from windres, but it looks like windres was not calculating section lengths correctly and I could not consistently duplicate the logic in their code so now goversioninfo should work very well.

@DavidR91 I also integrated the manifest ability into goversioninfo with a few lines of code so that can be used now in the meantime which we work on the integration.

I have a much better understanding of the VERSIONINFO layout and it's fresh in my mind so let's get started. Goversioninfo is basically broken down into two files goversioninfo.go and structbuild.go.

goversioninfo.go contains all the possible variables (in structs) like file version/product version/etc that are loaded into structs in structbuild.go which are modeled after the Version Information Structures.

The structure is really not complicated. Every structure (VSVersionInfo, VSFixedFileInfo, VSStringFileInfo, etc) has a similar format.

WLength is a word (2 bytes) in reverse that is the length (in bytes) of the current structure and all children. This is really important because it sets the boundaries.
WValueLength is a word (2 bytes) in reverse that is the length (usually in bytes) of the Value or Children. For the VSString the length is the number of words instead of bytes.
WType is a word (2 bytes) in reverse that is either 0 for binary of 1 for text. It's 1 in everything except in VSVersionInfo and VSVar.
SzKey is a byte array of a string. If the string is FileVersion with a length of 11, every letter is padded with 00 so the final length is 22.
Padding is required to align the next Value or Children on a 32-bit boundary (every 4 words). There must be at least 1 word (2 bytes) between each SzKey and Value/Children.
The Value is either a byte array of a string (VSString), 4 words (VSVar), or Children which is one or more structs under it.

All the VSStrings are listed here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms646987(v=vs.85).aspx

Right now, my structure is pretty rigid. I only allow for one StringTable. I only allow the strings defined in the app even though they are just guidelines in the spec. I don't use any types of encodings which I'm sure is not good. I also don't think when I'm aligning to a 32-bit boundary, they are calculated correctly, but I haven't seen any problems. There should also be a way to add in more Children for VSVarFileInfo.

@niondir
Copy link

niondir commented Jan 16, 2018

Any progress on this? I would love to attach some version info to my windows executable as well.

@akavel
Copy link
Owner

akavel commented Jan 16, 2018

Sorry, I'm overloaded with other stuff, so not expecting to personally work on this in any predictable timeframe.

That said, I'm open to pull requests, and there's in fact a related one open at #14, but the author didn't respond to the initial review, and for a PR to have chance to be accepted, I need cooperation. Given that finding time to do a review (and not forgetting about it inbetween more important things) is already hard for me, there's no chance I can find time to do the tweaks to a PR by myself.

By any chance, if you'd like to take the #14 and try to do something to improve it, you're more than welcome! Even incremental improvements to it are welcome, maybe someone else will come later and slowly converge the PR to some acceptable shape.

@josephspurrier
Copy link

I'm open to others improving it for the PR as well - I don't have the time currently.

@akavel akavel added the help wanted Just jump in! — mentoring provided :) label Mar 7, 2018
@akavel
Copy link
Owner

akavel commented Mar 7, 2018

I'm trying to add this to the listing at http://up-for-grabs.net. For anyone interested, I'll note here, that I'd be very happy and eager to guide and mentor a contributor! On the other hand, I must note I can be busy and may have a few days of latency when responding, as Real Life(tm) interferes quite often these days. But I'd absolutely do my best to communicate as quickly as possible.

As to technical details, the task would be based on some MSDN exploration and related googling, focused on a fragment of PE/COFF executable format (absolutely not rocket science; interesting for me, being some lower-level OS-related stuff). Plus testing the feature on a Windows machine. Given the expressions of interest in the feature, if you want to help, you can be more than sure that your contribution would be actually useful for many people! Though you may also be surprised how silent is the sound of success ;)

A contribution can be based on #14 (taking into account the initial review notes) or can start from scratch, whichever is preferred by the contributor!

@Kukulkano
Copy link

I also very much need the option to add version and vendor information. Maybe some news here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement help wanted Just jump in! — mentoring provided :)
Projects
None yet
Development

No branches or pull requests

5 participants