build: Force-remove all version information from libwinpthread

This commit is contained in:
WerWolv 2025-12-09 21:25:35 +01:00
parent 4d10d9a195
commit 495608ed7c
4 changed files with 136 additions and 11 deletions

View File

@ -330,21 +330,30 @@ macro(createPackage)
FILES "${_file}"
)
endforeach()
]])
# Download rcedit if not already present
set(RCEDIT_PATH "${CMAKE_BINARY_DIR}/rcedit.exe")
if(NOT EXISTS ${RCEDIT_PATH})
file(DOWNLOAD
"https://github.com/electron/rcedit/releases/download/v2.0.0/rcedit-x64.exe"
${RCEDIT_PATH}
)
set(VERSIONLESS_LIBWINPTHREAD "${CMAKE_BINARY_DIR}/libwinpthread-1.dll")
find_file(LIBWINPTHREAD_PATH NAMES libwinpthread-1.dll)
if (NOT LIBWINPTHREAD_PATH)
message(FATAL_ERROR "Could not find libwinpthread-1.dll!")
endif()
execute_process(COMMAND ${RCEDIT_PATH}
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/libwinpthread-1.dll"
--set-file-version "0,0,0,0"
add_custom_command(
OUTPUT ${VERSIONLESS_LIBWINPTHREAD}
COMMAND $<TARGET_FILE:version-stripper> ${LIBWINPTHREAD_PATH} ${VERSIONLESS_LIBWINPTHREAD}
DEPENDS version-stripper
COMMENT "Stripping version info from libwinpthread..."
VERBATIM
)
add_custom_target(versionless_libwinpthread ALL
DEPENDS ${VERSIONLESS_LIBWINPTHREAD}
)
# Install the generated file
install(FILES ${VERSIONLESS_LIBWINPTHREAD}
DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}"
)
]])
downloadImHexPatternsFiles(".")
elseif(UNIX AND NOT APPLE)

View File

@ -7,6 +7,7 @@ endif ()
add_subdirectory(gui)
if (WIN32)
add_subdirectory(forwarder)
add_subdirectory(version_stripper)
endif ()
if (NOT EMSCRIPTEN)

View File

@ -0,0 +1,5 @@
project(version-stripper)
add_executable(version-stripper
source/main.cpp
)

View File

@ -0,0 +1,110 @@
/**
* A simple utility to strip version resources from Windows executables.
*
* Usage: version_stripper <input path> <output path>
*
* This program copies the input executable to the output path and removes
* its version resource information.
*
* Based on https://github.com/shewitt-au/nuke_version
*/
#include <filesystem>
#include <tchar.h>
#include <windows.h>
#include <string>
#include <stdexcept>
#include <vector>
using LangIds = std::vector<WORD>;
BOOL CALLBACK EnumResLangProc(
HMODULE hModule,
LPCTSTR lpszType,
LPCTSTR lpszName,
WORD wIDLanguage,
LONG_PTR lParam
) {
auto& langs = *reinterpret_cast<LangIds*>(lParam);
langs.push_back(wIDLanguage);
return true;
}
LangIds getLangIDs(LPCTSTR pExe) {
LangIds langs;
HMODULE hMod = LoadLibrary(pExe);
if (hMod == nullptr)
throw std::runtime_error("LoadLibrary failed!");
BOOL bOK = EnumResourceLanguages(
hMod, // HMODULE hModule
RT_VERSION, // LPCTSTR lpType
MAKEINTRESOURCE(1), // LPCTSTR lpName
EnumResLangProc, // ENUMRESLANGPROC lpEnumFunc
reinterpret_cast<LONG_PTR>(&langs) // LONG_PTR lParam
);
FreeLibrary(hMod);
if (!bOK)
throw std::runtime_error("EnumResourceLanguages failed!");
return langs;
}
void nukeVersionResource(LPCTSTR pExe) {
LangIds langs = getLangIDs(pExe);
HANDLE hResUpdate = BeginUpdateResource(pExe, FALSE);
if (hResUpdate == nullptr)
throw std::runtime_error("BeginUpdateResource failed!");
for (WORD langID : langs) {
BOOL bOK = UpdateResource(
hResUpdate, // HANDLE hUpdate
RT_VERSION, // LPCTSTR lpType
MAKEINTRESOURCE(1), // LPCTSTR lpName
langID, // WORD wLanguage
nullptr, // LPVOID lpData
0 // DWORD cb
);
if (!bOK) {
EndUpdateResource(
hResUpdate, // HANDLE hUpdate
TRUE // BOOL fDiscard
);
throw std::runtime_error("UpdateResource failed! Nothing done!");
}
}
EndUpdateResource(
hResUpdate, // HANDLE hUpdate
FALSE // BOOL fDiscard
);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("Usage: %s <input path> <output path>\n", argv[0]);
return 1;
}
std::filesystem::path inputPath(argv[1]);
std::filesystem::path outputPath(argv[2]);
std::filesystem::copy(inputPath, outputPath);
try {
nukeVersionResource(outputPath.c_str());
} catch (const std::exception& e) {
fprintf(stderr, "%s", e.what());
std::filesystem::remove(outputPath);
return 1;
}
return 0;
}