build: produce shared objects for spice.exe / spice_laa.exe, disable 64-bit winxp builds (#744)

to speed up clean builds. GitHub CI time went from 20 minutes -> 10
minutes.
This commit is contained in:
bicarus
2026-06-08 17:42:41 -07:00
committed by GitHub
parent 1c6929dd84
commit 0a7ecf82a9
5 changed files with 95 additions and 32 deletions
+23 -13
View File
@@ -670,37 +670,47 @@ set(SOURCE_FILES ${SOURCE_FILES}
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES})
# spice.exe / spice_laa.exe shared objects
###########################################
# spice.exe and spice_laa.exe are compiled identically; the only difference is
# the large-address-aware bit, which is set at link time. Compile the sources
# once into a shared OBJECT library so spice_laa.exe only costs an extra link
# instead of a full recompile.
add_library(spicetools_spice_objs OBJECT ${SOURCE_FILES})
target_link_libraries(spicetools_spice_objs
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp
PRIVATE fmt::fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
target_link_libraries(spicetools_spice_objs PUBLIC winscard)
if(NOT MSVC)
set_target_properties(spicetools_spice_objs PROPERTIES COMPILE_FLAGS "-m32")
endif()
# spice.exe # spice.exe
########### ###########
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES}) add_executable(spicetools_spice ${RESOURCE_FILES})
target_link_libraries(spicetools_spice target_link_libraries(spicetools_spice PRIVATE spicetools_spice_objs)
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp
PRIVATE fmt::fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
target_link_libraries(spicetools_spice PUBLIC winscard)
set_target_properties(spicetools_spice PROPERTIES PREFIX "") set_target_properties(spicetools_spice PROPERTIES PREFIX "")
set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice") set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice")
IF(NOT MSVC) IF(NOT MSVC)
set_target_properties(spicetools_spice PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32") set_target_properties(spicetools_spice PROPERTIES LINK_FLAGS "-m32")
endif() endif()
# spice_laa.exe # spice_laa.exe
########### ###########
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES}) add_executable(spicetools_spice_laa ${RESOURCE_FILES})
target_link_libraries(spicetools_spice_laa target_link_libraries(spicetools_spice_laa PRIVATE spicetools_spice_objs)
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp
PRIVATE fmt::fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
target_link_libraries(spicetools_spice_laa PUBLIC winscard)
set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "") set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "")
set_target_properties(spicetools_spice_laa PROPERTIES OUTPUT_NAME "spice_laa") set_target_properties(spicetools_spice_laa PROPERTIES OUTPUT_NAME "spice_laa")
target_compile_definitions(spicetools_spice_laa PRIVATE SPICE32_LARGE_ADDRESS_AWARE=1)
IF(NOT MSVC) IF(NOT MSVC)
set_target_properties(spicetools_spice_laa PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32 -Wl,--large-address-aware") set_target_properties(spicetools_spice_laa PROPERTIES LINK_FLAGS "-m32 -Wl,--large-address-aware")
endif() endif()
# spice_linux.exe # spice_linux.exe
+37 -11
View File
@@ -91,14 +91,20 @@ fi
# is the XP-compatible toolchain installed? # is the XP-compatible toolchain installed?
XP_MUST_BUILD=0 XP_MUST_BUILD=0
BUILD_XP=0 # 64-bit WinXP builds are disabled by default; set to 1 to opt in
if [ -f "$TOOLCHAIN_WINXP_32" ] && [ -f "$TOOLCHAIN_WINXP_64" ]; then BUILD_XP_64_ENABLE=0
BUILD_XP=1; BUILD_XP_32=0
BUILD_XP_64=0
if [ -f "$TOOLCHAIN_WINXP_32" ]; then
BUILD_XP_32=1;
elif ((XP_MUST_BUILD > 0)) elif ((XP_MUST_BUILD > 0))
then then
echo "WinXP toolchain not available, aborting" echo "WinXP 32bit toolchain not available, aborting"
exit 1 exit 1
fi fi
if ((BUILD_XP_64_ENABLE > 0)) && [ -f "$TOOLCHAIN_WINXP_64" ]; then
BUILD_XP_64=1;
fi
# determine number of cores # determine number of cores
CORES=$(nproc) CORES=$(nproc)
@@ -113,12 +119,17 @@ echo "Git Branch: $GIT_BRANCH"
echo "Git Head: $GIT_HEAD" echo "Git Head: $GIT_HEAD"
echo "Toolchain for 32bit targets: $TOOLCHAIN_32" echo "Toolchain for 32bit targets: $TOOLCHAIN_32"
echo "Toolchain for 64bit targets: $TOOLCHAIN_64" echo "Toolchain for 64bit targets: $TOOLCHAIN_64"
if ((BUILD_XP > 0)) if ((BUILD_XP_32 > 0))
then then
echo "Toolchain for WinXP 32bit targets: $TOOLCHAIN_WINXP_32" echo "Toolchain for WinXP 32bit targets: $TOOLCHAIN_WINXP_32"
else
echo "WinXP 32bit toolchain not available, skipping WinXP 32bit builds"
fi
if ((BUILD_XP_64 > 0))
then
echo "Toolchain for WinXP 64bit targets: $TOOLCHAIN_WINXP_64" echo "Toolchain for WinXP 64bit targets: $TOOLCHAIN_WINXP_64"
else else
echo "WinXP toolchain not available, skipping WinXP builds" echo "WinXP 64bit builds disabled, skipping WinXP 64bit builds"
fi fi
echo "Distribution Name: $DIST_NAME" echo "Distribution Name: $DIST_NAME"
echo "Build Type: $BUILD_TYPE" echo "Build Type: $BUILD_TYPE"
@@ -160,7 +171,7 @@ time (
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} "$OLDPWD" && ninja ${TARGETS_64} cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} "$OLDPWD" && ninja ${TARGETS_64}
popd > /dev/null popd > /dev/null
if ((BUILD_XP > 0)) if ((BUILD_XP_32 > 0))
then then
# 32 bit Windows XP # 32 bit Windows XP
echo "" echo ""
@@ -174,7 +185,13 @@ time (
pushd ${BUILDDIR_WINXP_32} > /dev/null pushd ${BUILDDIR_WINXP_32} > /dev/null
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_WINXP_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DSPICE_XP=ON "$OLDPWD" && ninja ${TARGETS_XP32} cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_WINXP_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DSPICE_XP=ON "$OLDPWD" && ninja ${TARGETS_XP32}
popd > /dev/null popd > /dev/null
else
echo ""
echo "Skipping WinXP 32bit builds, toolchain not specified"
fi
if ((BUILD_XP_64 > 0))
then
# 64 bit Windows XP # 64 bit Windows XP
echo "" echo ""
echo "Building 64bit targets (WinXP toolchain)..." echo "Building 64bit targets (WinXP toolchain)..."
@@ -189,7 +206,7 @@ time (
popd > /dev/null popd > /dev/null
else else
echo "" echo ""
echo "Skipping WinXP builds, toolchain not specified" echo "Skipping WinXP 64bit builds"
fi fi
echo "" echo ""
@@ -197,7 +214,7 @@ time (
echo "===========================" echo "==========================="
) )
if ((BUILD_XP > 0)) if ((BUILD_XP_32 > 0)) || ((BUILD_XP_64 > 0))
then then
echo "" echo ""
echo "Checking XP compatibility..." echo "Checking XP compatibility..."
@@ -205,13 +222,19 @@ then
if ! command -v windows_dll_compat_checker &> /dev/null; then if ! command -v windows_dll_compat_checker &> /dev/null; then
echo "WARNING: windows_dll_compat_checker not found, skipping XP compatibility check" echo "WARNING: windows_dll_compat_checker not found, skipping XP compatibility check"
else else
if ((BUILD_XP_64 > 0))
then
windows_dll_compat_checker -s PREMADE/winxp_x86_64.ini \ windows_dll_compat_checker -s PREMADE/winxp_x86_64.ini \
${BUILDDIR_WINXP_64}/spicetools/64/spice64.exe ${BUILDDIR_WINXP_64}/spicetools/64/spice64.exe
fi
if ((BUILD_XP_32 > 0))
then
windows_dll_compat_checker -s PREMADE/winxp_x86_64_32bit_dlls.ini \ windows_dll_compat_checker -s PREMADE/winxp_x86_64_32bit_dlls.ini \
${BUILDDIR_WINXP_32}/spicetools/spicecfg.exe \ ${BUILDDIR_WINXP_32}/spicetools/spicecfg.exe \
${BUILDDIR_WINXP_32}/spicetools/32/spice.exe ${BUILDDIR_WINXP_32}/spicetools/32/spice.exe
fi fi
fi fi
fi
# generate PDBs # generate PDBs
if false # ((DEBUG > 0)) if false # ((DEBUG > 0))
@@ -271,7 +294,7 @@ mkdir -p ${OUTDIR_EXTRAS}/largeaddressaware
mkdir -p ${OUTDIR_EXTRAS}/linux mkdir -p ${OUTDIR_EXTRAS}/linux
mkdir -p ${OUTDIR_EXTRAS}/sdk/samples/32 mkdir -p ${OUTDIR_EXTRAS}/sdk/samples/32
mkdir -p ${OUTDIR_EXTRAS}/sdk/samples/64 mkdir -p ${OUTDIR_EXTRAS}/sdk/samples/64
if ((BUILD_XP > 0)) if ((BUILD_XP_32 > 0)) || ((BUILD_XP_64 > 0))
then then
mkdir -p ${OUTDIR_EXTRAS}/winxp mkdir -p ${OUTDIR_EXTRAS}/winxp
fi fi
@@ -301,10 +324,13 @@ else
cp ${BUILDDIR_32}/spicetools/32/sdk_sample_v0_flat_c.dll ${OUTDIR_EXTRAS}/sdk/samples/32/v0_flat_c.dll 2>/dev/null cp ${BUILDDIR_32}/spicetools/32/sdk_sample_v0_flat_c.dll ${OUTDIR_EXTRAS}/sdk/samples/32/v0_flat_c.dll 2>/dev/null
cp ${BUILDDIR_64}/spicetools/64/sdk_sample_v0_flat_c.dll ${OUTDIR_EXTRAS}/sdk/samples/64/v0_flat_c.dll 2>/dev/null cp ${BUILDDIR_64}/spicetools/64/sdk_sample_v0_flat_c.dll ${OUTDIR_EXTRAS}/sdk/samples/64/v0_flat_c.dll 2>/dev/null
cp ${BUILDDIR_64}/spicetools/64/sdk_sample_v0_cpp.dll ${OUTDIR_EXTRAS}/sdk/samples/64/v0_cpp.dll 2>/dev/null cp ${BUILDDIR_64}/spicetools/64/sdk_sample_v0_cpp.dll ${OUTDIR_EXTRAS}/sdk/samples/64/v0_cpp.dll 2>/dev/null
if ((BUILD_XP > 0)) if ((BUILD_XP_32 > 0))
then then
cp ${BUILDDIR_WINXP_32}/spicetools/spicecfg.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null cp ${BUILDDIR_WINXP_32}/spicetools/spicecfg.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null
cp ${BUILDDIR_WINXP_32}/spicetools/32/spice.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null cp ${BUILDDIR_WINXP_32}/spicetools/32/spice.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null
fi
if ((BUILD_XP_64 > 0))
then
cp ${BUILDDIR_WINXP_64}/spicetools/64/spice64.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null cp ${BUILDDIR_WINXP_64}/spicetools/64/spice64.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null
fi fi
fi fi
+7 -2
View File
@@ -1485,10 +1485,15 @@ int main_implementation(int argc, char *argv[]) {
#else #else
#ifdef SPICE64 #ifdef SPICE64
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)"); log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
#elif SPICE32_LARGE_ADDRESS_AWARE
log_info("launcher", "SpiceTools Bootstrap (x32 - Large Address Aware) (spice2x)");
#else #else
// spice.exe and spice_laa.exe share the same compiled objects; the only
// difference is the large-address-aware bit set at link time. detect it
// at runtime so the log line stays accurate without a separate compile.
if (sysutils::is_large_address_aware()) {
log_info("launcher", "SpiceTools Bootstrap (x32 - Large Address Aware) (spice2x)");
} else {
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)"); log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)");
}
#endif #endif
#endif #endif
+18
View File
@@ -589,6 +589,24 @@ namespace sysutils {
(void**)&EnumDisplayDevicesA_orig); (void**)&EnumDisplayDevicesA_orig);
} }
bool is_large_address_aware() {
auto image_base = reinterpret_cast<const uint8_t *>(GetModuleHandleW(nullptr));
if (image_base == nullptr) {
return false;
}
auto dos_header = reinterpret_cast<const IMAGE_DOS_HEADER *>(image_base);
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
return false;
}
auto nt_headers = reinterpret_cast<const IMAGE_NT_HEADERS *>(
image_base + dos_header->e_lfanew);
if (nt_headers->Signature != IMAGE_NT_SIGNATURE) {
return false;
}
return (nt_headers->FileHeader.Characteristics
& IMAGE_FILE_LARGE_ADDRESS_AWARE) != 0;
}
#if !SPICE_XP #if !SPICE_XP
bool is_running_as_admin() { bool is_running_as_admin() {
+4
View File
@@ -20,6 +20,10 @@ namespace sysutils {
const std::vector<MonitorEntry> &enumerate_monitors(); const std::vector<MonitorEntry> &enumerate_monitors();
// reads the running module's PE header to determine whether the
// IMAGE_FILE_LARGE_ADDRESS_AWARE bit is set (i.e. spice_laa.exe)
bool is_large_address_aware();
extern std::string SECOND_MONITOR_OVERRIDE; extern std::string SECOND_MONITOR_OVERRIDE;
void hook_EnumDisplayDevicesA(); void hook_EnumDisplayDevicesA();