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})
# 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
###########
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES})
target_link_libraries(spicetools_spice
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)
add_executable(spicetools_spice ${RESOURCE_FILES})
target_link_libraries(spicetools_spice PRIVATE spicetools_spice_objs)
set_target_properties(spicetools_spice PROPERTIES PREFIX "")
set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice")
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()
# spice_laa.exe
###########
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES})
target_link_libraries(spicetools_spice_laa
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)
add_executable(spicetools_spice_laa ${RESOURCE_FILES})
target_link_libraries(spicetools_spice_laa PRIVATE spicetools_spice_objs)
set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "")
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)
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()
# spice_linux.exe
+37 -11
View File
@@ -91,14 +91,20 @@ fi
# is the XP-compatible toolchain installed?
XP_MUST_BUILD=0
BUILD_XP=0
if [ -f "$TOOLCHAIN_WINXP_32" ] && [ -f "$TOOLCHAIN_WINXP_64" ]; then
BUILD_XP=1;
# 64-bit WinXP builds are disabled by default; set to 1 to opt in
BUILD_XP_64_ENABLE=0
BUILD_XP_32=0
BUILD_XP_64=0
if [ -f "$TOOLCHAIN_WINXP_32" ]; then
BUILD_XP_32=1;
elif ((XP_MUST_BUILD > 0))
then
echo "WinXP toolchain not available, aborting"
echo "WinXP 32bit toolchain not available, aborting"
exit 1
fi
if ((BUILD_XP_64_ENABLE > 0)) && [ -f "$TOOLCHAIN_WINXP_64" ]; then
BUILD_XP_64=1;
fi
# determine number of cores
CORES=$(nproc)
@@ -113,12 +119,17 @@ echo "Git Branch: $GIT_BRANCH"
echo "Git Head: $GIT_HEAD"
echo "Toolchain for 32bit targets: $TOOLCHAIN_32"
echo "Toolchain for 64bit targets: $TOOLCHAIN_64"
if ((BUILD_XP > 0))
if ((BUILD_XP_32 > 0))
then
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"
else
echo "WinXP toolchain not available, skipping WinXP builds"
echo "WinXP 64bit builds disabled, skipping WinXP 64bit builds"
fi
echo "Distribution Name: $DIST_NAME"
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}
popd > /dev/null
if ((BUILD_XP > 0))
if ((BUILD_XP_32 > 0))
then
# 32 bit Windows XP
echo ""
@@ -174,7 +185,13 @@ time (
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}
popd > /dev/null
else
echo ""
echo "Skipping WinXP 32bit builds, toolchain not specified"
fi
if ((BUILD_XP_64 > 0))
then
# 64 bit Windows XP
echo ""
echo "Building 64bit targets (WinXP toolchain)..."
@@ -189,7 +206,7 @@ time (
popd > /dev/null
else
echo ""
echo "Skipping WinXP builds, toolchain not specified"
echo "Skipping WinXP 64bit builds"
fi
echo ""
@@ -197,7 +214,7 @@ time (
echo "==========================="
)
if ((BUILD_XP > 0))
if ((BUILD_XP_32 > 0)) || ((BUILD_XP_64 > 0))
then
echo ""
echo "Checking XP compatibility..."
@@ -205,12 +222,18 @@ then
if ! command -v windows_dll_compat_checker &> /dev/null; then
echo "WARNING: windows_dll_compat_checker not found, skipping XP compatibility check"
else
if ((BUILD_XP_64 > 0))
then
windows_dll_compat_checker -s PREMADE/winxp_x86_64.ini \
${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 \
${BUILDDIR_WINXP_32}/spicetools/spicecfg.exe \
${BUILDDIR_WINXP_32}/spicetools/32/spice.exe
fi
fi
fi
# generate PDBs
@@ -271,7 +294,7 @@ mkdir -p ${OUTDIR_EXTRAS}/largeaddressaware
mkdir -p ${OUTDIR_EXTRAS}/linux
mkdir -p ${OUTDIR_EXTRAS}/sdk/samples/32
mkdir -p ${OUTDIR_EXTRAS}/sdk/samples/64
if ((BUILD_XP > 0))
if ((BUILD_XP_32 > 0)) || ((BUILD_XP_64 > 0))
then
mkdir -p ${OUTDIR_EXTRAS}/winxp
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_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
if ((BUILD_XP > 0))
if ((BUILD_XP_32 > 0))
then
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
fi
if ((BUILD_XP_64 > 0))
then
cp ${BUILDDIR_WINXP_64}/spicetools/64/spice64.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null
fi
fi
+7 -2
View File
@@ -1485,10 +1485,15 @@ int main_implementation(int argc, char *argv[]) {
#else
#ifdef SPICE64
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
#elif SPICE32_LARGE_ADDRESS_AWARE
log_info("launcher", "SpiceTools Bootstrap (x32 - Large Address Aware) (spice2x)");
#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)");
}
#endif
#endif
+18
View File
@@ -589,6 +589,24 @@ namespace sysutils {
(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
bool is_running_as_admin() {
+4
View File
@@ -20,6 +20,10 @@ namespace sysutils {
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;
void hook_EnumDisplayDevicesA();