From 7a882d3e077c89153e76ead88f6c942338db4cd7 Mon Sep 17 00:00:00 2001 From: Edwin Date: Tue, 12 Nov 2024 13:24:14 +0100 Subject: [PATCH] Provide version information in DLL (#1076) * Provide version information in DLL * Update changelog * only include rc file when building dll * move rc code gen, change product name, make FileVersion the same as ProductVersion * Further clean-ups and reuse for crashpad * moved code to utility function * that function uses the target argument to generate all required files (only manual parameter is the file description) * switched from manual string replacement to `configure_file()` which creates another intermediate file * to generate the final *.rc file we use file(GENERATE) together with `TARGET_FILE_NAME` generator expression to retrieve "OriginFilename" during the generate-time (between configure and build phase). * ensure that unit-tests don't pick up unnecessary resource-sources * update changelog * update changelog * replace `TARGET` parameter with `TGT` for good measure * add test-fixture checks for binaries * conditionally include windows-specific module * don't include utils.cmake only for shared-libs build... ...because even if we generate static client libraries crashpad_handler.exe and crashpad_wer.dll should still be versioned. * update crashpad submodule to getsentry ref --------- Co-authored-by: Mischan Toosarani-Hausberger --- CHANGELOG.md | 22 ++++++++++++++++++---- CMakeLists.txt | 5 +++++ cmake/utils.cmake | 21 +++++++++++++++++++++ external/crashpad | 2 +- scripts/bump-version.sh | 1 + sentry.rc.in | 22 ++++++++++++++++++++++ tests/cmake.py | 10 ++++++++++ tests/requirements.txt | 1 + tests/unit/CMakeLists.txt | 2 ++ tests/win_utils.py | 19 +++++++++++++++++++ 10 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 cmake/utils.cmake create mode 100644 sentry.rc.in create mode 100644 tests/win_utils.py diff --git a/CHANGELOG.md b/CHANGELOG.md index ec6e85354..5b4128705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,22 +1,32 @@ # Changelog +## Unreleased + +**Features**: + +- Provide version information for non-static Windows binaries. ([#1076](https://github.com/getsentry/sentry-native/pull/1076), [crashpad#110](https://github.com/getsentry/crashpad/pull/110)) + +**Thank you**: + +[olback](https://github.com/olback) + ## 0.7.12 **Features**: -- Add `sentry_capture_minidump()` to capture independently created minidumps ([#1067](https://github.com/getsentry/sentry-native/pull/1067)) +- Add `sentry_capture_minidump()` to capture independently created minidumps. ([#1067](https://github.com/getsentry/sentry-native/pull/1067)) **Fixes**: -- Add breadcrumb ringbuffer to avoid O(n) memmove on adding more than max breadcrumbs ([#1060](https://github.com/getsentry/sentry-native/pull/1060)) +- Add breadcrumb ringbuffer to avoid O(n) memmove on adding more than max breadcrumbs. ([#1060](https://github.com/getsentry/sentry-native/pull/1060)) ## 0.7.11 **Fixes**: -- Reject invalid trace- and span-ids in context update from header ([#1046](https://github.com/getsentry/sentry-native/pull/1046)) +- Reject invalid trace- and span-ids in context update from header. ([#1046](https://github.com/getsentry/sentry-native/pull/1046)) - Lookup `GetSystemTimePreciseAsFileTime()` at runtime and fall back to `GetSystemTimeAsFileTime()` to allow running on Windows < 8. ([#1051](https://github.com/getsentry/sentry-native/pull/1051)) -- Allow for empty DSN to still initialize crash handler ([#1059](https://github.com/getsentry/sentry-native/pull/1059)) +- Allow for empty DSN to still initialize crash handler. ([#1059](https://github.com/getsentry/sentry-native/pull/1059)) ## 0.7.10 @@ -24,6 +34,10 @@ - Correct the timestamp resolution to microseconds on Windows. ([#1039](https://github.com/getsentry/sentry-native/pull/1039)) +**Thank you**: + +- [ShawnCZek](https://github.com/ShawnCZek) + ## 0.7.9 **Fixes**: diff --git a/CMakeLists.txt b/CMakeLists.txt index 770ce074d..b35b8f1b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -369,6 +369,11 @@ if(WIN32) endif() endif() +include(cmake/utils.cmake) +if (WIN32 AND SENTRY_BUILD_SHARED_LIBS) + sentry_add_version_resource(sentry "Client Library") +endif() + # handle platform libraries if(ANDROID) set(_SENTRY_PLATFORM_LIBS "dl" "log") diff --git a/cmake/utils.cmake b/cmake/utils.cmake new file mode 100644 index 000000000..df3619c13 --- /dev/null +++ b/cmake/utils.cmake @@ -0,0 +1,21 @@ +# Generates a version resource file from the `sentry.rc.in` template for the `TGT` argument and adds it as a source. +function(sentry_add_version_resource TGT FILE_DESCRIPTION) + # generate a resource output-path from the target name + set(RESOURCE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${TGT}.rc") + set(RESOURCE_PATH_TMP "${RESOURCE_PATH}.in") + + # Extract major, minor and patch version from SENTRY_VERSION + string(REPLACE "." ";" _SENTRY_VERSION_LIST "${SENTRY_VERSION}") + list(GET _SENTRY_VERSION_LIST 0 SENTRY_VERSION_MAJOR) + list(GET _SENTRY_VERSION_LIST 1 SENTRY_VERSION_MINOR) + list(GET _SENTRY_VERSION_LIST 2 SENTRY_VERSION_PATCH) + + # Produce the resource file with configure-time replacements + configure_file("${CMAKE_SOURCE_DIR}/sentry.rc.in" "${RESOURCE_PATH_TMP}" @ONLY) + + # Replace the `ORIGINAL_FILENAME` at generate-time using the generator expression `TARGET_FILE_NAME` + file(GENERATE OUTPUT ${RESOURCE_PATH} INPUT ${RESOURCE_PATH_TMP}) + + # Finally add the generated resource file to the target sources + target_sources("${TGT}" PRIVATE "${RESOURCE_PATH}") +endfunction() \ No newline at end of file diff --git a/external/crashpad b/external/crashpad index 04101eb87..8961424c2 160000 --- a/external/crashpad +++ b/external/crashpad @@ -1 +1 @@ -Subproject commit 04101eb874f109f98c22f341dfa3162879d5b92a +Subproject commit 8961424c23c2ba98eaecbee526e0b729aabea1b2 diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh index 57a974378..5e5e37709 100755 --- a/scripts/bump-version.sh +++ b/scripts/bump-version.sh @@ -18,3 +18,4 @@ perl -pi -e "s/^#define SENTRY_SDK_VERSION.*/#define SENTRY_SDK_VERSION \"${NEW_ perl -pi -e "s/\"version\": \"[^\"]+\"/\"version\": \"${NEW_VERSION}\"/" tests/assertions.py perl -pi -e "s/sentry.native\/[^\"]+\"/sentry.native\/${NEW_VERSION}\"/" tests/test_integration_http.py perl -pi -e "s/^versionName\=.*/versionName\=${NEW_VERSION}/" ndk/gradle.properties +perl -pi -e "s/^sentry_version \=.*/sentry_version \= \"${NEW_VERSION}\"/" tests/win_utils.py \ No newline at end of file diff --git a/sentry.rc.in b/sentry.rc.in new file mode 100644 index 000000000..921811728 --- /dev/null +++ b/sentry.rc.in @@ -0,0 +1,22 @@ +1 VERSIONINFO +FILEVERSION @SENTRY_VERSION_MAJOR@,@SENTRY_VERSION_MINOR@,@SENTRY_VERSION_PATCH@,0 +PRODUCTVERSION @SENTRY_VERSION_MAJOR@,@SENTRY_VERSION_MINOR@,@SENTRY_VERSION_PATCH@,0 +BEGIN +BLOCK "StringFileInfo" +BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileDescription", "@FILE_DESCRIPTION@" + VALUE "FileVersion", "@SENTRY_VERSION@" + VALUE "InternalName", "sentry-native" + VALUE "LegalCopyright", "https://sentry.io" + VALUE "OriginalFilename", "$" + VALUE "ProductName", "Sentry Native SDK" + VALUE "ProductVersion", "@SENTRY_VERSION@" + END +END +BLOCK "VarFileInfo" +BEGIN + VALUE "Translation", 0x409, 1252 +END +END diff --git a/tests/cmake.py b/tests/cmake.py index 6466d7910..e9e951545 100644 --- a/tests/cmake.py +++ b/tests/cmake.py @@ -3,6 +3,8 @@ import shutil import subprocess import sys +import platform +from pathlib import Path import pytest @@ -204,6 +206,14 @@ def cmake(cwd, targets, options=None): except subprocess.CalledProcessError: raise pytest.fail.Exception("cmake build failed") from None + # check if the DLL and EXE artifacts contain version-information + if platform.system() == "Windows": + from tests.win_utils import check_binary_version + + check_binary_version(Path(cwd) / "sentry.dll") + check_binary_version(Path(cwd) / "crashpad_wer.dll") + check_binary_version(Path(cwd) / "crashpad_handler.exe") + if "code-checker" in os.environ.get("RUN_ANALYZER", ""): # For whatever reason, the compilation summary contains duplicate entries, # one with the correct absolute path, and the other one just with the basename, diff --git a/tests/requirements.txt b/tests/requirements.txt index 73cc2f63d..306be91e8 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -4,3 +4,4 @@ pytest-httpserver==1.0.10 msgpack==1.0.8 pytest-xdist==3.5.0 clang-format==19.1.3 +pywin32==308; sys_platform == "win32" diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 840c85561..dba445a17 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -13,6 +13,8 @@ sentry_get_property(INCLUDE_DIRECTORIES) sentry_get_property(LINK_LIBRARIES) sentry_get_property(INTERFACE_LINK_LIBRARIES) +list(FILTER SENTRY_SOURCES EXCLUDE REGEX "\\.rc$") + add_executable(sentry_test_unit ${SENTRY_SOURCES} main.c diff --git a/tests/win_utils.py b/tests/win_utils.py new file mode 100644 index 000000000..046bf6670 --- /dev/null +++ b/tests/win_utils.py @@ -0,0 +1,19 @@ +import pathlib +import win32api + +sentry_version = "0.7.12" + + +def check_binary_version(binary_path: pathlib.Path): + if not binary_path.exists(): + return + + info = win32api.GetFileVersionInfo(str(binary_path), "\\") + ms = info["FileVersionMS"] + ls = info["FileVersionLS"] + file_version = (ms >> 16, ms & 0xFFFF, ls >> 16, ls & 0xFFFF) + file_version = f"{file_version[0]}.{file_version[1]}.{file_version[2]}" + if sentry_version != file_version: + raise RuntimeError( + f"Binary {binary_path.parts[-1]} has a different version ({file_version}) than expected ({sentry_version})." + )