C++ - Embedding Application Metadata

3 minute read

I usually work with C++ in the context of desktop applications. One small detail that is nice on Windows and Linux is being able to inspect a binary and find out things like:

  • Application version
  • Application author
  • Product Name
  • Copyright
  • Original filename

To view this information you just need to right click the binary (on Windows this could be a .exe or .dll), and then navigate to the Details tab. To me, this just seemed like something I should be doing with all the apps I work on. As a professional developer I feel that it’s my job to make sure that all the details are paid attention to; so I set on finding out how to include the above information in the applications we build at my place of work so that they would be more “complete” (in my opinion at least).

As you may know by now, I really like CMake so naturally, I wanted to use CMake to make my life easier. As usual, I’m not the first person in the world who wanted to do this so I found this reddit post in the r/cmake subreddit that helped me and had a sample Windows application resource file that I used as a template. Below is the modified version of the file I used:

IDI_ICON1    ICON    DISCARDABLE    "@ICO_ICON_NAME@"

#include <windows.h>

#define VER_COMPANY_NAME "@COMPANY_NAME@"

#define VER_COMMENT "@COMMENT@"

#define VER_FILE_DESCRIPTION "@FILE_DESCRIPTION@"

#define VER_FILE_VERSION @FILE_VERSION@
#define VER_FILE_VERSION_STRING "@FILE_VERSION_STRING@"

#define VER_PRODUCT_VERSION @PRODUCT_VERSION@
#define VER_PRODUCT_VERSION_STR "@PRODUCT_VERSION_TEXT@"

#define VER_COPYRIGHT_STR "Copyright @COPYRIGHT_YEAR@ @COMPANY_NAME@. All rights reserved."

#define VER_ORIGINAL_FILENAME "@ORIGINAL_FILENAME@"

#define VER_PRODUCT_NAME "@PRODUCT_NAME@"

VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILE_VERSION
PRODUCTVERSION VER_PRODUCT_VERSION
// FILEFLAGSMASK VER_FILE_FLAGS_MASK
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L

BEGIN
    BLOCK "StringFileInfo"
    BEGIN
            BLOCK "040904B0"   /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
            BEGIN
                VALUE "Comment",          VER_COMMENT
                VALUE "CompanyName",      VER_COMPANY_NAME
                VALUE "FileDescription",  VER_FILE_DESCRIPTION
                VALUE "FileVersion",      VER_FILE_VERSION
                VALUE "LegalCopyright",   VER_COPYRIGHT_STR
                VALUE "OriginalFilename", VER_ORIGINAL_FILENAME
                VALUE "ProductName",      VER_PRODUCT_NAME
                VALUE "ProductVersion",   VER_PRODUCT_VERSION_STR
            END
    END

    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x0409, 0x04B0
    END
END

After some tweaking, I realized passing in the FILEFLAGS, FILEOS, FILETYPE and FILESUBTYPE variables via CMake wasn’t working (I’m probably missing something but didn’t have time to figure out what). I decided to just make things simple and not make that part of the resource file configurable. Instead, it will have to be changed manually for each project, but only if it is not an application. Documentation for these inputs can be found here. One other thing I had to do is add the inclusion of <windows.h>. Without this, the details were not properly populated in my application.

Basically you can take the above file (let’s call it resource.rc.in) and then pass it through cmake to generate a final resource file for your application. All you need to do is define the variables surrounded by the @ symbols in CMake using the set() command. For example, there is a variable called in the resource.rc.in file for your company’s name (@COMPANY_NAME@). To define this variable properly, just add the following to your CMakeLists.txt:

set(COMPANY_NAME "My Company, LLC.")

Note that you must have the above line, before calling the configure_file() command as shown below:

configure_file(resource.rc.in resource.rc @ONLY)

This will read in the resource.rc.in file, replace all variables surrounded by @ symbols and then puts the results in a file called resource.in. The option @ONLY means that only variables surrounded by @ symbols will be replaced. This replacement happens at configure time when running cmake so this file is available when creating your binary targets, so you can just append it to your applications sources:

add_executable(${PROJECT_NAME} ${project_headers} ${project_sources} resources.rc)

You can also add a line to the top of the file that will set the icon of your application provided you have an .ico version of your application’s icon. I’ve added a line to the resource.rc.in file at the very top. You just need to define the path to the .ico file via the ICO_ICON_NAME variable. Note, however, that you will need this .ico file in your build directory (${CMAKE_BINARY_PATH}) in order for compilation to succeed; otherwise the resource compiler will complain it can’t find your .ico image when it tries to compile the resource.rc file.

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...