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

[Feature]Add version info into dll and exe under Windows #14

Open
nkh0472 opened this issue Jun 8, 2021 · 4 comments
Open

[Feature]Add version info into dll and exe under Windows #14

nkh0472 opened this issue Jun 8, 2021 · 4 comments

Comments

@nkh0472
Copy link
Contributor

nkh0472 commented Jun 8, 2021

It is very useful for compiling under Windows system, but may need do a little patch like adding a header file or/and patch the configure file…… Of course, a new third-party tool also could be used to modify the compiled file, which will not affect the source code and compilation process, but the implementation is not so elegant.

It could be implemented by upstream developers or in this compiler script.

Some useful links:
https://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/
https://stackoverflow.com/questions/2618669/compiling-dll-with-version-information
https://stackoverflow.com/questions/3314800/how-to-embed-version-information-into-shared-library-and-binary

@kekyo
Copy link
Owner

kekyo commented Jun 10, 2021

Good suggestion!

I don't know how to do it with simple solution on shell scripting and/or 3rd party tools.

Bit off topic:
I have an .NET OSS solution RelaxVersioner, it inserts version resource script at that compilation time (MSBuild, same as make). Version informations will be extracted from git repository tags (uses libgit2) and attributes/annotations applied in source code. This is a perfect automated solution, so internal is very complex.

I know (but only user side) text based generator likely it in configure script by autoconf/automake. If not wrong my understanding, it has very complex sed/awk based script...

I think a solutions is: it makes (with sed?) from a template resource script text with variable version string, and variable string comes from building script (build.sh) entering MANUALLY (Yes, it isn't elegant :) :

LIBFDK=2.0.2
FDKAAC=1.0.2

#...

sed -e 's/LIBFDK/${LIBFDK}/g' version.template | sed -e 's/FDKAAC/${FDKAAC}/g' > version.rc

# TODO: How to insert resource bin into?
make -j$NPB 

@nkh0472
Copy link
Contributor Author

nkh0472 commented Jun 10, 2021

I don't know anything about regular expressions and text processing, but I can provide some ways to use tools to add version information.

Generally speaking, there are two implementation paths. One is to inject the version information into the compiled file through a third-party tool like Resource Hacker; Another method is to modify makefile.ac of the original project and add windres related processes. Obviously, the second way is a relatively elegant but complex solution. If you choose this solution, the modify of the compilation script should be submitted to the upstream, instead of modifying by this script.

But anyway, both of these two methods need a resource.rc file first.

1.Writing resource.rc

https://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/

#include <windows.h>

// DLL version information.
VS_VERSION_INFO    VERSIONINFO
FILEVERSION        1,0,0,0
PRODUCTVERSION     1,0,0,0
FILEFLAGSMASK      VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
 FILEFLAGS        VS_FF_DEBUG | VS_FF_PRERELEASE
#else
 FILEFLAGS        0
#endif
FILEOS             VOS_NT_WINDOWS32
FILETYPE           VFT_DLL
FILESUBTYPE        VFT2_UNKNOWN
BEGIN
 BLOCK "StringFileInfo"
 BEGIN
   BLOCK "080904b0"
   BEGIN
     VALUE "CompanyName", "Transmission Zero"
     VALUE "FileDescription", "A library to perform addition."
     VALUE "FileVersion", "1.0.0.0"
     VALUE "InternalName", "AddLib"
     VALUE "LegalCopyright", "©2013 Transmission Zero"
     VALUE "OriginalFilename", "AddLib.dll"
     VALUE "ProductName", "Addition Library"
     VALUE "ProductVersion", "1.0.0.0"
   END
 END
 BLOCK "VarFileInfo"
 BEGIN
   VALUE "Translation", 0x809, 1200
 END
END

https://stackoverflow.com/questions/46430483/version-info-exe-with-gcc-and-windres

In this discussion, someone said it should use winver.h. This file and windows.h are both included in \x86_64-w64-mingw32\include\, I guess both of them could work. However, if we use Resource Hacker, it's no need to include a header file (See ).

aaaa ICON "icon.ico"

#include "winver.h"

VS_VERSION_INFO VERSIONINFO
    FILEVERSION    RC_FILEVERSION
    PRODUCTVERSION RC_FILEVERSION
{
    BLOCK "StringFileInfo"
    {
        BLOCK "040C04E4"
        {
            VALUE "CompanyName",        "Compagny\0"
            VALUE "FileDescription",    "Description\0"
            VALUE "FileVersion",        FULLVERSION_STRING
            VALUE "LegalCopyright",     "Copyright (C) 2017\0"
            VALUE "OriginalFilename",   "program.exe\0"
            VALUE "ProductName",        "Program\0"
            VALUE "ProductVersion",     FULLVERSION_STRING
        }
    }
    BLOCK "VarFileInfo"
    {
        VALUE "Translation", 0x40C, 0x4E4 // French, multilingual
    }
}

For all available items in .rc file, could refer to the Microsoft documentation.

2.1. Inject version info to binary files

We need a ResourceHacker.exe. And add these to build.sh:

SET INPUT_EXE=app.exe
#dll file works as well
SET OUTPUT_EXE=app.1.exe

ResourceHacker.exe -open resources.rc -save resources.res -action compile -log CONSOLE

ResourceHacker.exe -open %OUTPUT_EXE% -save %OUTPUT_EXE% -resource resources.res -action addoverwrite -mask VersionInf ​-log CONSOLE

More info about the command line syntax of Resource Hacker could be found on their official site.

2.2. Add version info during compile

2.2.1. Manually add version info

After some searching, I think the most concise tutorial I found is this one, it should be read first. windres should be contained in binutils-mingw, which is a kind of "official" tool to generate version info for windows.

(a) Compile the .rc file:

Under MSVC, these are compiled into '.res' files. Under gcc, you need to convert it to a '.o' file.

windres -i resource.rc -o resource.o

Here is the man page of windres:
https://manpages.debian.org/testing/binutils-mingw-w64-x86-64/x86_64-w64-mingw32-windres.1.en.html

(b) Link everything:
gcc other.o files.o etc.o resource.o -o final.exe

2.2.2. Add version info using autotools

The above two steps are simple, but I don't know how to use autotool to complete the above process. Maybe the first concise tutorial is a good start.

Drop this into your Makefile.am:

.rc.o:
        windres $^ -o $@
%.o : %.rc
        windres $^ -o $@

I found I needed the windres rule twice, in the two forms shown. The first tells automake to recognise .rc files (it doesn't understand the second form), while the version of make I was using (GNU make) didn't seem to like the second form. Weird.

After this, just add the '.rc' file to the SOURCES list, eg.

chocolate_doom_SOURCES=\
other.c other.h files.c files.h etc.c etc.h \
chocolate-doom-res.rc

It should then build it all automatically.

Here autotools tags for compiling resources is another (maybe usefull) discussion.
But if we submit the modification of the makefile.am to upstream, I probably don't know how cross-platform compatibility is.

@nkh0472
Copy link
Contributor Author

nkh0472 commented Jun 10, 2021

Since this project only compile for stable release version, we could somehow use their existing version number definition.

In fdkaac, the author defines the version number in version.h, then use the number in configure.ac:

https://github.com/nu774/fdkaac/blob/347e995cfc44941f6d6dfe8d4e09362a71ea8d26/version.h#L1-L4

const char *fdkaac_version = "1.0.2";

https://github.com/nu774/fdkaac/blob/fdf5c2f251a6b35dc2b3df561cfd247829b98f5d/configure.ac#L1-L6


In fdk-aac, the author defines the version number both in CMakeLists.txt and configure.ac:

https://github.com/mstorsjo/fdk-aac/blob/801f67f671929311e0c9952c5f92d6e147c7b003/configure.ac#L29

FDK_AAC_VERSION=2:2:0

https://github.com/mstorsjo/fdk-aac/blob/801f67f671929311e0c9952c5f92d6e147c7b003/CMakeLists.txt#L487-L493

### Set public headers and shared library version. Version info is critical for Unix-like OSes.
set_target_properties(fdk-aac PROPERTIES
  PUBLIC_HEADER "${fdk_aacinclude_HEADERS}"
  VERSION 2.0.2
  SOVERSION 2
  MACHO_COMPATIBILITY_VERSION 3.0.0
  MACHO_CURRENT_VERSION 3.2.0)

So, I think we should modify their configure.ac, to add the code snippet to compile version information using windres.

@nkh0472
Copy link
Contributor Author

nkh0472 commented Jun 11, 2021

Now fdkaac.exe will display version info normally in my Windows.

I've tested my modify in https://github.com/nkh0472/fdkaac/tree/patch-1.

Please help me to see if the file display in the English system is normal.

1
2


PS:
I'm working on https://github.com/nkh0472/fdk-aac/tree/win-versioninfo.
Still confused about syntax of autotools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants