Skip to content

Add version resources to Azure SDK binaries when building on Windows #6965

@avivanoff

Description

@avivanoff

Problem

When Azure SDK for C++ packages are built as shared libraries (DLLs) on Windows, the resulting binaries contain no embedded version information. Windows users and administrators rely on the Details tab in file properties to identify DLL versions, publisher, and product information. Without a VERSIONINFO resource, the DLL Details tab is empty, making it difficult to:

  • Determine which version of an Azure SDK library is deployed
  • Diagnose version mismatch issues in production environments
  • Satisfy enterprise software inventory and compliance requirements
  • Identify the publisher and copyright information

This was originally reported in #5158 which was auto-closed due to inactivity.

Current State

Each SDK package already defines version information in src/private/package_version.hpp with standard macros:

#define AZURE_CORE_VERSION_MAJOR 1
#define AZURE_CORE_VERSION_MINOR 17
#define AZURE_CORE_VERSION_PATCH 0
#define AZURE_CORE_VERSION_PRERELEASE "beta.1"

The CMake infrastructure already extracts these values via get_az_version() in cmake-modules/AzureVersion.cmake and sets AZ_LIBRARY_VERSION on each target. The az_vcpkg_export() macro in AzureVcpkg.cmake already handles Windows-specific DLL configuration (export symbols, dll_import_export.hpp patching). However, no .rc resource files exist anywhere in the repository — there is no version resource embedded in any DLL.

Proposed Solution

Add a Windows version resource (.rc file) to each SDK library that is compiled into the DLL when BUILD_SHARED_LIBS=ON on Windows. The resource should be generated from a shared template using CMake's configure_file(), populated with the version values already parsed from package_version.hpp.

Implementation Plan

1. Create a shared .rc.in template

Add cmake-modules/version.rc.in with a VERSIONINFO resource template:

#include <winver.h>

VS_VERSION_INFO VERSIONINFO
FILEVERSION    @AZ_VERSION_MAJOR@, @AZ_VERSION_MINOR@, @AZ_VERSION_PATCH@, 0
PRODUCTVERSION @AZ_VERSION_MAJOR@, @AZ_VERSION_MINOR@, @AZ_VERSION_PATCH@, 0
FILEFLAGSMASK  VS_FFI_FILEFLAGSMASK
FILEFLAGS      @AZ_VERSION_FILEFLAGS@
FILEOS         VOS_NT_WINDOWS32
FILETYPE       VFT_DLL
FILESUBTYPE    VFT2_UNKNOWN
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904B0"
        BEGIN
            VALUE "CompanyName",      "Microsoft Corporation\0"
            VALUE "FileDescription",  "@AZ_VERSION_FILE_DESCRIPTION@\0"
            VALUE "FileVersion",      "@AZ_VERSION_STRING@\0"
            VALUE "InternalName",     "@AZ_VERSION_TARGET_NAME@\0"
            VALUE "LegalCopyright",   "Copyright (c) Microsoft Corporation. All rights reserved.\0"
            VALUE "OriginalFilename", "@AZ_VERSION_TARGET_NAME@.dll\0"
            VALUE "ProductName",      "Microsoft Azure SDK for C++\0"
            VALUE "ProductVersion",   "@AZ_VERSION_STRING@\0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x0409, 0x04B0
    END
END

2. Add a CMake helper function

Add az_add_version_resource() to AzureVersion.cmake (or a new AzureVersionResource.cmake module). This function should:

  • Accept the target name and a human-readable file description
  • Require that get_az_version() has already been called (use the parsed VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH values)
  • Only activate when WIN32 AND BUILD_SHARED_LIBS are both true (no-op otherwise)
  • Set AZ_VERSION_FILEFLAGS to VS_FF_PRERELEASE when VERSION_PRERELEASE is non-empty, and 0 otherwise
  • Call configure_file() on the .rc.in template to produce a target-specific .rc file in ${CMAKE_CURRENT_BINARY_DIR}
  • Add the generated .rc file to the target's sources via target_sources()

3. Integrate into each library's CMakeLists.txt

After the existing get_az_version() and set_target_properties(... VERSION ...) calls, add:

az_add_version_resource(azure-core "Microsoft Azure Core SDK for C++")

This must be added to all 20 SDK packages that have package_version.hpp files:

  • azure-core, azure-core-amqp, azure-core-test, azure-core-tracing-opentelemetry
  • azure-identity
  • azure-security-attestation
  • azure-security-keyvault-administration, azure-security-keyvault-certificates, azure-security-keyvault-keys, azure-security-keyvault-secrets
  • azure-storage-blobs, azure-storage-common, azure-storage-files-datalake, azure-storage-files-shares, azure-storage-queues
  • azure-messaging-eventhubs, azure-messaging-eventhubs-checkpointstore-blob
  • azure-data-appconfiguration, azure-data-tables
  • azure-template

4. Update get_az_version() to export individual version components

Currently get_az_version() only sets AZ_LIBRARY_VERSION in the parent scope. It should also set AZ_VERSION_MAJOR, AZ_VERSION_MINOR, AZ_VERSION_PATCH, and AZ_VERSION_PRERELEASE in the parent scope so the version resource function can use them without re-parsing.

Testing Plan

Build Verification

  • Build azure-core as a DLL on Windows (-DBUILD_SHARED_LIBS=ON) and verify the resulting .dll has a Details tab with correct version, company, and description
  • Verify the VS_FF_PRERELEASE flag is set when building a pre-release version
  • Build as a static library and verify no .rc file is compiled (no-op path)

Cross-Platform Verification

  • Build on Linux/macOS and verify the version resource logic is completely skipped with no warnings or errors

Version Accuracy

  • Verify the embedded FileVersion and ProductVersion match the values in package_version.hpp
  • Verify the OriginalFilename matches the actual DLL output name

CI Integration

  • Ensure the existing Windows CI pipelines (Win2022_Win32Api_debug_tests_winhttp_x86, etc.) pass with the new .rc files
  • Add a CI step or test that reads the version resource from a built DLL using powershell [System.Diagnostics.FileVersionInfo]::GetVersionInfo() and validates it matches expected values

Multi-Package Verification

  • Build at least 2-3 additional packages (e.g., azure-identity, azure-storage-blobs) as DLLs and verify each has correct, distinct version resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    Azure.Corecustomer-reportedIssues that are reported by GitHub users external to the Azure organization.needs-triageWorkflow: This is a new issue that needs to be triaged to the appropriate team.questionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions