From 282b4913c7e4d4b5a141c9f89da97a65ee86bdd9 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 15 May 2025 13:57:57 +0100 Subject: [PATCH 1/3] cmake: Add application manifests when cross-compiling for Windows Windows application manifests provide several benefits. However, on the master branch, the linker generates and embeds manifests only when building with MSVC. This change unifies manifest embedding for both native and cross-compilation. --- CMakeLists.txt | 4 ++++ cmake/module/AddWindowsResources.cmake | 17 +++++++++++++++-- cmake/windows-app.manifest.in | 15 +++++++++++++++ src/CMakeLists.txt | 5 +++++ src/qt/CMakeLists.txt | 1 + src/test/CMakeLists.txt | 2 ++ 6 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 cmake/windows-app.manifest.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 69f23d44b16..7b88987caf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,6 +276,10 @@ if(WIN32) /Zc:__cplusplus /sdl ) + target_link_options(core_interface INTERFACE + # We embed our own manifests. + /MANIFEST:NO + ) # Improve parallelism in MSBuild. # See: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/. list(APPEND CMAKE_VS_GLOBALS "UseMultiToolTask=true") diff --git a/cmake/module/AddWindowsResources.cmake b/cmake/module/AddWindowsResources.cmake index a9b4f51f73d..5c69d968897 100644 --- a/cmake/module/AddWindowsResources.cmake +++ b/cmake/module/AddWindowsResources.cmake @@ -4,11 +4,24 @@ include_guard(GLOBAL) -macro(add_windows_resources target rc_file) +function(add_windows_resources target rc_file) if(WIN32) target_sources(${target} PRIVATE ${rc_file}) set_property(SOURCE ${rc_file} APPEND PROPERTY COMPILE_DEFINITIONS WINDRES_PREPROC ) endif() -endmacro() +endfunction() + +# Add a fusion manifest to Windows executables. +# See: https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests +function(add_windows_application_manifest target) + if(WIN32) + configure_file(${PROJECT_SOURCE_DIR}/cmake/windows-app.manifest.in ${target}.manifest USE_SOURCE_PERMISSIONS) + file(CONFIGURE + OUTPUT ${target}-manifest.rc + CONTENT "1 /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 24 /* RT_MANIFEST */ \"${target}.manifest\"" + ) + add_windows_resources(${target} ${CMAKE_CURRENT_BINARY_DIR}/${target}-manifest.rc) + endif() +endfunction() diff --git a/cmake/windows-app.manifest.in b/cmake/windows-app.manifest.in new file mode 100644 index 00000000000..c3bd333a227 --- /dev/null +++ b/cmake/windows-app.manifest.in @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dac8872080a..82bb4de460a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -206,6 +206,7 @@ if(ENABLE_WALLET) wallet/wallettool.cpp ) add_windows_resources(bitcoin-wallet bitcoin-wallet-res.rc) + add_windows_application_manifest(bitcoin-wallet) target_link_libraries(bitcoin-wallet core_interface bitcoin_wallet @@ -339,6 +340,7 @@ if(BUILD_DAEMON) init/bitcoind.cpp ) add_windows_resources(bitcoind bitcoind-res.rc) + add_windows_application_manifest(bitcoind) target_link_libraries(bitcoind core_interface bitcoin_node @@ -392,6 +394,7 @@ target_link_libraries(bitcoin_cli if(BUILD_CLI) add_executable(bitcoin-cli bitcoin-cli.cpp) add_windows_resources(bitcoin-cli bitcoin-cli-res.rc) + add_windows_application_manifest(bitcoin-cli) target_link_libraries(bitcoin-cli core_interface bitcoin_cli @@ -407,6 +410,7 @@ endif() if(BUILD_TX) add_executable(bitcoin-tx bitcoin-tx.cpp) add_windows_resources(bitcoin-tx bitcoin-tx-res.rc) + add_windows_application_manifest(bitcoin-tx) target_link_libraries(bitcoin-tx core_interface bitcoin_common @@ -420,6 +424,7 @@ endif() if(BUILD_UTIL) add_executable(bitcoin-util bitcoin-util.cpp) add_windows_resources(bitcoin-util bitcoin-util-res.rc) + add_windows_application_manifest(bitcoin-util) target_link_libraries(bitcoin-util core_interface bitcoin_common diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 7379a1f328e..6c853cbf2f8 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -256,6 +256,7 @@ add_executable(bitcoin-qt ) add_windows_resources(bitcoin-qt res/bitcoin-qt-res.rc) +add_windows_application_manifest(bitcoin-qt) target_link_libraries(bitcoin-qt core_interface diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index ce9f3218879..6ce33621af8 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -142,6 +142,8 @@ target_raw_data_sources(test_bitcoin NAMESPACE test::data data/asmap.raw ) +add_windows_application_manifest(test_bitcoin) + target_link_libraries(test_bitcoin core_interface test_util From 2bb6ab8f1baa4b3d72b3ccde7f5fa96f8ca330aa Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 15 May 2025 13:58:05 +0100 Subject: [PATCH 2/3] ci: Add "Get bitcoind manifest" steps to Windows CI jobs This change makes it easy to verify any changes in the application manifests. --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77f0877c00a..14421fba500 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -237,6 +237,15 @@ jobs: run: | cmake --build . -j $NUMBER_OF_PROCESSORS --config Release + - name: Get bitcoind manifest + if: matrix.job-type == 'standard' + working-directory: build + run: | + mt.exe -nologo -inputresource:bin/Release/bitcoind.exe -out:bitcoind.manifest + cat bitcoind.manifest + echo + mt.exe -nologo -inputresource:bin/Release/bitcoind.exe -validate_manifest + - name: Run test suite if: matrix.job-type == 'standard' working-directory: build @@ -347,6 +356,20 @@ jobs: - name: Run bitcoind.exe run: ./bin/bitcoind.exe -version + - name: Find mt.exe tool + shell: pwsh + run: | + $sdk_dir = (Get-ItemProperty 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots' -Name KitsRoot10).KitsRoot10 + $sdk_latest = (Get-ChildItem "$sdk_dir\bin" -Directory | Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } | Sort-Object Name -Descending | Select-Object -First 1).Name + "MT_EXE=${sdk_dir}bin\${sdk_latest}\x64\mt.exe" >> $env:GITHUB_ENV + + - name: Get bitcoind manifest + shell: pwsh + run: | + & $env:MT_EXE -nologo -inputresource:bin\bitcoind.exe -out:bitcoind.manifest + Get-Content bitcoind.manifest + & $env:MT_EXE -nologo -inputresource:bin\bitcoind.exe -validate_manifest + - name: Run unit tests # Can't use ctest here like other jobs as we don't have a CMake build tree. run: | From 8f4fed7ec70093e2535423d63e9f9dd400c378ac Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 15 May 2025 13:58:13 +0100 Subject: [PATCH 3/3] symbol-check: Add check for application manifest in Windows binaries Check that the application manifest is present in all binaries. Co-authored-by: laanwj <126646+laanwj@users.noreply.github.com> --- contrib/guix/symbol-check.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contrib/guix/symbol-check.py b/contrib/guix/symbol-check.py index 9bb5322e170..0d0e26c3ddd 100755 --- a/contrib/guix/symbol-check.py +++ b/contrib/guix/symbol-check.py @@ -278,6 +278,14 @@ def check_PE_subsystem_version(binary) -> bool: return True return False +def check_PE_application_manifest(binary) -> bool: + if not binary.has_resources: + # No resources at all. + return False + + rm = binary.resources_manager + return rm.has_manifest + def check_ELF_interpreter(binary) -> bool: expected_interpreter = ELF_INTERPRETER_NAMES[binary.header.machine_type][binary.abstract.header.endianness] @@ -307,6 +315,7 @@ lief.EXE_FORMATS.MACHO: [ lief.EXE_FORMATS.PE: [ ('DYNAMIC_LIBRARIES', check_PE_libraries), ('SUBSYSTEM_VERSION', check_PE_subsystem_version), + ('APPLICATION_MANIFEST', check_PE_application_manifest), ] }