From 272d23e937e0a91ab6e0e5d34ab80d2dfb251489 Mon Sep 17 00:00:00 2001 From: tashcan Date: Thu, 15 Oct 2026 16:40:43 -0700 Subject: [PATCH 1/7] Build the core mod with Zig Dependency URLs and pins are fixed for Zig 0.16, with verified SDK downloads and shared target settings. The xmake build stays available while the migration is prepared. The IL2CPP, Unity, SPUD, protobuf, logging and settings sources build as C++23. macOS uses the SDK curl and Windows uses Schannel, so no OpenSSL build is added. --- .gitignore | 5 + build.zig | 84 +++ build.zig.zon | 87 +++ src/mod/game/navigation.h | 2 - src/mod/version.h | 2 +- tests/dependency_smoke.cc | 67 ++ third_party/libil2cpp/utils/Il2CppHashMap.h | 4 +- third_party/libil2cpp/utils/Il2CppHashSet.h | 4 +- .../include}/sparsehash/dense_hash_map.h | 0 .../include}/sparsehash/dense_hash_set.h | 0 .../sparsehash/internal/densehashtable.h | 0 .../sparsehash/internal/hashtable-common.h | 0 .../internal/libc_allocator_with_realloc.h | 0 .../sparsehash/internal/sparseconfig.h | 0 .../sparsehash/internal/sparsehashtable.h | 0 .../include}/sparsehash/sparse_hash_map.h | 0 .../include}/sparsehash/sparse_hash_set.h | 0 .../include}/sparsehash/sparsetable.h | 0 .../include}/sparsehash/template_util.h | 0 .../include}/sparsehash/type_traits.h | 0 .../spud-src => third_party/spud}/LICENSE | 0 .../spud}/include/spud/arch.h | 0 .../spud}/include/spud/detour.h | 0 .../spud}/include/spud/diagnostics.h | 0 .../spud}/include/spud/error.h | 0 .../spud}/include/spud/memory.h | 0 .../spud}/include/spud/memory/protection.h | 0 .../spud}/include/spud/pointer.h | 0 .../spud}/include/spud/signature.h | 0 .../spud}/include/spud/utils.h | 0 .../spud}/src/detour/aarch64/aarch64.cc | 0 .../spud}/src/detour/aarch64/aarch64.h | 0 .../spud}/src/detour/chain.cc | 0 .../spud}/src/detour/chain.h | 0 .../spud}/src/detour/control_flow.cc | 0 .../spud}/src/detour/control_flow.h | 0 .../spud}/src/detour/detour.cc | 0 .../spud}/src/detour/detour_impl.h | 0 .../spud}/src/detour/detour_stub.h | 0 .../spud}/src/detour/fwd.h | 0 .../spud}/src/detour/import.cc | 0 .../spud}/src/detour/pointer.cc | 0 .../detour/x86_64/detour_context_support.masm | 0 .../spud}/src/detour/x86_64/x86_64.cc | 0 .../spud}/src/detour/x86_64/x86_64.h | 0 .../spud}/src/memory/executable_pool.cc | 0 .../spud}/src/memory/executable_pool.h | 0 .../spud}/src/memory/protection.cc | 0 .../spud}/src/memory/readable.h | 0 .../spud}/src/memory/safe_patch.cc | 0 .../spud}/src/memory/safe_patch.h | 0 .../spud}/src/memory/unwind.cc | 0 .../spud}/src/memory/unwind.h | 0 .../spud}/src/memory/unwind/apple.cc | 0 .../spud}/src/memory/unwind/compact.cc | 0 .../spud}/src/memory/unwind/dwarf.cc | 0 .../spud}/src/memory/unwind/dwarf.h | 0 .../spud}/src/memory/unwind/linux.cc | 0 .../spud}/src/memory/unwind/windows.cc | 0 .../spud}/src/memory/unwind/windows.h | 0 .../src/memory/unwind/windows_handler.cc | 0 .../spud}/src/module_path.h | 0 .../spud}/src/signature/scan.h | 0 .../spud}/src/signature/signature.cc | 0 .../spud}/src/signature/signature_avx2.cc | 0 .../spud}/src/signature/signature_neon.cc | 0 .../spud}/src/signature/signature_sse.cc | 0 .../spud}/src/utils.cc | 0 .../packages/s/spud/spud-src/CMakeLists.txt | 670 ------------------ .../spud/spud-src/cmake/generated/deps.cmake | 74 -- .../spud-src/cmake/generated/options.cmake | 8 - .../spud-src/cmake/generated/sources.cmake | 68 -- .../s/spud/spud-src/cmake/spud.manifest.json | 148 ---- .../s/spud/spud-src/cmake/spudConfig.cmake.in | 40 -- zig/ctx.zig | 281 ++++++++ zig/deps.zig | 244 +++++++ zig/deps/abseil_sources.zon | 145 ++++ zig/deps/protobuf_sources.zon | 29 + zig/mod.zig | 187 +++++ zig/protobuf.zig | 82 +++ zig/tests.zig | 194 +++++ zig/toolchains.zig | 122 ++++ zig/toolchains.zon | 19 + zig/tools/fetch_toolchain.zig | 326 +++++++++ 84 files changed, 1877 insertions(+), 1015 deletions(-) create mode 100644 build.zig create mode 100644 build.zig.zon create mode 100644 tests/dependency_smoke.cc rename third_party/{external/google => sparsehash/include}/sparsehash/dense_hash_map.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/dense_hash_set.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/internal/densehashtable.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/internal/hashtable-common.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/internal/libc_allocator_with_realloc.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/internal/sparseconfig.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/internal/sparsehashtable.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/sparse_hash_map.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/sparse_hash_set.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/sparsetable.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/template_util.h (100%) rename third_party/{external/google => sparsehash/include}/sparsehash/type_traits.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/LICENSE (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/arch.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/detour.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/diagnostics.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/error.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/memory.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/memory/protection.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/pointer.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/signature.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/include/spud/utils.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/aarch64/aarch64.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/aarch64/aarch64.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/chain.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/chain.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/control_flow.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/control_flow.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/detour.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/detour_impl.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/detour_stub.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/fwd.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/import.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/pointer.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/x86_64/detour_context_support.masm (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/x86_64/x86_64.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/detour/x86_64/x86_64.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/executable_pool.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/executable_pool.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/protection.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/readable.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/safe_patch.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/safe_patch.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/apple.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/compact.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/dwarf.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/dwarf.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/linux.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/windows.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/windows.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/memory/unwind/windows_handler.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/module_path.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/signature/scan.h (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/signature/signature.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/signature/signature_avx2.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/signature/signature_neon.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/signature/signature_sse.cc (100%) rename {xmake-packages/packages/s/spud/spud-src => third_party/spud}/src/utils.cc (100%) delete mode 100644 xmake-packages/packages/s/spud/spud-src/CMakeLists.txt delete mode 100644 xmake-packages/packages/s/spud/spud-src/cmake/generated/deps.cmake delete mode 100644 xmake-packages/packages/s/spud/spud-src/cmake/generated/options.cmake delete mode 100644 xmake-packages/packages/s/spud/spud-src/cmake/generated/sources.cmake delete mode 100644 xmake-packages/packages/s/spud/spud-src/cmake/spud.manifest.json delete mode 100644 xmake-packages/packages/s/spud/spud-src/cmake/spudConfig.cmake.in create mode 100644 zig/ctx.zig create mode 100644 zig/deps.zig create mode 100644 zig/deps/abseil_sources.zon create mode 100644 zig/deps/protobuf_sources.zon create mode 100644 zig/mod.zig create mode 100644 zig/protobuf.zig create mode 100644 zig/tests.zig create mode 100644 zig/toolchains.zig create mode 100644 zig/toolchains.zon create mode 100644 zig/tools/fetch_toolchain.zig diff --git a/.gitignore b/.gitignore index fe2d009d8..5989b63b3 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,8 @@ debug.log mods/.xmake Analyse-GameAssembly.ps1 assets/LoadingScreens/*.psd + +# zig +/zig-out/ +/.zig-cache/ +/zig-pkg/ diff --git a/build.zig b/build.zig new file mode 100644 index 000000000..11f679db4 --- /dev/null +++ b/build.zig @@ -0,0 +1,84 @@ +//! Build graph for the mod and its native test fixtures. +//! +//! zig/ctx.zig per-target compile rules (Ctx), library handles (Lib), shared options +//! zig/toolchains.zig pinned SDKs: fetch-toolchains and sysroot lookup +//! zig/deps.zig third-party C and C++ libraries +//! zig/protobuf.zig protobuf-lite, Abseil, and generated game messages +//! zig/mod.zig IL2CPP and Unity libraries, the mod, and platform entry points +//! zig/tests.zig native fixtures and the dependency smoke test +//! zig/tools/ host programs the build runs +const std = @import("std"); +const builtin = @import("builtin"); +const Ctx = @import("zig/ctx.zig").Ctx; +const Options = @import("zig/ctx.zig").Options; +const globFiles = @import("zig/ctx.zig").globFiles; +const deps = @import("zig/deps.zig"); +const mod = @import("zig/mod.zig"); +const protobuf = @import("zig/protobuf.zig"); +const tests = @import("zig/tests.zig"); +const toolchains = @import("zig/toolchains.zig"); + +comptime { + if (builtin.zig_version.order(.{ .major = 0, .minor = 16, .patch = 0 }) != .eq) + @compileError("This build is pinned to Zig 0.16.0"); +} + +pub fn build(b: *std.Build) void { + // Steps that do not depend on -Dtarget. + toolchains.addFetchSteps(b); + addFormatStep(b); + + const target = b.standardTargetOptions(.{ + .default_target = .{ .abi = if (builtin.os.tag == .windows) .msvc else null }, + }); + const optimize = b.standardOptimizeOption(.{}); + const options = Options.parse(b); + const ctx = Ctx.init(b, target, optimize, options); + + // Libraries the native fixtures share with the shipped mod. None of them need networking or a platform SDK, + // so Linux can build and run the fixtures. + const il2cpp = mod.il2cpp(ctx); + const spdlog = deps.spdlog(ctx); + const toml = deps.tomlplusplus(ctx); + const spud = deps.spud(ctx, deps.zydis(ctx), deps.capstone(ctx)); + const proto_runtime = protobuf.protobufLite(ctx, protobuf.abseil(ctx)); + // A null result means Zig still has to fetch a lazy dependency; it reruns build() once it has. + const proto = protobuf.generate(ctx, proto_runtime) orelse return; + tests.add(ctx, .{ + .il2cpp = il2cpp, + .spdlog = spdlog, + .spud = spud, + .proto = proto, + .proto_runtime = proto_runtime, + .toml = toml, + }); + if (!ctx.isWindows() and !ctx.isMacos()) return; + + // Everything below ships in, or tests, a platform build. + const zlib = deps.zlib(ctx); + const curl = deps.curl(ctx, zlib) orelse return; + const cpr = deps.cpr(ctx, curl); + const unity = mod.unity(ctx, il2cpp, spud); + mod.add(ctx, &.{ il2cpp, unity, spdlog, spud, proto, proto_runtime, cpr, curl, toml, deps.nlohmannJson(ctx) }); + tests.addDependencySmoke(ctx, &.{ proto, proto_runtime, cpr, curl, zlib }); + + // Build one dependency in isolation, to check a pin bump or a cross-compile without the mod. + const net_step = cpr.addInstallStep(b, "dep-net", "Build the platform HTTPS dependencies"); + curl.addBuildDependencies(net_step); + const proto_step = proto.addInstallStep(b, "dep-protobuf", "Build protobuf-lite and generated game messages"); + proto_runtime.addBuildDependencies(proto_step); + _ = spud.addInstallStep(b, "dep-spud", "Build SPUD and its pinned dependencies"); + _ = spdlog.addInstallStep(b, "dep-spdlog", "Build only the spdlog dependency"); +} + +/// `fmt`: clang-format for C++ and zig fmt for the build. Objective-C++ (.mm) is left alone; the C++ rules do not +/// suit it. +fn addFormatStep(b: *std.Build) void { + const step = b.step("fmt", "Format the project's C++ and Zig sources (needs clang-format on PATH)"); + const clang_format = b.addSystemCommand(&.{ "clang-format", "-i" }); + clang_format.has_side_effects = true; + inline for (.{ "src", "tests" }) |dir| + for (globFiles(b, b.path(""), dir, &.{ ".cc", ".h" }, &.{})) |file| clang_format.addFileArg(b.path(file)); + step.dependOn(&clang_format.step); + step.dependOn(&b.addFmt(.{ .paths = &.{ "build.zig", "build.zig.zon", "zig" } }).step); +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 000000000..0285ae5fa --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,87 @@ +.{ + .name = .stfc_community_mod, + .version = "0.0.0", + .fingerprint = 0x3332afbd34425758, + .minimum_zig_version = "0.16.0", + .dependencies = .{ + .spdlog = .{ + .url = "https://github.com/gabime/spdlog/archive/refs/tags/v1.17.0.tar.gz", + .hash = "N-V-__8AALV4EgBbl10jtpTgXbAMeWyE5t24VkpFyu6JKaWR", + }, + .tomlplusplus = .{ + .url = "https://github.com/marzer/tomlplusplus/archive/refs/tags/v3.4.0.tar.gz", + .hash = "N-V-__8AADK0RQD1COdtDdmDmnolfWdg42Bp8usyxNExSWf6", + }, + .nlohmann_json = .{ + .url = "https://github.com/nlohmann/json/archive/refs/tags/v3.12.0.tar.gz", + .hash = "N-V-__8AANqC8wBtv10C_41rBAgWfTMpQow7tzRi4h6LQYxm", + }, + .protobuf = .{ + .url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.1/protobuf-35.1.tar.gz", + .hash = "N-V-__8AAKESzQLTflk_8mGwLlk9VhY62vntiaDf9ZwZwX6U", + }, + .abseil = .{ + .url = "https://github.com/abseil/abseil-cpp/archive/refs/tags/20250512.1.tar.gz", + .hash = "N-V-__8AAPVZnwDbTjOwxj7Svc8jGQDVnvG3Qz1XJ-L4fuL2", + }, + .cpr = .{ + .url = "https://github.com/libcpr/cpr/archive/refs/tags/1.14.2.tar.gz", + .hash = "N-V-__8AAB5XDQDfjou0s1GHxJA1FIHZePsd9z_pVi7mF7Wj", + }, + .curl = .{ + .lazy = true, + .url = "https://github.com/curl/curl/releases/download/curl-8_21_0/curl-8.21.0.tar.xz", + .hash = "N-V-__8AALEMTAGmPn1iGtLTj0oIiySFaGadtszadQ_-WeEo", + }, + .zlib = .{ + .url = "https://github.com/madler/zlib/releases/download/v1.3.2/zlib-1.3.2.tar.gz", + .hash = "N-V-__8AAJ2cNgAgfBtAw33Bxfu1IWISDeKKSr3DAqoAysIJ", + }, + .zydis = .{ + .url = "https://github.com/zyantific/zydis/archive/refs/tags/v4.1.0.tar.gz", + .hash = "N-V-__8AAG_f3ADsgtXR-6KT0oPilS_pRzH13KCfebN3aFmV", + }, + .capstone = .{ + .url = "https://github.com/capstone-engine/capstone/archive/refs/tags/6.0.0-Alpha5.tar.gz", + .hash = "N-V-__8AAMOHLgV4MQeePit44McQPtZU2W-jHK8yptwaGKxQ", + }, + .inifile_cpp = .{ + .url = "https://github.com/Rookfighter/inifile-cpp/archive/7e49789411beba98ca2c98940c40f7ca7e4b23b5.tar.gz", + .hash = "N-V-__8AACEjAQCdTAwUfweX68VRRFPW3PBPuD1N83eAD7Qu", + }, + .librsync = .{ + .url = "https://github.com/librsync/librsync/archive/refs/tags/v2.3.4.tar.gz", + .hash = "N-V-__8AAPZ5CwCIAxNBNInePykgTCHaNsTQ1-uP5Yv3tTvm", + }, + .zycore = .{ + .url = "https://github.com/zyantific/zycore-c/archive/refs/tags/v1.5.0.tar.gz", + .hash = "N-V-__8AAOV4BwAQKJ-oHUpZyjV4gxIQJ58HDu3MsYzRq5FP", + }, + .protoc_osx_aarch_64 = .{ + .url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.1/protoc-35.1-osx-aarch_64.zip", + .hash = "N-V-__8AAIsxlACp1iWtsa4CgX7of3HQoHNIpvH_TupNRKK1", + .lazy = true, + }, + .protoc_osx_x86_64 = .{ + .url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.1/protoc-35.1-osx-x86_64.zip", + .hash = "N-V-__8AAGunlQA4VwrG3eBnzctIfhPfzbTOr32gFgkXdHbf", + .lazy = true, + }, + .protoc_linux_x86_64 = .{ + .url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.1/protoc-35.1-linux-x86_64.zip", + .hash = "N-V-__8AAOMcogCzsYJdqo1IGH01T9MlD4H9ImMkTX4AH3dO", + .lazy = true, + }, + .protoc_linux_aarch_64 = .{ + .url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.1/protoc-35.1-linux-aarch_64.zip", + .hash = "N-V-__8AAPsfogALHjIUXkHC6Bj5zxTcjsA9btJER-eLnHvA", + .lazy = true, + }, + .protoc_win64 = .{ + .url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.1/protoc-35.1-win64.zip", + .hash = "N-V-__8AAPh-yQByeYHnYD95ofHmRBZ06_htJWJtlkaX15Ci", + .lazy = true, + }, + }, + .paths = .{ "build.zig", "build.zig.zon", "zig", "src", "third_party", "assets", "tests", "LICENSE" }, +} diff --git a/src/mod/game/navigation.h b/src/mod/game/navigation.h index bbe2f06e4..310662234 100644 --- a/src/mod/game/navigation.h +++ b/src/mod/game/navigation.h @@ -307,13 +307,11 @@ struct InteriorRadiusConstraint : il2cpp::Object { void SetMaximum(float value) { SetField<"_max">(value); } }; - struct InteriorOrbitConstraint : il2cpp::Object { using Class = il2cpp::Class<"Assembly-CSharp", "Digit.Client.CameraController", "OrbitConstraint">; InteriorRadiusConstraint* Radius() { return Field<"_radius", InteriorRadiusConstraint*>(); } }; - struct InteriorOrbitProvider : il2cpp::Object { using Class = il2cpp::Class<"Assembly-CSharp", "Digit.Client.CameraController", "AbstractOrbitFrameProvider">; InteriorOrbitConstraint* Constraint() diff --git a/src/mod/version.h b/src/mod/version.h index adc0063f0..a2d79e18e 100644 --- a/src/mod/version.h +++ b/src/mod/version.h @@ -32,7 +32,7 @@ #endif #ifndef STFC_BUILD_INVOCATION_ID -#define STFC_BUILD_INVOCATION_ID "xmake-direct" +#define STFC_BUILD_INVOCATION_ID "zig-direct" #endif #ifndef STFC_BUILD_MODE diff --git a/tests/dependency_smoke.cc b/tests/dependency_smoke.cc new file mode 100644 index 000000000..ac7ac520d --- /dev/null +++ b/tests/dependency_smoke.cc @@ -0,0 +1,67 @@ +// Verify the migrated build's serialization, compression, and HTTPS contracts. +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void require(bool condition, const char* message) +{ + if (!condition) + throw std::runtime_error(message); +} + +int main(int argc, char** argv) +{ + try { + google::protobuf::Int64Value value; + value.set_value(42); + google::protobuf::Int64Value decoded; + require(decoded.ParseFromString(value.SerializeAsString()) && decoded.value() == 42, "protobuf wrappers failed"); + google::protobuf::Timestamp timestamp; + timestamp.set_seconds(123456789); + google::protobuf::Timestamp restored; + require(restored.ParseFromString(timestamp.SerializeAsString()) && restored.seconds() == timestamp.seconds(), + "protobuf timestamp failed"); + + const std::string input = "zig-network-ok"; + unsigned char compressed[128], output[128]; + uLongf compressed_size = sizeof(compressed), output_size = sizeof(output); + require(compress(compressed, &compressed_size, reinterpret_cast(input.data()), input.size()) == Z_OK, + "zlib compression failed"); + require(uncompress(output, &output_size, compressed, compressed_size) == Z_OK && output_size == input.size() + && std::memcmp(output, input.data(), input.size()) == 0, + "zlib round trip failed"); + + const auto* version = curl_version_info(CURLVERSION_NOW); + require(version && (version->features & CURL_VERSION_SSL) && (version->features & CURL_VERSION_LIBZ), + "curl must support TLS and zlib"); +#if _WIN32 + require(version->ssl_version && std::strstr(version->ssl_version, "Schannel"), "Windows must use Schannel"); +#else + require(version->ssl_version != nullptr, "macOS system curl must provide TLS"); +#endif + if (argc > 1) { + cpr::Session session; + session.SetUrl(cpr::Url{argv[1]}); + session.SetTimeout(cpr::Timeout{5000}); + if (argc > 2) + session.SetSslOptions(cpr::Ssl(cpr::ssl::CaInfo{argv[2]})); + const auto response = session.Get(); + if (response.error.code != cpr::ErrorCode::OK) + std::cerr << response.error.message << '\n'; + require(response.error.code == cpr::ErrorCode::OK && response.status_code == 200 && response.text == input, + "HTTP(S) round trip failed"); + } + std::cout << "Dependency smoke checks passed: " << version->ssl_version << '\n'; + return 0; + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + return 1; + } +} diff --git a/third_party/libil2cpp/utils/Il2CppHashMap.h b/third_party/libil2cpp/utils/Il2CppHashMap.h index 73ee38c0b..9e863b1f6 100644 --- a/third_party/libil2cpp/utils/Il2CppHashMap.h +++ b/third_party/libil2cpp/utils/Il2CppHashMap.h @@ -4,9 +4,9 @@ #pragma push_macro("GROUP_SIZE") #undef GROUP_SIZE #if IL2CPP_USE_SPARSEHASH -#include "../../external/google/sparsehash/sparse_hash_map.h" +#include #else -#include "../../external/google/sparsehash/dense_hash_map.h" +#include #endif #pragma pop_macro("GROUP_SIZE") diff --git a/third_party/libil2cpp/utils/Il2CppHashSet.h b/third_party/libil2cpp/utils/Il2CppHashSet.h index 0e23a9f9c..ab0f4d05f 100644 --- a/third_party/libil2cpp/utils/Il2CppHashSet.h +++ b/third_party/libil2cpp/utils/Il2CppHashSet.h @@ -4,9 +4,9 @@ #pragma push_macro("GROUP_SIZE") #undef GROUP_SIZE #if IL2CPP_USE_SPARSEHASH -#include "../../external/google/sparsehash/sparse_hash_set.h" +#include #else -#include "../../external/google/sparsehash/dense_hash_set.h" +#include #endif #pragma pop_macro("GROUP_SIZE") diff --git a/third_party/external/google/sparsehash/dense_hash_map.h b/third_party/sparsehash/include/sparsehash/dense_hash_map.h similarity index 100% rename from third_party/external/google/sparsehash/dense_hash_map.h rename to third_party/sparsehash/include/sparsehash/dense_hash_map.h diff --git a/third_party/external/google/sparsehash/dense_hash_set.h b/third_party/sparsehash/include/sparsehash/dense_hash_set.h similarity index 100% rename from third_party/external/google/sparsehash/dense_hash_set.h rename to third_party/sparsehash/include/sparsehash/dense_hash_set.h diff --git a/third_party/external/google/sparsehash/internal/densehashtable.h b/third_party/sparsehash/include/sparsehash/internal/densehashtable.h similarity index 100% rename from third_party/external/google/sparsehash/internal/densehashtable.h rename to third_party/sparsehash/include/sparsehash/internal/densehashtable.h diff --git a/third_party/external/google/sparsehash/internal/hashtable-common.h b/third_party/sparsehash/include/sparsehash/internal/hashtable-common.h similarity index 100% rename from third_party/external/google/sparsehash/internal/hashtable-common.h rename to third_party/sparsehash/include/sparsehash/internal/hashtable-common.h diff --git a/third_party/external/google/sparsehash/internal/libc_allocator_with_realloc.h b/third_party/sparsehash/include/sparsehash/internal/libc_allocator_with_realloc.h similarity index 100% rename from third_party/external/google/sparsehash/internal/libc_allocator_with_realloc.h rename to third_party/sparsehash/include/sparsehash/internal/libc_allocator_with_realloc.h diff --git a/third_party/external/google/sparsehash/internal/sparseconfig.h b/third_party/sparsehash/include/sparsehash/internal/sparseconfig.h similarity index 100% rename from third_party/external/google/sparsehash/internal/sparseconfig.h rename to third_party/sparsehash/include/sparsehash/internal/sparseconfig.h diff --git a/third_party/external/google/sparsehash/internal/sparsehashtable.h b/third_party/sparsehash/include/sparsehash/internal/sparsehashtable.h similarity index 100% rename from third_party/external/google/sparsehash/internal/sparsehashtable.h rename to third_party/sparsehash/include/sparsehash/internal/sparsehashtable.h diff --git a/third_party/external/google/sparsehash/sparse_hash_map.h b/third_party/sparsehash/include/sparsehash/sparse_hash_map.h similarity index 100% rename from third_party/external/google/sparsehash/sparse_hash_map.h rename to third_party/sparsehash/include/sparsehash/sparse_hash_map.h diff --git a/third_party/external/google/sparsehash/sparse_hash_set.h b/third_party/sparsehash/include/sparsehash/sparse_hash_set.h similarity index 100% rename from third_party/external/google/sparsehash/sparse_hash_set.h rename to third_party/sparsehash/include/sparsehash/sparse_hash_set.h diff --git a/third_party/external/google/sparsehash/sparsetable.h b/third_party/sparsehash/include/sparsehash/sparsetable.h similarity index 100% rename from third_party/external/google/sparsehash/sparsetable.h rename to third_party/sparsehash/include/sparsehash/sparsetable.h diff --git a/third_party/external/google/sparsehash/template_util.h b/third_party/sparsehash/include/sparsehash/template_util.h similarity index 100% rename from third_party/external/google/sparsehash/template_util.h rename to third_party/sparsehash/include/sparsehash/template_util.h diff --git a/third_party/external/google/sparsehash/type_traits.h b/third_party/sparsehash/include/sparsehash/type_traits.h similarity index 100% rename from third_party/external/google/sparsehash/type_traits.h rename to third_party/sparsehash/include/sparsehash/type_traits.h diff --git a/xmake-packages/packages/s/spud/spud-src/LICENSE b/third_party/spud/LICENSE similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/LICENSE rename to third_party/spud/LICENSE diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/arch.h b/third_party/spud/include/spud/arch.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/arch.h rename to third_party/spud/include/spud/arch.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/detour.h b/third_party/spud/include/spud/detour.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/detour.h rename to third_party/spud/include/spud/detour.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/diagnostics.h b/third_party/spud/include/spud/diagnostics.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/diagnostics.h rename to third_party/spud/include/spud/diagnostics.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/error.h b/third_party/spud/include/spud/error.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/error.h rename to third_party/spud/include/spud/error.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/memory.h b/third_party/spud/include/spud/memory.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/memory.h rename to third_party/spud/include/spud/memory.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/memory/protection.h b/third_party/spud/include/spud/memory/protection.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/memory/protection.h rename to third_party/spud/include/spud/memory/protection.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/pointer.h b/third_party/spud/include/spud/pointer.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/pointer.h rename to third_party/spud/include/spud/pointer.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/signature.h b/third_party/spud/include/spud/signature.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/signature.h rename to third_party/spud/include/spud/signature.h diff --git a/xmake-packages/packages/s/spud/spud-src/include/spud/utils.h b/third_party/spud/include/spud/utils.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/include/spud/utils.h rename to third_party/spud/include/spud/utils.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/aarch64/aarch64.cc b/third_party/spud/src/detour/aarch64/aarch64.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/aarch64/aarch64.cc rename to third_party/spud/src/detour/aarch64/aarch64.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/aarch64/aarch64.h b/third_party/spud/src/detour/aarch64/aarch64.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/aarch64/aarch64.h rename to third_party/spud/src/detour/aarch64/aarch64.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/chain.cc b/third_party/spud/src/detour/chain.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/chain.cc rename to third_party/spud/src/detour/chain.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/chain.h b/third_party/spud/src/detour/chain.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/chain.h rename to third_party/spud/src/detour/chain.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/control_flow.cc b/third_party/spud/src/detour/control_flow.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/control_flow.cc rename to third_party/spud/src/detour/control_flow.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/control_flow.h b/third_party/spud/src/detour/control_flow.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/control_flow.h rename to third_party/spud/src/detour/control_flow.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/detour.cc b/third_party/spud/src/detour/detour.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/detour.cc rename to third_party/spud/src/detour/detour.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/detour_impl.h b/third_party/spud/src/detour/detour_impl.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/detour_impl.h rename to third_party/spud/src/detour/detour_impl.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/detour_stub.h b/third_party/spud/src/detour/detour_stub.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/detour_stub.h rename to third_party/spud/src/detour/detour_stub.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/fwd.h b/third_party/spud/src/detour/fwd.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/fwd.h rename to third_party/spud/src/detour/fwd.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/import.cc b/third_party/spud/src/detour/import.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/import.cc rename to third_party/spud/src/detour/import.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/pointer.cc b/third_party/spud/src/detour/pointer.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/pointer.cc rename to third_party/spud/src/detour/pointer.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/x86_64/detour_context_support.masm b/third_party/spud/src/detour/x86_64/detour_context_support.masm similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/x86_64/detour_context_support.masm rename to third_party/spud/src/detour/x86_64/detour_context_support.masm diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/x86_64/x86_64.cc b/third_party/spud/src/detour/x86_64/x86_64.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/x86_64/x86_64.cc rename to third_party/spud/src/detour/x86_64/x86_64.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/detour/x86_64/x86_64.h b/third_party/spud/src/detour/x86_64/x86_64.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/detour/x86_64/x86_64.h rename to third_party/spud/src/detour/x86_64/x86_64.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/executable_pool.cc b/third_party/spud/src/memory/executable_pool.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/executable_pool.cc rename to third_party/spud/src/memory/executable_pool.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/executable_pool.h b/third_party/spud/src/memory/executable_pool.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/executable_pool.h rename to third_party/spud/src/memory/executable_pool.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/protection.cc b/third_party/spud/src/memory/protection.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/protection.cc rename to third_party/spud/src/memory/protection.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/readable.h b/third_party/spud/src/memory/readable.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/readable.h rename to third_party/spud/src/memory/readable.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/safe_patch.cc b/third_party/spud/src/memory/safe_patch.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/safe_patch.cc rename to third_party/spud/src/memory/safe_patch.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/safe_patch.h b/third_party/spud/src/memory/safe_patch.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/safe_patch.h rename to third_party/spud/src/memory/safe_patch.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind.cc b/third_party/spud/src/memory/unwind.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind.cc rename to third_party/spud/src/memory/unwind.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind.h b/third_party/spud/src/memory/unwind.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind.h rename to third_party/spud/src/memory/unwind.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/apple.cc b/third_party/spud/src/memory/unwind/apple.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/apple.cc rename to third_party/spud/src/memory/unwind/apple.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/compact.cc b/third_party/spud/src/memory/unwind/compact.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/compact.cc rename to third_party/spud/src/memory/unwind/compact.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/dwarf.cc b/third_party/spud/src/memory/unwind/dwarf.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/dwarf.cc rename to third_party/spud/src/memory/unwind/dwarf.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/dwarf.h b/third_party/spud/src/memory/unwind/dwarf.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/dwarf.h rename to third_party/spud/src/memory/unwind/dwarf.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/linux.cc b/third_party/spud/src/memory/unwind/linux.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/linux.cc rename to third_party/spud/src/memory/unwind/linux.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/windows.cc b/third_party/spud/src/memory/unwind/windows.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/windows.cc rename to third_party/spud/src/memory/unwind/windows.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/windows.h b/third_party/spud/src/memory/unwind/windows.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/windows.h rename to third_party/spud/src/memory/unwind/windows.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/memory/unwind/windows_handler.cc b/third_party/spud/src/memory/unwind/windows_handler.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/memory/unwind/windows_handler.cc rename to third_party/spud/src/memory/unwind/windows_handler.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/module_path.h b/third_party/spud/src/module_path.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/module_path.h rename to third_party/spud/src/module_path.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/signature/scan.h b/third_party/spud/src/signature/scan.h similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/signature/scan.h rename to third_party/spud/src/signature/scan.h diff --git a/xmake-packages/packages/s/spud/spud-src/src/signature/signature.cc b/third_party/spud/src/signature/signature.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/signature/signature.cc rename to third_party/spud/src/signature/signature.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/signature/signature_avx2.cc b/third_party/spud/src/signature/signature_avx2.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/signature/signature_avx2.cc rename to third_party/spud/src/signature/signature_avx2.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/signature/signature_neon.cc b/third_party/spud/src/signature/signature_neon.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/signature/signature_neon.cc rename to third_party/spud/src/signature/signature_neon.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/signature/signature_sse.cc b/third_party/spud/src/signature/signature_sse.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/signature/signature_sse.cc rename to third_party/spud/src/signature/signature_sse.cc diff --git a/xmake-packages/packages/s/spud/spud-src/src/utils.cc b/third_party/spud/src/utils.cc similarity index 100% rename from xmake-packages/packages/s/spud/spud-src/src/utils.cc rename to third_party/spud/src/utils.cc diff --git a/xmake-packages/packages/s/spud/spud-src/CMakeLists.txt b/xmake-packages/packages/s/spud/spud-src/CMakeLists.txt deleted file mode 100644 index 9f67fabb8..000000000 --- a/xmake-packages/packages/s/spud/spud-src/CMakeLists.txt +++ /dev/null @@ -1,670 +0,0 @@ -cmake_minimum_required(VERSION 3.23 FATAL_ERROR) - -if(WIN32) - project(spud VERSION 0.1.0 LANGUAGES C CXX ASM_MASM) -else() - project(spud VERSION 0.1.0 LANGUAGES C CXX ASM) -endif(WIN32) - -# Only the top-level project owns BUILD_TESTING and the CTest dashboard targets. -if(PROJECT_IS_TOP_LEVEL) - include(CTest) -endif() -include(FetchContent) -# Timestamps of extracted dependency tarballs are the extraction time, so a -# changed pin rebuilds. -if(POLICY CMP0135) - cmake_policy(SET CMP0135 NEW) -endif() -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) - -if(PROJECT_IS_TOP_LEVEL) - set(CMAKE_CXX_STANDARD 20) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") -endif() - -option(SPUD_BUILD_TESTS "Build Catch2 unit tests" ${PROJECT_IS_TOP_LEVEL}) -option(SPUD_BUILD_BENCHMARKS "Build Catch2 benchmarks" ${PROJECT_IS_TOP_LEVEL}) -option(SPUD_BUILD_EXAMPLES "Build example programs" ${PROJECT_IS_TOP_LEVEL}) - -if( - CMAKE_SYSTEM_PROCESSOR MATCHES "arm" - OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch" - OR CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64" -) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH "arm64") - else() - set(ARCH "arm") - endif() -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips.*") - message(FATAL_ERROR "MIPS is not a supported Spud architecture") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc.*") - message(FATAL_ERROR "PowerPC is not a supported Spud architecture") -else() - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH "x86_64") - else() - message(FATAL_ERROR "32-bit x86 is not a supported Spud architecture") - endif() -endif() - -if(CMAKE_OSX_ARCHITECTURES) - list(LENGTH CMAKE_OSX_ARCHITECTURES _spud_osx_arch_count) - if(_spud_osx_arch_count GREATER 1) - message( - FATAL_ERROR - "Spud does not support universal binaries. Specify one of arm64, x86_64." - ) - endif() - if(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") - set(ARCH "arm64") - elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64") - set(ARCH "x86_64") - else() - message( - FATAL_ERROR - "Architecture ${CMAKE_OSX_ARCHITECTURES} is not supported. " - "Use arm64 or x86_64." - ) - endif() -endif() - -if(NOT ARCH STREQUAL "x86_64" AND NOT ARCH STREQUAL "arm64") - message(FATAL_ERROR "Architecture ${ARCH} is not supported") -endif() -if(WIN32 AND ARCH STREQUAL "arm64") - message(FATAL_ERROR "Windows ARM64 is not a supported Spud target") -endif() - -# ARM64 hosts need the Capstone-backed backend. x86-64 builds only compile it -# when asked, or for the unit tests, which check ARM64 encodings on every host. -if(ARCH STREQUAL "arm64" OR SPUD_BUILD_TESTS) - set(SPUD_AARCH64_DEFAULT ON) -else() - set(SPUD_AARCH64_DEFAULT OFF) -endif() - -# Generated from cmake/spud.manifest.json by `zig build gen-cmake`. -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/generated/options.cmake") -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/generated/deps.cmake") -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/generated/sources.cmake") - -# Deprecated spelling, kept so existing -DSPUD_NO_INSTALL=ON builds still work. -if(SPUD_NO_INSTALL) - message(DEPRECATION "SPUD_NO_INSTALL is deprecated; use SPUD_INSTALL=OFF") - set(SPUD_INSTALL OFF) -endif() - - -spud_provide_zydis() -spud_provide_capstone() - -add_library("spud" STATIC) -add_library(spud::spud ALIAS spud) -target_compile_features("spud" PUBLIC cxx_std_20) -target_link_libraries("spud" PRIVATE "Zydis") -if(WIN32) - target_link_libraries("spud" PRIVATE "psapi") -endif() -if(SPUD_AARCH64_SUPPORT) - target_link_libraries("spud" PRIVATE "capstone") -endif() - -# Warnings for spud's own targets, never for vendored code. Errors are for -# CI only, so a newer compiler's new warning cannot break a consumer build. -function(spud_warnings target) - if(MSVC) - target_compile_options(${target} PRIVATE "/permissive-" "/W4") - if(SPUD_WARNINGS_AS_ERRORS) - target_compile_options(${target} PRIVATE "/WX") - endif() - else() - target_compile_options(${target} PRIVATE -Wall -Wextra) - if(SPUD_WARNINGS_AS_ERRORS) - target_compile_options(${target} PRIVATE -Werror) - endif() - endif() -endfunction() -spud_warnings(spud) -if(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC) - target_compile_options(spud PUBLIC $<$:-fms-extensions>) -endif() - -if(SPUD_DETOUR_TRACING) - target_compile_definitions(spud PUBLIC SPUD_DETOUR_TRACING=1) -endif() - -target_compile_definitions(spud PUBLIC - SPUD_UNWIND_SUPPORT=$) - -# No public header reads it; the tests that include src/ add it themselves. -if(SPUD_AARCH64_SUPPORT) - target_compile_definitions(spud PRIVATE SPUD_AARCH64_SUPPORT=1) -endif() - -target_compile_definitions(spud PRIVATE NOMINMAX=1) - -# No forced LTO. GCC's IPO objects are LTO-only (-fno-fat-lto-objects), so an -# installed libspud.a would only link with the same GCC and plugin. Set -# CMAKE_INTERPROCEDURAL_OPTIMIZATION in the consuming build to opt in. - -target_sources( - "spud" - PUBLIC - FILE_SET public_headers - TYPE HEADERS - BASE_DIRS "include" - FILES ${SPUD_PUBLIC_HDRS} -) -target_include_directories( - "spud" - PUBLIC - $ - $ - PRIVATE "src" -) - -if(ARCH STREQUAL "arm64" AND NOT SPUD_AARCH64_SUPPORT) - message(FATAL_ERROR "ARM64 hosts require SPUD_AARCH64_SUPPORT=ON") -endif() - -# GCC and Clang read the hook context register with inline assembly; MSVC -# has no x64 inline assembly and calls this helper instead. -# CMake's MASM language only claims .asm files, so the .masm helper needs an -# explicit language or it is silently left out of the library. clang-cl -# takes the inline path like Clang everywhere else. -set(ASM_SRCS "") -if(MSVC AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(ASM_SRCS ${SPUD_ASM_X86_64_MASM}) - set_source_files_properties(${ASM_SRCS} PROPERTIES LANGUAGE ASM_MASM) -endif() - -if(ARCH STREQUAL "arm64") - set(SPUD_NEON_SRCS ${SPUD_SIMD_NEON_SRCS}) - set(SPUD_SSE_SRCS "") - set(SPUD_AVX2_SRCS "") -else() - set(SPUD_SSE_SRCS ${SPUD_SIMD_SSE_SRCS}) - set(SPUD_AVX2_SRCS ${SPUD_SIMD_AVX2_SRCS}) - set(SPUD_NEON_SRCS "") -endif() - -set(SPUD_AARCH64_FILES "") -if(SPUD_AARCH64_SUPPORT) - set(SPUD_AARCH64_FILES ${SPUD_AARCH64_BACKEND_SRCS}) -endif() - -target_sources( - "spud" - PRIVATE - ${SPUD_COMMON_SRCS} - "${SPUD_AARCH64_FILES}" - "${ASM_SRCS}" - "${SPUD_SSE_SRCS}" - "${SPUD_AVX2_SRCS}" - "${SPUD_NEON_SRCS}" -) - -if(SPUD_INSTALL) - if(SPUD_UNWIND_SUPPORT) - set(SPUD_UNWIND_SUPPORT_VALUE 1) - else() - set(SPUD_UNWIND_SUPPORT_VALUE 0) - endif() - if(SPUD_DETOUR_TRACING) - set(SPUD_DETOUR_TRACING_VALUE 1) - else() - set(SPUD_DETOUR_TRACING_VALUE 0) - endif() - set(SPUD_STATIC_LIB_FILENAME - "${CMAKE_STATIC_LIBRARY_PREFIX}spud${CMAKE_STATIC_LIBRARY_SUFFIX}" - ) - set(SPUD_ZYDIS_FILENAME - "${CMAKE_STATIC_LIBRARY_PREFIX}Zydis${CMAKE_STATIC_LIBRARY_SUFFIX}" - ) - set(SPUD_ZYCORE_FILENAME - "${CMAKE_STATIC_LIBRARY_PREFIX}Zycore${CMAKE_STATIC_LIBRARY_SUFFIX}" - ) - - install( - TARGETS ${PROJECT_NAME} - FILE_SET public_headers - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - ) - install( - FILES - "$" - "$" - DESTINATION "${CMAKE_INSTALL_LIBDIR}" - ) - configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/spudConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/spudConfig.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/spud" - PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR - ) - write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/spudConfigVersion.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion - ) - install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/spudConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/spudConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/spud" - ) -endif() - -if(SPUD_BUILD_TESTS OR SPUD_BUILD_BENCHMARKS) - spud_provide_catch2() - # The signature scan corpus, compiled once for both executables. - add_library(spud_scan_corpus OBJECT "tests/test_bin.cc") - target_link_libraries(spud_scan_corpus PRIVATE spud) -endif() - -if(SPUD_BUILD_BENCHMARKS) - add_executable("spud.benchmark" benchmark/test.cc) - target_link_libraries( - "spud.benchmark" - PRIVATE "Catch2" "Catch2::Catch2WithMain" "spud" spud_scan_corpus - ) - target_include_directories("spud.benchmark" PRIVATE "benchmark" "tests") - spud_warnings(spud.benchmark) -endif() - -if(SPUD_BUILD_TESTS) - set(TEST_SRCS "tests/signature.cc") - - file( - GLOB_RECURSE TEST_DETOUR_SHARED_SRCS CONFIGURE_DEPENDS - tests/detour/shared/*.cc - tests/detour/shared/*.h - ) - list(APPEND TEST_SRCS ${TEST_DETOUR_SHARED_SRCS}) - if(NOT MSVC) - set_source_files_properties( - "tests/detour/shared/instrumented.cc" - PROPERTIES COMPILE_OPTIONS "-finstrument-functions") - endif() - - if(ARCH MATCHES "arm64") - file( - GLOB_RECURSE TEST_DETOUR_SRCS CONFIGURE_DEPENDS - tests/detour/arm64/*.cc - tests/detour/arm64/*.h - ) - else() - file( - GLOB_RECURSE TEST_DETOUR_SRCS CONFIGURE_DEPENDS - tests/detour/x86_64/*.cc - tests/detour/x86_64/*.h - ) - endif() - - # clang-cl assembles the GAS form; MSVC needs the MASM twin. - if(WIN32 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") - file(GLOB_RECURSE TEST_ASM_SRCS CONFIGURE_DEPENDS tests/detour/x86_64/*.asm) - else() - if(ARCH MATCHES "arm64") - file(GLOB_RECURSE TEST_ASM_SRCS CONFIGURE_DEPENDS tests/detour/arm64/*.S) - else() - file(GLOB_RECURSE TEST_ASM_SRCS CONFIGURE_DEPENDS tests/detour/x86_64/*.S) - endif() - endif() - - list(APPEND TEST_SRCS ${TEST_DETOUR_SRCS}) - list(APPEND TEST_SRCS ${TEST_ASM_SRCS}) - - add_executable( - "spud.test" - ${TEST_SRCS} - "tests/test_util.h" - "tests/test_util.cc" - ) - add_library(spud_import_probe SHARED "tests/detour/shared/import_probe.c") - set_target_properties( - spud_import_probe - PROPERTIES - WINDOWS_EXPORT_ALL_SYMBOLS ON - LIBRARY_OUTPUT_DIRECTORY "$" - RUNTIME_OUTPUT_DIRECTORY "$" - ) - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - add_library(spud_import_lazy SHARED "tests/detour/shared/import_lazy.c") - target_link_libraries(spud_import_lazy PRIVATE spud_import_probe) - target_link_options(spud_import_lazy PRIVATE "LINKER:-z,lazy") - set_target_properties( - spud_import_lazy - PROPERTIES LIBRARY_OUTPUT_DIRECTORY "$" - ) - target_link_libraries("spud.test" PRIVATE spud_import_lazy) - target_compile_definitions("spud.test" PRIVATE SPUD_TEST_LAZY_IMPORT=1) - endif() - target_include_directories("spud.test" PRIVATE "tests" "src") - spud_warnings(spud.test) - target_link_libraries( - "spud.test" - PRIVATE - "Catch2" - "Catch2::Catch2WithMain" - "spud" - "Zydis" - spud_import_probe - spud_scan_corpus - ) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries("spud.test" PRIVATE "capstone") - endif() - - add_test(NAME spud.test COMMAND spud.test) - # A hung patch should fail the run, not stall CI until its global limit. - # The suite takes well under a minute on a desktop; 300 s leaves room - # for slow shared runners. - set_tests_properties(spud.test PROPERTIES TIMEOUT 300) - # Inline overflow checks that trap without a runtime; -O2 keeps clang's - # trap block after the return, the shape the prologue scan must end on. - if(NOT ARCH MATCHES "arm64" AND NOT WIN32 AND - CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - set_source_files_properties(tests/detour/x86_64/sanitized/sanitized.cc - PROPERTIES COMPILE_OPTIONS - "-O2;-fsanitize=signed-integer-overflow;-fsanitize-trap=signed-integer-overflow") - endif() - # A dense switch becomes a register-dispatched jump table at -O2. MSVC - # debug builds cannot mix /O2 with /RTC1, so they test the plain form. - if(NOT ARCH MATCHES "arm64" AND NOT MSVC) - set_source_files_properties(tests/detour/x86_64/optimized/switch.cc - PROPERTIES COMPILE_OPTIONS "-O2") - endif() - # GCC moves catch handlers into .cold parts at -O2. - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set_source_files_properties(tests/detour/shared/cold_landing.cc - PROPERTIES COMPILE_OPTIONS "-O2") - endif() - if(NOT WIN32) - add_executable(spud.window_allocations tests/detour/audit/window_allocations.cc) - target_include_directories(spud.window_allocations PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.window_allocations PRIVATE spud) - add_test(NAME spud.window_allocations COMMAND spud.window_allocations) - endif() - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - add_library(spud.source_module_library MODULE tests/detour/audit/source_module_library.c) - add_executable(spud.source_module tests/detour/audit/source_module.cc) - target_link_libraries(spud.source_module PRIVATE spud ${CMAKE_DL_LIBS}) - add_test(NAME spud.source_module COMMAND spud.source_module $) - add_test(NAME spud.source_module_disabled COMMAND spud.source_module $ disabled) - # A non-PIE executable takes a function's address as its own PLT - # entry, and -z lazy leaves the GOT slot behind it unbound. - add_executable(spud.lazy_import tests/detour/audit/lazy_import.cc) - target_include_directories(spud.lazy_import PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests) - target_compile_options(spud.lazy_import PRIVATE -fno-pie) - target_link_options(spud.lazy_import PRIVATE -no-pie "LINKER:-z,lazy") - target_link_libraries(spud.lazy_import PRIVATE spud spud_import_probe) - add_test(NAME spud.lazy_import COMMAND spud.lazy_import) - endif() - if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND ARCH STREQUAL "x86_64") - # Hand-assembled relocation hazards from the relocation audit, one - # process per case and mode because a bad trampoline faults. `near` - # emits a trampoline next to the code, `hook` installs a detour. - # Accepted cases must return the original result; refused ones must - # be refused (limits.md lists why), not run. - add_executable(spud.relocation_probe tests/detour/audit/probe.cc) - target_include_directories(spud.relocation_probe PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.relocation_probe PRIVATE spud Zydis) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries(spud.relocation_probe PRIVATE capstone) - endif() - # `near` writes trampoline dumps to the working directory. - set(_spud_probe_dir "${CMAKE_CURRENT_BINARY_DIR}/relocation-probe") - file(MAKE_DIRECTORY "${_spud_probe_dir}") - set(_spud_probe_accepted r11_indirect gs_push gs_call ah_load push16 - rsp_store eip_load late_self_read backedge_1100 backedge_padding - pop_slot gs_self) - # PC discovery (call_pc, x87_pc), a segmented indirect jump, branches - # into the middle of a copied instruction, an indirect jump back into - # the copy, and register-indexed RIP bit operations. - set(_spud_probe_refused call_pc gs_jmp overlap_branch overlap_rewrite - overlap_movabs backedge_indirect bt_dynamic_self bts_dynamic_self - x87_pc) - foreach(_case ${_spud_probe_accepted} ${_spud_probe_refused}) - foreach(_mode near hook) - # gs_self reads its own first byte through a nonzero GS base. - # Aliases into the patch through a segment base are outside - # the detour contract, so hooked it reads the jump stub. - if(_case STREQUAL "gs_self" AND _mode STREQUAL "hook") - continue() - endif() - set(_test spud.relocation_probe.${_case}.${_mode}) - add_test(NAME ${_test} - COMMAND spud.relocation_probe ${_case} ${_mode} - WORKING_DIRECTORY "${_spud_probe_dir}") - set_tests_properties(${_test} PROPERTIES TIMEOUT 30) - if(_case IN_LIST _spud_probe_refused) - # Exit code 3 with REFUSED; a run that gets as far as - # printing a result did not refuse. - set_tests_properties(${_test} PROPERTIES - PASS_REGULAR_EXPRESSION "REFUSED" - FAIL_REGULAR_EXPRESSION "actual=") - endif() - endforeach() - endforeach() - endif() - if(SPUD_UNWIND_SUPPORT AND - ((CMAKE_SYSTEM_NAME STREQUAL "Linux" AND (ARCH STREQUAL "x86_64" OR ARCH STREQUAL "arm64")) OR - (APPLE AND ARCH STREQUAL "arm64"))) - add_executable(spud.spill_unwind tests/detour/audit/spill_unwind.cc) - target_include_directories(spud.spill_unwind PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.spill_unwind PRIVATE spud Zydis) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries(spud.spill_unwind PRIVATE capstone) - endif() - add_test(NAME spud.spill_unwind COMMAND spud.spill_unwind) - set_tests_properties(spud.spill_unwind PROPERTIES SKIP_RETURN_CODE 77) - endif() - if(WIN32) - add_executable(spud.windows_unwind tests/detour/audit/windows_unwind.cc) - if(MSVC) - target_sources(spud.windows_unwind PRIVATE tests/detour/audit/windows_msvc.cc) - target_compile_definitions(spud.windows_unwind PRIVATE SPUD_MSVC_FIXTURE=1 SPUD_MSVC_GS_FIXTURE=1) - # The fixture deliberately throws through extern "C" entries. - set_source_files_properties(tests/detour/audit/windows_msvc.cc - PROPERTIES COMPILE_OPTIONS "/EHsc-") - endif() - target_include_directories(spud.windows_unwind PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.windows_unwind PRIVATE spud Zydis) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries(spud.windows_unwind PRIVATE capstone) - endif() - add_test(NAME spud.windows_unwind COMMAND spud.windows_unwind) - endif() - if(APPLE AND SPUD_UNWIND_SUPPORT) - add_executable(spud.macos_unwind tests/detour/audit/macos_unwind.cc) - target_include_directories(spud.macos_unwind PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.macos_unwind PRIVATE spud) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries(spud.macos_unwind PRIVATE capstone) - endif() - add_test(NAME spud.macos_unwind COMMAND spud.macos_unwind) - if(ARCH STREQUAL "x86_64") - add_executable(spud.macos_unwind_fde - tests/detour/audit/macos_unwind.cc - tests/detour/audit/macos_fde.cc) - target_include_directories(spud.macos_unwind_fde PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.macos_unwind_fde PRIVATE spud) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries(spud.macos_unwind_fde PRIVATE capstone) - endif() - add_test(NAME spud.macos_unwind_fde COMMAND spud.macos_unwind_fde) - endif() - add_executable(spud.macos_compact tests/detour/audit/macos_compact.cc) - target_include_directories(spud.macos_compact PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.macos_compact PRIVATE spud Zydis) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries(spud.macos_compact PRIVATE capstone) - endif() - add_test(NAME spud.macos_compact COMMAND spud.macos_compact) - if(ARCH STREQUAL "x86_64") - add_executable(spud.macos_handler_backedge - tests/detour/audit/macos_unwind.cc) - target_compile_definitions(spud.macos_handler_backedge PRIVATE - SPUD_UNWIND_HANDLER_BACKEDGE=1) - target_include_directories(spud.macos_handler_backedge PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_link_libraries(spud.macos_handler_backedge PRIVATE spud) - if(SPUD_AARCH64_SUPPORT) - target_link_libraries(spud.macos_handler_backedge PRIVATE capstone) - endif() - add_test(NAME spud.macos_handler_backedge - COMMAND spud.macos_handler_backedge) - endif() - endif() - - # SPUD_AARCH64_SUPPORT is private to the library, but these programs - # include src/ headers whose layouts depend on it. - if(SPUD_AARCH64_SUPPORT) - foreach(_target spud.test spud.window_allocations spud.relocation_probe - spud.spill_unwind spud.windows_unwind spud.macos_unwind - spud.macos_unwind_fde spud.macos_compact - spud.macos_handler_backedge) - if(TARGET ${_target}) - target_compile_definitions(${_target} PRIVATE SPUD_AARCH64_SUPPORT=1) - endif() - endforeach() - endif() - - if(MSVC) - set(_spud_syntax_only /nologo /std:c++20 /Zs) - set(_spud_header_warnings "") - set(_spud_include_flag /I) - set(_spud_define_flag /D) - else() - set(_spud_syntax_only -std=c++20 -fsyntax-only) - # Consumers may build with -Wundef; the headers test macros with - # defined() where arch.h only defines them when true. - set(_spud_header_warnings -Wall -Wextra -Wundef -Werror) - set(_spud_include_flag -I) - set(_spud_define_flag -D) - endif() - - add_test( - NAME spud.tracing_header - COMMAND - ${CMAKE_CXX_COMPILER} ${_spud_syntax_only} - "${_spud_define_flag}SPUD_DETOUR_TRACING=1" - "${_spud_include_flag}${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/tests/install/tracing_consumer.cc" - ) - add_test( - NAME spud.tracing_header_order - COMMAND - ${CMAKE_CXX_COMPILER} ${_spud_syntax_only} - "${_spud_define_flag}SPUD_DETOUR_TRACING=1" - "${_spud_include_flag}${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/tests/install/tracing_consumer_order.cc" - ) - - add_test( - NAME spud.signature_literal - COMMAND - ${CMAKE_CXX_COMPILER} ${_spud_syntax_only} - "${_spud_include_flag}${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/tests/install/signature_literal.cc" - ) - add_test( - NAME spud.signature_literal_rejects - COMMAND - ${CMAKE_CXX_COMPILER} ${_spud_syntax_only} - "${_spud_define_flag}SPUD_BAD_PATTERN=1" - "${_spud_include_flag}${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/tests/install/signature_literal.cc" - ) - # Rejected for the right reason: sig() names the bad token in its error. -set_tests_properties(spud.signature_literal_rejects PROPERTIES - PASS_REGULAR_EXPRESSION "signature_has_an_invalid_token") - - if(SPUD_INSTALL) - set(_spud_install_check "${CMAKE_CURRENT_BINARY_DIR}/install-check") - add_test( - NAME spud.install - COMMAND - ${CMAKE_COMMAND} --install ${CMAKE_CURRENT_BINARY_DIR} --prefix - ${_spud_install_check} - ) - add_test( - NAME spud.installed_header - COMMAND - ${CMAKE_CXX_COMPILER} ${_spud_syntax_only} ${_spud_header_warnings} - "${_spud_include_flag}${_spud_install_check}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/tests/install/consumer.cc" - ) - add_test( - NAME spud.installed_tracing_header - COMMAND - ${CMAKE_CXX_COMPILER} ${_spud_syntax_only} - "${_spud_define_flag}SPUD_DETOUR_TRACING=1" - "${_spud_include_flag}${_spud_install_check}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/tests/install/tracing_consumer.cc" - ) - set_tests_properties( - spud.installed_header spud.installed_tracing_header - PROPERTIES DEPENDS spud.install - ) - add_test( - NAME spud.installed_link - COMMAND - ${CMAKE_COMMAND} - -DCMAKE_COMMAND=${CMAKE_COMMAND} - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} - -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM} - "-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}" - -DSPUD_PREFIX=${_spud_install_check} - -DCONSUMER_SRC=${CMAKE_CURRENT_SOURCE_DIR}/tests/install/link_consumer - -DCONSUMER_BIN=${CMAKE_CURRENT_BINARY_DIR}/link-consumer-build - -DBUILD_TYPE=$ - -DGENERATOR=${CMAKE_GENERATOR} - -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/install/run_link_consumer.cmake - ) - set_tests_properties( - spud.installed_link - PROPERTIES DEPENDS spud.install - ) - endif() - - # A consumer built with the other SPUD_DETOUR_TRACING setting must fail - # to link against this libspud, on the handle types the setting moves - # into an inline namespace, rather than run with the wrong layout. - if(NOT MSVC) - if(SPUD_DETOUR_TRACING) - set(_spud_other_tracing 0) - else() - set(_spud_other_tracing 1) - endif() - set(_spud_mismatch_libs $ $ $) - if(NOT APPLE) - list(APPEND _spud_mismatch_libs -pthread) - endif() - add_test( - NAME spud.tracing_mismatch - COMMAND - ${CMAKE_CXX_COMPILER} -std=c++20 - -DSPUD_DETOUR_TRACING=${_spud_other_tracing} - "-I${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/tests/install/link_consumer/main.cc" - ${_spud_mismatch_libs} - -o "${CMAKE_CURRENT_BINARY_DIR}/tracing-mismatch" - ) - # GNU ld and lld print demangled names, ld64 may print mangled ones. - set_tests_properties(spud.tracing_mismatch PROPERTIES - PASS_REGULAR_EXPRESSION "detail::(tracing::)?detour::|detail(7tracing)?6detour") - endif() -endif() - -if(SPUD_BUILD_EXAMPLES) - add_subdirectory(examples) -endif() diff --git a/xmake-packages/packages/s/spud/spud-src/cmake/generated/deps.cmake b/xmake-packages/packages/s/spud/spud-src/cmake/generated/deps.cmake deleted file mode 100644 index a19573929..000000000 --- a/xmake-packages/packages/s/spud/spud-src/cmake/generated/deps.cmake +++ /dev/null @@ -1,74 +0,0 @@ -# GENERATED by `zig build gen-cmake` — do not edit. -# Source of truth: cmake/spud.manifest.json - -set(SPUD_VENDOR_DIR "${CMAKE_CURRENT_LIST_DIR}/../../vendor") -set(SPUD_DEP_ZYDIS_URL "https://github.com/zyantific/zydis/archive/refs/tags/v4.1.0.tar.gz") -set(SPUD_DEP_ZYDIS_SHA256 "31f23de8abb4cc2efa0fd0e827bbabcaa0f3d00fcaed8598e05295ba7b3806ad") -set(SPUD_DEP_ZYDIS_VENDOR_DIR "zydis") -set(SPUD_DEP_ZYCORE_URL "https://github.com/zyantific/zycore-c/archive/74620eefd233bec20daeb66e78e744ff06e273b7.tar.gz") -set(SPUD_DEP_ZYCORE_SHA256 "51717e66bc94966ecc8ae415b2d90aae5e624d8da9198332a1e81aa898f82a55") -set(SPUD_DEP_ZYCORE_VENDOR_DIR "zycore") -set(SPUD_DEP_CAPSTONE_URL "https://github.com/capstone-engine/capstone/archive/refs/tags/6.0.0-Alpha5.tar.gz") -set(SPUD_DEP_CAPSTONE_SHA256 "a909a0ea9cd9da5a55fb498b4bd54507469dafe80eadc2e1928c80c8773ed7c5") -set(SPUD_DEP_CAPSTONE_VENDOR_DIR "capstone") -set(SPUD_DEP_CATCH2_URL "https://github.com/catchorg/Catch2/archive/refs/tags/v3.8.0.tar.gz") -set(SPUD_DEP_CATCH2_SHA256 "1ab2de20460d4641553addfdfe6acd4109d871d5531f8f519a52ea4926303087") -set(SPUD_DEP_CATCH2_VENDOR_DIR "catch2") - -# Source tree for a pinned dep: vendor/ when scripts/fetch_vendor.sh has -# run, otherwise the same tarball, hash-checked, through FetchContent. -# SOURCE_SUBDIR points nowhere so FetchContent only unpacks; the caller -# adds the tree with its own options. -function(spud_dep_source_dir name out) - string(TOUPPER "${name}" upper) - set(vendor "${SPUD_VENDOR_DIR}/${SPUD_DEP_${upper}_VENDOR_DIR}") - if(EXISTS "${vendor}/CMakeLists.txt") - set(${out} "${vendor}" PARENT_SCOPE) - return() - endif() - FetchContent_Declare( - spud_${name} - URL "${SPUD_DEP_${upper}_URL}" - URL_HASH "SHA256=${SPUD_DEP_${upper}_SHA256}" - SOURCE_SUBDIR "spud-populate-only" - ) - FetchContent_MakeAvailable(spud_${name}) - set(${out} "${spud_${name}_SOURCE_DIR}" PARENT_SCOPE) -endfunction() - -macro(spud_provide_zydis) - if(NOT TARGET Zydis) - spud_dep_source_dir(zycore _spud_zycore_dir) - spud_dep_source_dir(zydis _spud_zydis_dir) - option(ZYDIS_BUILD_TOOLS "" OFF) - option(ZYDIS_BUILD_EXAMPLES "" OFF) - set(ZYAN_ZYCORE_PATH "${_spud_zycore_dir}" CACHE PATH "The path to look for Zycore" FORCE) - add_subdirectory("${_spud_zydis_dir}" zydis EXCLUDE_FROM_ALL) - endif() -endmacro() - -# Capstone links in as an OBJECT library, so its objects take the MSVC -# runtime of the parent build. CAPSTONE_BUILD_STATIC_MSVC_RUNTIME would -# force /MT and break /MD consumers. -macro(spud_provide_capstone) - if(SPUD_AARCH64_SUPPORT AND NOT TARGET capstone) - spud_dep_source_dir(capstone _spud_capstone_dir) - set(CAPSTONE_BUILD_STATIC_LIBS ON) - set(CAPSTONE_BUILD_SHARED_LIBS OFF) - set(CAPSTONE_BUILD_STATIC_MSVC_RUNTIME OFF) - set(CAPSTONE_BUILD_MACOS_THIN ON) - set(CAPSTONE_ARCHITECTURE_DEFAULT OFF) - set(CAPSTONE_AARCH64_SUPPORT ON) - add_subdirectory("${_spud_capstone_dir}" capstone EXCLUDE_FROM_ALL) - endif() -endmacro() - -# Catch2 is about a hundred small sources that each parse the same -# headers; as one unity source it builds roughly ten times cheaper. -macro(spud_provide_catch2) - if(NOT TARGET Catch2) - spud_dep_source_dir(catch2 _spud_catch2_dir) - add_subdirectory("${_spud_catch2_dir}" catch2 EXCLUDE_FROM_ALL) - set_target_properties(Catch2 PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 0) - endif() -endmacro() diff --git a/xmake-packages/packages/s/spud/spud-src/cmake/generated/options.cmake b/xmake-packages/packages/s/spud/spud-src/cmake/generated/options.cmake deleted file mode 100644 index a250c65d8..000000000 --- a/xmake-packages/packages/s/spud/spud-src/cmake/generated/options.cmake +++ /dev/null @@ -1,8 +0,0 @@ -# GENERATED by `zig build gen-cmake` — do not edit. -# Source of truth: cmake/spud.manifest.json - -option(SPUD_UNWIND_SUPPORT "Describe generated code for stack walks and exception handling" ON) -option(SPUD_AARCH64_SUPPORT "Build the ARM64 relocation backend (Capstone)" ${SPUD_AARCH64_DEFAULT}) -option(SPUD_DETOUR_TRACING "Embed source locations in installed hooks" OFF) -option(SPUD_INSTALL "Generate install rules" ${PROJECT_IS_TOP_LEVEL}) -option(SPUD_WARNINGS_AS_ERRORS "Treat warnings in spud's own targets as errors (CI)" OFF) diff --git a/xmake-packages/packages/s/spud/spud-src/cmake/generated/sources.cmake b/xmake-packages/packages/s/spud/spud-src/cmake/generated/sources.cmake deleted file mode 100644 index 1dd307421..000000000 --- a/xmake-packages/packages/s/spud/spud-src/cmake/generated/sources.cmake +++ /dev/null @@ -1,68 +0,0 @@ -# GENERATED by `zig build gen-cmake` — do not edit. -# Source of truth: cmake/spud.manifest.json - -set(SPUD_PUBLIC_HDRS - "include/spud/arch.h" - "include/spud/detour.h" - "include/spud/diagnostics.h" - "include/spud/error.h" - "include/spud/utils.h" - "include/spud/signature.h" - "include/spud/pointer.h" - "include/spud/memory.h" - "include/spud/memory/protection.h" -) - -set(SPUD_COMMON_SRCS - "src/utils.cc" - "src/detour/x86_64/x86_64.cc" - "src/detour/x86_64/x86_64.h" - "src/detour/chain.cc" - "src/detour/chain.h" - "src/detour/control_flow.cc" - "src/detour/control_flow.h" - "src/detour/import.cc" - "src/detour/pointer.cc" - "src/detour/detour.cc" - "src/detour/detour_impl.h" - "src/detour/detour_stub.h" - "src/detour/fwd.h" - "src/memory/protection.cc" - "src/memory/safe_patch.cc" - "src/memory/safe_patch.h" - "src/memory/executable_pool.cc" - "src/memory/executable_pool.h" - "src/memory/unwind.cc" - "src/memory/unwind.h" - "src/memory/unwind/apple.cc" - "src/memory/unwind/compact.cc" - "src/memory/unwind/dwarf.cc" - "src/memory/unwind/dwarf.h" - "src/memory/unwind/linux.cc" - "src/memory/unwind/windows.cc" - "src/memory/unwind/windows.h" - "src/memory/unwind/windows_handler.cc" - "src/signature/signature.cc" - "src/signature/scan.h" -) - -set(SPUD_AARCH64_BACKEND_SRCS - "src/detour/aarch64/aarch64.cc" - "src/detour/aarch64/aarch64.h" -) - -set(SPUD_ASM_X86_64_MASM - "src/detour/x86_64/detour_context_support.masm" -) - -set(SPUD_SIMD_SSE_SRCS - "src/signature/signature_sse.cc" -) - -set(SPUD_SIMD_AVX2_SRCS - "src/signature/signature_avx2.cc" -) - -set(SPUD_SIMD_NEON_SRCS - "src/signature/signature_neon.cc" -) diff --git a/xmake-packages/packages/s/spud/spud-src/cmake/spud.manifest.json b/xmake-packages/packages/s/spud/spud-src/cmake/spud.manifest.json deleted file mode 100644 index 1a2663c4f..000000000 --- a/xmake-packages/packages/s/spud/spud-src/cmake/spud.manifest.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "name": "spud", - "version": "0.1.0", - "cxx_standard": 20, - "unsupported": [ - "32-bit x86", - "Windows ARM64", - "ARM32", - "MIPS", - "PowerPC", - "universal macOS binaries" - ], - "options": { - "SPUD_UNWIND_SUPPORT": { - "help": "Describe generated code for stack walks and exception handling", - "default": true, - "define": "SPUD_UNWIND_SUPPORT" - }, - "SPUD_AARCH64_SUPPORT": { - "help": "Build the ARM64 relocation backend (Capstone)", - "default": "SPUD_AARCH64_DEFAULT", - "define": "SPUD_AARCH64_SUPPORT" - }, - "SPUD_DETOUR_TRACING": { - "help": "Embed source locations in installed hooks", - "default": false, - "define": "SPUD_DETOUR_TRACING" - }, - "SPUD_INSTALL": { - "help": "Generate install rules", - "default": "PROJECT_IS_TOP_LEVEL" - }, - "SPUD_WARNINGS_AS_ERRORS": { - "help": "Treat warnings in spud's own targets as errors (CI)", - "default": false - } - }, - "public_headers": [ - "include/spud/arch.h", - "include/spud/detour.h", - "include/spud/diagnostics.h", - "include/spud/error.h", - "include/spud/utils.h", - "include/spud/signature.h", - "include/spud/pointer.h", - "include/spud/memory.h", - "include/spud/memory/protection.h" - ], - "sources": { - "common": [ - "src/utils.cc", - "src/detour/x86_64/x86_64.cc", - "src/detour/x86_64/x86_64.h", - "src/detour/chain.cc", - "src/detour/chain.h", - "src/detour/control_flow.cc", - "src/detour/control_flow.h", - "src/detour/import.cc", - "src/detour/pointer.cc", - "src/detour/detour.cc", - "src/detour/detour_impl.h", - "src/detour/detour_stub.h", - "src/detour/fwd.h", - "src/memory/protection.cc", - "src/memory/safe_patch.cc", - "src/memory/safe_patch.h", - "src/memory/executable_pool.cc", - "src/memory/executable_pool.h", - "src/memory/unwind.cc", - "src/memory/unwind.h", - "src/memory/unwind/apple.cc", - "src/memory/unwind/compact.cc", - "src/memory/unwind/dwarf.cc", - "src/memory/unwind/dwarf.h", - "src/memory/unwind/linux.cc", - "src/memory/unwind/windows.cc", - "src/memory/unwind/windows.h", - "src/memory/unwind/windows_handler.cc", - "src/signature/signature.cc", - "src/signature/scan.h" - ], - "aarch64_backend": [ - "src/detour/aarch64/aarch64.cc", - "src/detour/aarch64/aarch64.h" - ], - "asm": { - "x86_64_masm": [ - "src/detour/x86_64/detour_context_support.masm" - ] - }, - "simd": { - "sse": [ - "src/signature/signature_sse.cc" - ], - "avx2": [ - "src/signature/signature_avx2.cc" - ], - "neon": [ - "src/signature/signature_neon.cc" - ] - } - }, - "deps": { - "zydis": { - "url": "https://github.com/zyantific/zydis/archive/refs/tags/v4.1.0.tar.gz", - "sha256": "31f23de8abb4cc2efa0fd0e827bbabcaa0f3d00fcaed8598e05295ba7b3806ad", - "strip": 1, - "vendor_dir": "zydis", - "cmake_target": "Zydis", - "defines": [ - "ZYDIS_STATIC_BUILD", - "ZYCORE_STATIC_BUILD", - "ZYAN_STATIC_BUILD" - ] - }, - "zycore": { - "url": "https://github.com/zyantific/zycore-c/archive/74620eefd233bec20daeb66e78e744ff06e273b7.tar.gz", - "sha256": "51717e66bc94966ecc8ae415b2d90aae5e624d8da9198332a1e81aa898f82a55", - "strip": 1, - "vendor_dir": "zycore", - "cmake_target": "Zycore", - "defines": [ - "ZYCORE_STATIC_BUILD", - "ZYAN_STATIC_BUILD" - ] - }, - "capstone": { - "url": "https://github.com/capstone-engine/capstone/archive/refs/tags/6.0.0-Alpha5.tar.gz", - "sha256": "a909a0ea9cd9da5a55fb498b4bd54507469dafe80eadc2e1928c80c8773ed7c5", - "strip": 1, - "vendor_dir": "capstone", - "optional": "SPUD_AARCH64_SUPPORT", - "cmake_target": "capstone", - "defines": [ - "CAPSTONE_USE_SYS_DYN_MEM", - "CAPSTONE_HAS_AARCH64" - ] - }, - "catch2": { - "url": "https://github.com/catchorg/Catch2/archive/refs/tags/v3.8.0.tar.gz", - "sha256": "1ab2de20460d4641553addfdfe6acd4109d871d5531f8f519a52ea4926303087", - "strip": 1, - "vendor_dir": "catch2", - "tests_only": true, - "cmake_target": "Catch2" - } - } -} diff --git a/xmake-packages/packages/s/spud/spud-src/cmake/spudConfig.cmake.in b/xmake-packages/packages/s/spud/spud-src/cmake/spudConfig.cmake.in deleted file mode 100644 index d79899e3b..000000000 --- a/xmake-packages/packages/s/spud/spud-src/cmake/spudConfig.cmake.in +++ /dev/null @@ -1,40 +0,0 @@ -@PACKAGE_INIT@ - -include(CMakeFindDependencyMacro) -find_dependency(Threads) - -set_and_check(SPUD_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") -set_and_check(SPUD_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@") - -if(NOT TARGET spud::spud) - add_library(spud::spud STATIC IMPORTED) - set(_spud_location - "${SPUD_LIB_DIR}/@SPUD_STATIC_LIB_FILENAME@") - set(_spud_link - "${SPUD_LIB_DIR}/@SPUD_ZYDIS_FILENAME@" - "${SPUD_LIB_DIR}/@SPUD_ZYCORE_FILENAME@" - Threads::Threads) - if(WIN32) - list(APPEND _spud_link psapi) - endif() - set_target_properties( - spud::spud - PROPERTIES - IMPORTED_LOCATION "${_spud_location}" - INTERFACE_INCLUDE_DIRECTORIES "${SPUD_INCLUDE_DIR}" - INTERFACE_COMPILE_FEATURES "cxx_std_20" - INTERFACE_COMPILE_DEFINITIONS - "SPUD_DETOUR_TRACING=@SPUD_DETOUR_TRACING_VALUE@;SPUD_UNWIND_SUPPORT=@SPUD_UNWIND_SUPPORT_VALUE@" - INTERFACE_LINK_LIBRARIES "${_spud_link}" - ) - # Mirrors the PUBLIC option in CMakeLists.txt: the Windows headers need MS - # extensions under GNU-style Clang. - if(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC) - set_property(TARGET spud::spud PROPERTY INTERFACE_COMPILE_OPTIONS - "$<$:-fms-extensions>") - endif() - unset(_spud_location) - unset(_spud_link) -endif() - -check_required_components(spud) diff --git a/zig/ctx.zig b/zig/ctx.zig new file mode 100644 index 000000000..1eb14e454 --- /dev/null +++ b/zig/ctx.zig @@ -0,0 +1,281 @@ +//! Per-target compile rules shared by every library and executable in the build. +//! `Ctx` turns project options and a located sysroot into modules and flags; `Lib` carries what a consumer needs +//! to compile against and link one library. +const std = @import("std"); +const Build = std.Build; +const toolchains = @import("toolchains.zig"); + +/// Project options that apply to every target. Options that configure a single step stay with that step. +pub const Options = struct { + /// null keeps the per-target default: on for Windows release builds, off elsewhere. + lto: ?bool, + moddbg: bool, + use_original_bg: bool, + bg_image: []const u8, + msvc_sysroot: ?[]const u8, + macos_sdk: ?[]const u8, + + /// Declare the shared options. Call once from `build`. + pub fn parse(b: *Build) Options { + const bg_image = b.option([]const u8, "bg_image", "Custom loading screen image") orelse ""; + return .{ + .lto = b.option(bool, "lto", "Enable LTO (Windows release default; unsupported for macOS in Zig 0.16)"), + .moddbg = b.option(bool, "moddbg", "Enable diagnostic patch toggles (_MODDBG)") orelse false, + .use_original_bg = b.option( + bool, + "use_original_bg", + "Use the original game loading background", + ) orelse false, + .bg_image = if (bg_image.len == 0) "assets/loadingscreen.png" else bg_image, + .msvc_sysroot = b.option([]const u8, "msvc-sysroot", "Path to an extracted MSVC + Windows SDK toolchain"), + .macos_sdk = b.option([]const u8, "macos-sdk", "Path to a MacOSX.sdk directory"), + }; + } +}; + +/// One target's build settings. Every module and compile step in the graph goes through this. +pub const Ctx = struct { + b: *Build, + target: Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, + options: Options, + lto: bool, + sysroot: toolchains.Sysroot, + + /// Resolve LTO and locate the platform SDK. Linux targets only build native fixtures and need no sysroot. + pub fn init( + b: *Build, + target: Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, + options: Options, + ) *const Ctx { + const os = target.result.os.tag; + const lto = options.lto orelse (os == .windows and optimize != .Debug); + if (lto and os == .macos) + std.debug.panic("Zig 0.16 does not support Mach-O LTO; use -Dlto=false for macOS", .{}); + const ctx = b.allocator.create(Ctx) catch @panic("OOM"); + ctx.* = .{ + .b = b, + .target = target, + .optimize = optimize, + .options = options, + .lto = lto, + .sysroot = if (os == .windows or os == .macos) toolchains.find(b, target, options) else .{}, + }; + return ctx; + } + + pub fn isWindows(ctx: *const Ctx) bool { + return ctx.target.result.os.tag == .windows; + } + + pub fn isMacos(ctx: *const Ctx) bool { + return ctx.target.result.os.tag == .macos; + } + + pub fn isAarch64(ctx: *const Ctx) bool { + return ctx.target.result.cpu.arch == .aarch64; + } + + /// A C or C++ module for this target with the sysroot attached. C++ uses libc++ everywhere except Windows, + /// which links the static MSVC STL and CRT from the sysroot. + pub fn createModule(ctx: *const Ctx, cpp: bool) *Build.Module { + const b = ctx.b; + const module = b.createModule(.{ + .target = ctx.target, + .optimize = ctx.optimize, + .link_libc = true, + .link_libcpp = if (cpp and !ctx.isWindows()) true else null, + .pic = true, + // Zig turns UBSan on in Debug. The xmake build never had it, and a trap inside a game detour takes the + // client down. + .sanitize_c = .off, + }); + + if (ctx.isWindows()) { + if (ctx.sysroot.msvc_root) |root| { + inline for (.{ "um", "shared", "winrt", "cppwinrt" }) |dir| + module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ root, "winsdk/include", dir }) }); + inline for (.{ "winsdk/lib/um/x64", "winsdk/lib/ucrt/x64", "msvc/lib/x64" }) |dir| + module.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ root, dir }) }); + } else { + // No cached SDK on a Windows host: a Visual Studio developer shell supplies the paths, including + // C++/WinRT, which Zig's own MSVC detection leaves out. + const env = &b.graph.environ_map; + if (env.get("INCLUDE")) |includes| { + var it = std.mem.splitScalar(u8, includes, ';'); + while (it.next()) |dir| if (dir.len != 0) module.addSystemIncludePath(.{ .cwd_relative = dir }); + if (env.get("LIB")) |libs| { + var lib_it = std.mem.splitScalar(u8, libs, ';'); + while (lib_it.next()) |dir| if (dir.len != 0) module.addLibraryPath(.{ .cwd_relative = dir }); + } + } + } + inline for (.{ "libcmt", "libcpmt", "libucrt", "libvcruntime" }) |lib| + module.linkSystemLibrary(lib, .{}); + } else if (ctx.sysroot.macos_sdk) |sdk| { + module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "usr/include" }) }); + module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "System/Library/Frameworks" }) }); + module.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "usr/lib" }) }); + } + return module; + } + + /// Apply the libc file and LTO. Every library and executable built for the target goes through here. + pub fn applyCompile(ctx: *const Ctx, compile: *Build.Step.Compile) void { + if (ctx.sysroot.msvc_libc_file) |libc| compile.setLibCFile(libc); + if (ctx.lto) { + compile.lto = .full; + compile.use_lld = true; + } + } + + pub fn staticLib(ctx: *const Ctx, name: []const u8, module: *Build.Module) *Build.Step.Compile { + const lib = ctx.b.addLibrary(.{ .name = name, .linkage = .static, .root_module = module }); + ctx.applyCompile(lib); + return lib; + } + + pub fn executable(ctx: *const Ctx, name: []const u8, module: *Build.Module) *Build.Step.Compile { + const exe = ctx.b.addExecutable(.{ .name = name, .root_module = module }); + ctx.applyCompile(exe); + return exe; + } + + /// An owned copy of `list`. `Lib` fields outlive the caller's stack, so literal slices must be copied. + pub fn dirs(ctx: *const Ctx, list: []const Build.LazyPath) []const Build.LazyPath { + return ctx.b.allocator.dupe(Build.LazyPath, list) catch @panic("OOM"); + } + + /// Compile `files` as one translation unit of `#include`s, so headers they share are parsed once. Only use it + /// for sources that tolerate each other's macros and statics. + pub fn addCxxBatch( + ctx: *const Ctx, + module: *Build.Module, + name: []const u8, + root: Build.LazyPath, + files: []const []const u8, + flags: []const []const u8, + ) void { + const b = ctx.b; + var contents: std.Io.Writer.Allocating = .init(b.allocator); + const generated = b.addWriteFiles(); + for (files, 0..) |file, index| { + // Changing an included source must also change the generated batch's cache key. + _ = generated.addCopyFile(root.path(b, file), b.fmt("inputs/{d}.cc", .{index})); + const path = b.pathJoin(&.{ root.getPath(b), file }); + std.mem.replaceScalar(u8, path, '\\', '/'); + const quoted = std.json.Stringify.valueAlloc(b.allocator, path, .{}) catch @panic("OOM"); + contents.writer.print("#include {s}\n", .{quoted}) catch @panic("OOM"); + } + const source = generated.add(b.fmt("{s}-sources.cc", .{name}), contents.written()); + module.addCSourceFile(.{ .file = source, .flags = flags }); + } + + /// C flags for this target, then `extra`. + pub fn cFlags(ctx: *const Ctx, extra: []const []const u8) []const []const u8 { + var list: std.ArrayList([]const u8) = .empty; + if (ctx.isWindows()) list.append(ctx.b.allocator, "-fms-runtime-lib=static") catch @panic("OOM"); + list.appendSlice(ctx.b.allocator, extra) catch @panic("OOM"); + return list.items; + } + + /// C++ flags at `std_ver` with exceptions enabled, then `extra`. + pub fn cxxFlags(ctx: *const Ctx, comptime std_ver: []const u8, extra: []const []const u8) []const []const u8 { + var list: std.ArrayList([]const u8) = .empty; + const base: []const []const u8 = &.{ "-std=" ++ std_ver, "-fexceptions", "-fcxx-exceptions" }; + list.appendSlice(ctx.b.allocator, base) catch @panic("OOM"); + // Zig passes -nostdinc++ when it uses the MSVC STL. Clang's MSVC driver reports it unused, and Zig turns + // that warning into an error. + if (ctx.isWindows()) list.appendSlice(ctx.b.allocator, &.{ + "-DNOMINMAX", + "-fms-runtime-lib=static", + "-Wno-unused-command-line-argument", + }) catch @panic("OOM"); + list.appendSlice(ctx.b.allocator, extra) catch @panic("OOM"); + return list.items; + } +}; + +/// A compiled or header-only library, as its consumers see it. +pub const Lib = struct { + artifact: ?*Build.Step.Compile = null, + /// Libraries this one links against. Consumers link them too, instead of this artifact linking them, so + /// independent static libraries compile in parallel. + dependencies: []const Lib = &.{}, + system_libs: []const []const u8 = &.{}, + include_dirs: []const Build.LazyPath = &.{}, + /// Preprocessor defines consumers must match, such as SPDLOG_COMPILED_LIB. + defines: []const [2][]const u8 = &.{}, + /// Import library folders the library's headers ask the linker for, such as GameAssembly.lib. + lib_dirs: []const Build.LazyPath = &.{}, + + /// Compile against this library's headers without linking it. Static libraries use this so they never wait + /// for each other; the final binary links everything. + pub fn includeInto(lib: Lib, module: *Build.Module) void { + for (lib.include_dirs) |dir| module.addIncludePath(dir); + for (lib.defines) |d| module.addCMacro(d[0], d[1]); + for (lib.lib_dirs) |dir| module.addLibraryPath(dir); + } + + /// Compile against the headers and link the library with its dependencies. + pub fn linkInto(lib: Lib, module: *Build.Module) void { + lib.includeInto(module); + if (lib.artifact) |artifact| module.linkLibrary(artifact); + for (lib.dependencies) |dependency| dependency.linkInto(module); + for (lib.system_libs) |name| module.linkSystemLibrary(name, .{}); + } + + /// Make `step` build this library and its whole dependency closure. + pub fn addBuildDependencies(lib: Lib, step: *Build.Step) void { + if (lib.artifact) |artifact| step.dependOn(&artifact.step); + for (lib.dependencies) |dependency| dependency.addBuildDependencies(step); + } + + /// A named step that installs this library and builds its dependencies, for checking one library alone. + pub fn addInstallStep(lib: Lib, b: *Build, name: []const u8, description: []const u8) *Build.Step { + const step = b.step(name, description); + step.dependOn(&b.addInstallArtifact(lib.artifact.?, .{}).step); + lib.addBuildDependencies(step); + return step; + } +}; + +/// Files under `root/sub_path` ending in one of `exts`, sorted, relative to `root` and with forward slashes. +/// A file is skipped when its path contains any of the `exclude` substrings. +pub fn globFiles( + b: *Build, + root: Build.LazyPath, + sub_path: []const u8, + exts: []const []const u8, + exclude: []const []const u8, +) []const []const u8 { + const io = b.graph.io; + const root_path = root.getPath3(b, null); + var dir = root_path.root_dir.handle.openDir(io, b.pathJoin(&.{ root_path.sub_path, sub_path }), .{ + .iterate = true, + }) catch |err| std.debug.panic("unable to open {s}/{s}: {t}", .{ root_path.sub_path, sub_path, err }); + defer dir.close(io); + var walker = dir.walk(b.allocator) catch @panic("OOM"); + defer walker.deinit(); + + var out: std.ArrayList([]const u8) = .empty; + next: while (walker.next(io) catch |err| std.debug.panic("walk failed: {t}", .{err})) |entry| { + if (entry.kind != .file) continue; + const ext = std.fs.path.extension(entry.basename); + for (exts) |want| { + if (std.mem.eql(u8, ext, want)) break; + } else continue; + const rel = b.pathJoin(&.{ sub_path, entry.path }); + // Windows hosts join with backslashes; exclusions and callers expect logical paths. + std.mem.replaceScalar(u8, rel, '\\', '/'); + for (exclude) |skip| if (std.mem.indexOf(u8, rel, skip) != null) continue :next; + out.append(b.allocator, rel) catch @panic("OOM"); + } + std.mem.sort([]const u8, out.items, {}, struct { + fn lessThan(_: void, lhs: []const u8, rhs: []const u8) bool { + return std.mem.lessThan(u8, lhs, rhs); + } + }.lessThan); + return out.items; +} diff --git a/zig/deps.zig b/zig/deps.zig new file mode 100644 index 000000000..1181fe53b --- /dev/null +++ b/zig/deps.zig @@ -0,0 +1,244 @@ +//! Third-party C and C++ libraries other than protobuf, compiled from the pins in build.zig.zon. +//! Source lists are explicit where upstream ships platform files or tools we must not compile. +const std = @import("std"); +const Ctx = @import("ctx.zig").Ctx; +const Lib = @import("ctx.zig").Lib; +const globFiles = @import("ctx.zig").globFiles; + +// --- Logging, settings, JSON, INI ----------------------------------------------------------------------------- + +/// spdlog with its bundled fmt, compiled once instead of header-only in every consumer. +pub fn spdlog(ctx: *const Ctx) Lib { + const b = ctx.b; + const src = b.dependency("spdlog", .{}).path(""); + const module = ctx.createModule(true); + module.addIncludePath(src.path(b, "include")); + module.addCMacro("SPDLOG_COMPILED_LIB", "1"); + module.addCSourceFiles(.{ + .root = src, + .files = &.{ + "src/spdlog.cpp", + "src/stdout_sinks.cpp", + "src/color_sinks.cpp", + "src/file_sinks.cpp", + "src/async.cpp", + "src/cfg.cpp", + "src/bundled_fmtlib_format.cpp", + }, + .flags = ctx.cxxFlags("c++20", &.{}), + }); + return .{ + .artifact = ctx.staticLib("spdlog", module), + .include_dirs = ctx.dirs(&.{src.path(b, "include")}), + .defines = &.{.{ "SPDLOG_COMPILED_LIB", "1" }}, + }; +} + +/// toml++, header-only. +pub fn tomlplusplus(ctx: *const Ctx) Lib { + return .{ .include_dirs = ctx.dirs(&.{ctx.b.dependency("tomlplusplus", .{}).path("include")}) }; +} + +/// nlohmann/json, header-only. +pub fn nlohmannJson(ctx: *const Ctx) Lib { + return .{ .include_dirs = ctx.dirs(&.{ctx.b.dependency("nlohmann_json", .{}).path("single_include")}) }; +} + +/// inifile-cpp, header-only. Only the macOS loader reads INI files. +pub fn inifileCpp(ctx: *const Ctx) Lib { + return .{ .include_dirs = ctx.dirs(&.{ctx.b.dependency("inifile_cpp", .{}).path("include")}) }; +} + +// --- Detours --------------------------------------------------------------------------------------------------- + +/// Zydis and Zycore, SPUD's x86 decoder. +pub fn zydis(ctx: *const Ctx) Lib { + const b = ctx.b; + const core = b.dependency("zycore", .{}).path(""); + const src = b.dependency("zydis", .{}).path(""); + const module = ctx.createModule(false); + module.addIncludePath(core.path(b, "include")); + module.addIncludePath(src.path(b, "include")); + module.addIncludePath(src.path(b, "src")); + module.addCMacro("ZYCORE_STATIC_BUILD", "1"); + module.addCMacro("ZYDIS_STATIC_BUILD", "1"); + // Native fixtures on Linux: glibc hides Zycore's recursive mutex attribute under strict C11. + if (ctx.target.result.os.tag == .linux) module.addCMacro("_GNU_SOURCE", "1"); + inline for (.{ core, src }) |root| module.addCSourceFiles(.{ + .root = root, + .files = globFiles(b, root, "src", &.{".c"}, &.{}), + .flags = ctx.cFlags(&.{"-std=c11"}), + }); + return .{ + .artifact = ctx.staticLib("zydis", module), + .include_dirs = ctx.dirs(&.{ core.path(b, "include"), src.path(b, "include") }), + .defines = &.{ .{ "ZYCORE_STATIC_BUILD", "1" }, .{ "ZYDIS_STATIC_BUILD", "1" } }, + }; +} + +/// Capstone's core and AArch64 decoder only, for SPUD's ARM64 relocator. +pub fn capstone(ctx: *const Ctx) Lib { + const b = ctx.b; + const src = b.dependency("capstone", .{}).path(""); + const module = ctx.createModule(false); + module.addIncludePath(src.path(b, "include")); + module.addIncludePath(src); + module.addCMacro("CAPSTONE_HAS_AARCH64", "1"); + module.addCMacro("CAPSTONE_USE_SYS_DYN_MEM", "1"); + module.addCSourceFiles(.{ + .root = src, + .files = &.{ + "cs.c", + "Mapping.c", + "MCInst.c", + "MCInstrDesc.c", + "MCInstPrinter.c", + "MCRegisterInfo.c", + "SStream.c", + "utils.c", + "arch/AArch64/AArch64BaseInfo.c", + "arch/AArch64/AArch64Disassembler.c", + "arch/AArch64/AArch64DisassemblerExtension.c", + "arch/AArch64/AArch64InstPrinter.c", + "arch/AArch64/AArch64Mapping.c", + "arch/AArch64/AArch64Module.c", + }, + .flags = ctx.cFlags(&.{"-std=c11"}), + }); + return .{ + .artifact = ctx.staticLib("capstone", module), + .include_dirs = ctx.dirs(&.{src.path(b, "include")}), + }; +} + +/// The vendored SPUD detour library. third_party/spud is SPUD's unmodified include/, src/ and LICENSE; the pinned +/// commit is in docs/THIRD_PARTY.md. +pub fn spud(ctx: *const Ctx, zy: Lib, cs: Lib) Lib { + const b = ctx.b; + const src = b.path("third_party/spud"); + const aarch64 = ctx.isAarch64(); + const module = ctx.createModule(true); + module.addIncludePath(src.path(b, "include")); + module.addIncludePath(src.path(b, "src")); + zy.linkInto(module); + // Only the ARM64 relocator uses Capstone. Like upstream, x86-64 builds leave both out. + if (aarch64) { + module.addCMacro("SPUD_AARCH64_SUPPORT", "1"); + cs.linkInto(module); + } + // Every SIMD kernel for the architecture is compiled. Each opts in per function with SPUD_TARGET and is picked + // at run time, so no translation unit raises the CPU baseline. + const skip: []const []const u8 = if (aarch64) + &.{ "_sse.cc", "_avx2.cc" } + else + &.{ "_neon.cc", "src/detour/aarch64" }; + module.addCSourceFiles(.{ + .root = src, + .files = globFiles(b, src, "src", &.{".cc"}, skip), + .flags = ctx.cxxFlags("c++23", &.{}), + }); + return .{ + .artifact = ctx.staticLib("spud", module), + .dependencies = b.allocator.dupe(Lib, if (aarch64) &.{ zy, cs } else &.{zy}) catch @panic("OOM"), + .include_dirs = ctx.dirs(&.{src.path(b, "include")}), + }; +} + +// --- Networking ------------------------------------------------------------------------------------------------ + +/// zlib, for libcurl on Windows. +pub fn zlib(ctx: *const Ctx) Lib { + const b = ctx.b; + const src = b.dependency("zlib", .{}).path(""); + const module = ctx.createModule(false); + module.addIncludePath(src); + if (!ctx.isWindows()) module.addCMacro("HAVE_UNISTD_H", "1"); + module.addCSourceFiles(.{ + .root = src, + .files = &.{ + "adler32.c", + "compress.c", + "crc32.c", + "deflate.c", + "gzclose.c", + "gzlib.c", + "gzread.c", + "gzwrite.c", + "inflate.c", + "infback.c", + "inftrees.c", + "inffast.c", + "trees.c", + "uncompr.c", + "zutil.c", + }, + .flags = ctx.cFlags(&.{"-std=c11"}), + }); + return .{ .artifact = ctx.staticLib("zlib", module), .include_dirs = ctx.dirs(&.{src}) }; +} + +/// libcurl. macOS links Apple's system copy. Windows compiles the pin with Schannel TLS and the unused protocols +/// off, so the DLL needs no OpenSSL. null until Zig has fetched the lazy dependency. +pub fn curl(ctx: *const Ctx, z: Lib) ?Lib { + const b = ctx.b; + // The SDK's curl headers match the system library, so CPR never picks newer APIs than Apple ships. + if (ctx.isMacos()) return .{ .system_libs = &.{"curl"} }; + + const src = (b.lazyDependency("curl", .{}) orelse return null).path(""); + const module = ctx.createModule(false); + module.addIncludePath(src.path(b, "include")); + module.addIncludePath(src.path(b, "lib")); + module.addCMacro("BUILDING_LIBCURL", "1"); + module.addCMacro("CURL_STATICLIB", "1"); + z.linkInto(module); + module.addCMacro("USE_SCHANNEL", "1"); + module.addCMacro("USE_WINDOWS_SSPI", "1"); + module.addCMacro("HAVE_LIBZ", "1"); + inline for (.{ + "FTP", "FILE", "LDAP", "LDAPS", "RTSP", "DICT", "TELNET", + "TFTP", "POP3", "IMAP", "SMB", "SMTP", "GOPHER", "MQTT", + }) |protocol| module.addCMacro("CURL_DISABLE_" ++ protocol, "1"); + inline for (.{ "ws2_32", "crypt32", "bcrypt", "secur32", "advapi32", "iphlpapi", "user32" }) |lib| + module.linkSystemLibrary(lib, .{}); + module.addCSourceFiles(.{ + .root = src, + .files = globFiles(b, src, "lib", &.{".c"}, &.{}), + .flags = ctx.cFlags(&.{"-std=c11"}), + }); + return .{ + .artifact = ctx.staticLib("curl", module), + .dependencies = b.allocator.dupe(Lib, &.{z}) catch @panic("OOM"), + .include_dirs = ctx.dirs(&.{src.path(b, "include")}), + .defines = &.{.{ "CURL_STATICLIB", "1" }}, + }; +} + +/// CPR, the C++ HTTP client over libcurl. +pub fn cpr(ctx: *const Ctx, curl_lib: Lib) Lib { + const b = ctx.b; + const src = b.dependency("cpr", .{}).path(""); + // CPR's CMake generates this header. Keep it in step with the cpr pin in build.zig.zon. + const version = b.addWriteFiles().add("cpr/cprver.h", + \\#pragma once + \\#define CPR_VERSION "1.14.2" + \\#define CPR_VERSION_MAJOR 1 + \\#define CPR_VERSION_MINOR 14 + \\#define CPR_VERSION_PATCH 2 + \\#define CPR_VERSION_NUM 0x010e02 + \\ + ); + const generated = version.dirname().dirname(); + const module = ctx.createModule(true); + module.addIncludePath(src.path(b, "include")); + module.addIncludePath(generated); + curl_lib.linkInto(module); + module.addCSourceFiles(.{ + .root = src, + .files = globFiles(b, src, "cpr", &.{".cpp"}, &.{}), + .flags = ctx.cxxFlags("c++17", &.{}), + }); + return .{ + .artifact = ctx.staticLib("cpr", module), + .include_dirs = ctx.dirs(&.{ src.path(b, "include"), generated }), + }; +} diff --git a/zig/deps/abseil_sources.zon b/zig/deps/abseil_sources.zon new file mode 100644 index 000000000..7928ecb35 --- /dev/null +++ b/zig/deps/abseil_sources.zon @@ -0,0 +1,145 @@ +// Transitive source closure of protobuf 35.1 protobuf_ABSL_USED_TARGETS, +// resolved from Abseil 20250512.1 absl_cc_library declarations. +.{ + "absl/base/internal/cycleclock.cc", + "absl/base/internal/low_level_alloc.cc", + "absl/base/internal/raw_logging.cc", + "absl/base/internal/spinlock.cc", + "absl/base/internal/spinlock_wait.cc", + "absl/base/internal/strerror.cc", + "absl/base/internal/sysinfo.cc", + "absl/base/internal/thread_identity.cc", + "absl/base/internal/throw_delegate.cc", + "absl/base/internal/tracing.cc", + "absl/base/internal/unscaledcycleclock.cc", + "absl/base/log_severity.cc", + "absl/container/internal/hashtablez_sampler.cc", + "absl/container/internal/hashtablez_sampler_force_weak_definition.cc", + "absl/container/internal/raw_hash_set.cc", + "absl/crc/crc32c.cc", + "absl/crc/internal/cpu_detect.cc", + "absl/crc/internal/crc.cc", + "absl/crc/internal/crc_cord_state.cc", + "absl/crc/internal/crc_memcpy_fallback.cc", + "absl/crc/internal/crc_memcpy_x86_arm_combined.cc", + "absl/crc/internal/crc_non_temporal_memcpy.cc", + "absl/crc/internal/crc_x86_arm_combined.cc", + "absl/debugging/internal/address_is_readable.cc", + "absl/debugging/internal/decode_rust_punycode.cc", + "absl/debugging/internal/demangle.cc", + "absl/debugging/internal/demangle_rust.cc", + "absl/debugging/internal/elf_mem_image.cc", + "absl/debugging/internal/examine_stack.cc", + "absl/debugging/internal/utf8_for_code_point.cc", + "absl/debugging/internal/vdso_support.cc", + "absl/debugging/leak_check.cc", + "absl/debugging/stacktrace.cc", + "absl/debugging/symbolize.cc", + "absl/flags/commandlineflag.cc", + "absl/flags/internal/commandlineflag.cc", + "absl/flags/internal/flag.cc", + "absl/flags/internal/private_handle_accessor.cc", + "absl/flags/internal/program_name.cc", + "absl/flags/marshalling.cc", + "absl/flags/reflection.cc", + "absl/flags/usage_config.cc", + "absl/hash/internal/city.cc", + "absl/hash/internal/hash.cc", + "absl/hash/internal/low_level_hash.cc", + "absl/log/die_if_null.cc", + "absl/log/globals.cc", + "absl/log/initialize.cc", + "absl/log/internal/check_op.cc", + "absl/log/internal/conditions.cc", + "absl/log/internal/fnmatch.cc", + "absl/log/internal/globals.cc", + "absl/log/internal/log_format.cc", + "absl/log/internal/log_message.cc", + "absl/log/internal/log_sink_set.cc", + "absl/log/internal/nullguard.cc", + "absl/log/internal/proto.cc", + "absl/log/internal/structured_proto.cc", + "absl/log/internal/vlog_config.cc", + "absl/log/log_sink.cc", + "absl/numeric/int128.cc", + "absl/profiling/internal/exponential_biased.cc", + "absl/random/discrete_distribution.cc", + "absl/random/gaussian_distribution.cc", + "absl/random/internal/entropy_pool.cc", + "absl/random/internal/randen.cc", + "absl/random/internal/randen_detect.cc", + "absl/random/internal/randen_hwaes.cc", + "absl/random/internal/randen_round_keys.cc", + "absl/random/internal/randen_slow.cc", + "absl/random/internal/seed_material.cc", + "absl/random/seed_gen_exception.cc", + "absl/random/seed_sequences.cc", + "absl/status/internal/status_internal.cc", + "absl/status/status.cc", + "absl/status/status_payload_printer.cc", + "absl/status/statusor.cc", + "absl/strings/ascii.cc", + "absl/strings/charconv.cc", + "absl/strings/cord.cc", + "absl/strings/cord_analysis.cc", + "absl/strings/escaping.cc", + "absl/strings/internal/escaping.cc", + "absl/strings/internal/charconv_bigint.cc", + "absl/strings/internal/charconv_parse.cc", + "absl/strings/internal/cord_internal.cc", + "absl/strings/internal/cord_rep_btree.cc", + "absl/strings/internal/cord_rep_btree_navigator.cc", + "absl/strings/internal/cord_rep_btree_reader.cc", + "absl/strings/internal/cord_rep_consume.cc", + "absl/strings/internal/cord_rep_crc.cc", + "absl/strings/internal/cordz_functions.cc", + "absl/strings/internal/cordz_handle.cc", + "absl/strings/internal/cordz_info.cc", + "absl/strings/internal/damerau_levenshtein_distance.cc", + "absl/strings/internal/memutil.cc", + "absl/strings/internal/ostringstream.cc", + "absl/strings/internal/str_format/arg.cc", + "absl/strings/internal/str_format/bind.cc", + "absl/strings/internal/str_format/extension.cc", + "absl/strings/internal/str_format/float_conversion.cc", + "absl/strings/internal/str_format/output.cc", + "absl/strings/internal/str_format/parser.cc", + "absl/strings/internal/stringify_sink.cc", + "absl/strings/internal/utf8.cc", + "absl/strings/match.cc", + "absl/strings/numbers.cc", + "absl/strings/str_cat.cc", + "absl/strings/str_replace.cc", + "absl/strings/str_split.cc", + "absl/strings/string_view.cc", + "absl/strings/substitute.cc", + "absl/synchronization/barrier.cc", + "absl/synchronization/blocking_counter.cc", + "absl/synchronization/internal/create_thread_identity.cc", + "absl/synchronization/internal/futex_waiter.cc", + "absl/synchronization/internal/graphcycles.cc", + "absl/synchronization/internal/kernel_timeout.cc", + "absl/synchronization/internal/per_thread_sem.cc", + "absl/synchronization/internal/pthread_waiter.cc", + "absl/synchronization/internal/sem_waiter.cc", + "absl/synchronization/internal/stdcpp_waiter.cc", + "absl/synchronization/internal/waiter_base.cc", + "absl/synchronization/internal/win32_waiter.cc", + "absl/synchronization/mutex.cc", + "absl/synchronization/notification.cc", + "absl/time/civil_time.cc", + "absl/time/clock.cc", + "absl/time/duration.cc", + "absl/time/format.cc", + "absl/time/internal/cctz/src/civil_time_detail.cc", + "absl/time/internal/cctz/src/time_zone_fixed.cc", + "absl/time/internal/cctz/src/time_zone_format.cc", + "absl/time/internal/cctz/src/time_zone_if.cc", + "absl/time/internal/cctz/src/time_zone_impl.cc", + "absl/time/internal/cctz/src/time_zone_info.cc", + "absl/time/internal/cctz/src/time_zone_libc.cc", + "absl/time/internal/cctz/src/time_zone_lookup.cc", + "absl/time/internal/cctz/src/time_zone_posix.cc", + "absl/time/internal/cctz/src/zone_info_source.cc", + "absl/time/time.cc", +} diff --git a/zig/deps/protobuf_sources.zon b/zig/deps/protobuf_sources.zon new file mode 100644 index 000000000..68bc66130 --- /dev/null +++ b/zig/deps/protobuf_sources.zon @@ -0,0 +1,29 @@ +// libprotobuf_lite_srcs from protobuf 35.1 src/file_lists.cmake. +.{ + "src/google/protobuf/any_lite.cc", + "src/google/protobuf/arena.cc", + "src/google/protobuf/arena_align.cc", + "src/google/protobuf/arenastring.cc", + "src/google/protobuf/arenaz_sampler.cc", + "src/google/protobuf/extension_set.cc", + "src/google/protobuf/generated_enum_util.cc", + "src/google/protobuf/generated_message_tctable_lite.cc", + "src/google/protobuf/generated_message_util.cc", + "src/google/protobuf/implicit_weak_message.cc", + "src/google/protobuf/inlined_string_field.cc", + "src/google/protobuf/io/coded_stream.cc", + "src/google/protobuf/io/io_win32.cc", + "src/google/protobuf/io/zero_copy_stream.cc", + "src/google/protobuf/io/zero_copy_stream_impl.cc", + "src/google/protobuf/io/zero_copy_stream_impl_lite.cc", + "src/google/protobuf/map.cc", + "src/google/protobuf/message_lite.cc", + "src/google/protobuf/micro_string.cc", + "src/google/protobuf/parse_context.cc", + "src/google/protobuf/port.cc", + "src/google/protobuf/raw_ptr.cc", + "src/google/protobuf/repeated_field.cc", + "src/google/protobuf/repeated_ptr_field.cc", + "src/google/protobuf/stubs/common.cc", + "src/google/protobuf/wire_format_lite.cc", +} diff --git a/zig/mod.zig b/zig/mod.zig new file mode 100644 index 000000000..04fb89b2d --- /dev/null +++ b/zig/mod.zig @@ -0,0 +1,187 @@ +//! First-party code: the IL2CPP and Unity libraries, the mod, its platform entry points, and the macOS loader. +const std = @import("std"); +const Ctx = @import("ctx.zig").Ctx; +const Lib = @import("ctx.zig").Lib; +const globFiles = @import("ctx.zig").globFiles; +const deps = @import("deps.zig"); + +/// Runtime bindings: metadata lookup, typed calls, strings, GC handles and detours. Also exposes Unity's +/// libil2cpp headers. +pub fn il2cpp(ctx: *const Ctx) Lib { + const b = ctx.b; + const headers = Lib{ + .include_dirs = ctx.dirs(&.{ b.path("src/libs/il2cpp/include"), b.path("third_party/libil2cpp") }), + // il2cpp/api.h asks the linker for GameAssembly.lib on Windows. + .lib_dirs = if (ctx.isWindows()) ctx.dirs(&.{b.path("src/libs/il2cpp")}) else &.{}, + }; + const module = ctx.createModule(true); + headers.includeInto(module); + module.addCSourceFiles(.{ + .root = b.path("src/libs/il2cpp"), + .files = &.{ "src/api.cc", "src/il2cpp.cc" }, + .flags = ctx.cxxFlags("c++23", &.{}), + }); + const artifact = ctx.staticLib("il2cpp", module); + b.step("il2cpp", "Build the IL2CPP integration static library").dependOn(&b.addInstallArtifact(artifact, .{}).step); + return .{ .artifact = artifact, .include_dirs = headers.include_dirs, .lib_dirs = headers.lib_dirs }; +} + +/// Unity engine bindings over il2cpp: core types, UI, input and instance tracking. Knows nothing about the game. +pub fn unity(ctx: *const Ctx, runtime: Lib, spud: Lib) Lib { + const b = ctx.b; + const include = ctx.dirs(&.{b.path("src/libs/unity/include")}); + const module = ctx.createModule(true); + for (include) |dir| module.addIncludePath(dir); + runtime.linkInto(module); + spud.linkInto(module); + module.addCSourceFiles(.{ + .root = b.path("src/libs/unity"), + .files = &.{ "src/input.cc", "src/tracker.cc" }, + .flags = ctx.cxxFlags("c++23", &.{}), + }); + const artifact = ctx.staticLib("unity", module); + b.step("unity", "Build the Unity bindings static library").dependOn(&b.addInstallArtifact(artifact, .{}).step); + return .{ .artifact = artifact, .include_dirs = include }; +} + +/// The `mods` static library and the binary the game loads: version.dll on Windows, the injected dylib and its +/// loader on macOS. `libs` is everything the mod compiles against. +pub fn add(ctx: *const Ctx, libs: []const Lib) void { + const b = ctx.b; + const flags = ctx.cxxFlags("c++23", &.{ + "-fms-extensions", + "-Wno-invalid-offsetof", + "-Wno-deprecated-literal-operator", + "-Wno-unused-command-line-argument", + }); + + const module = ctx.createModule(true); + module.addIncludePath(b.path("src/mod")); + if (ctx.options.moddbg) module.addCMacro("_MODDBG", "1"); + if (ctx.options.use_original_bg) module.addCMacro("_USE_ORIGINAL_BG", "1"); + for (libs) |lib| lib.linkInto(module); + embedImages(ctx, module); + addModSources(ctx, module, flags); + const mods = ctx.staticLib("mods", module); + const mods_step = b.step("mods", "Build the core mod static library"); + mods_step.dependOn(&b.addInstallArtifact(mods, .{}).step); + for (libs) |lib| lib.addBuildDependencies(mods_step); + + const entry = ctx.createModule(true); + entry.addIncludePath(b.path("src/mod")); + entry.linkLibrary(mods); + for (libs) |lib| lib.linkInto(entry); + const entry_root = b.path(if (ctx.isWindows()) "src/platform/windows" else "src/platform/macos/dylib"); + entry.addCSourceFiles(.{ + .root = entry_root, + .files = globFiles(b, entry_root, "", &.{".cc"}, &.{}), + .flags = flags, + }); + const library = b.addLibrary(.{ + .name = if (ctx.isWindows()) "version" else "stfc-community-mod", + .linkage = .dynamic, + .root_module = entry, + }); + ctx.applyCompile(library); + if (ctx.isWindows()) { + // version.dll proxies the system DLL: the .def forwards its exports, the .rc carries the build identity. + library.win32_module_definition = b.path("src/platform/windows/version.def"); + const rc_flags = addBuildIdentity(ctx, entry); + entry.addIncludePath(b.path("src/platform/windows")); + entry.addWin32ResourceFile(.{ + .file = b.path("src/platform/windows/version.rc"), + .flags = rc_flags, + .include_paths = &.{ b.path("src/mod"), b.path("src/platform/windows") }, + }); + inline for (.{ "shell32", "user32", "ole32", "oleaut32" }) |lib| entry.linkSystemLibrary(lib, .{}); + } + b.installArtifact(library); + if (ctx.isMacos()) addLoader(ctx, flags); +} + +fn addModSources(ctx: *const Ctx, module: *std.Build.Module, flags: []const []const u8) void { + const b = ctx.b; + const root = b.path("src/mod"); + module.addCSourceFiles(.{ .root = root, .files = globFiles(b, root, "", &.{".cc"}, &.{}), .flags = flags }); + + if (ctx.isMacos()) { + module.addCSourceFiles(.{ .root = root, .files = globFiles(b, root, "", &.{".mm"}, &.{}), .flags = flags }); + module.linkFramework("Cocoa", .{}); + } else if (ctx.isWindows()) { + inline for (.{ "winmm", "rpcrt4", "runtimeobject" }) |lib| module.linkSystemLibrary(lib, .{}); + } +} + +/// Define the build identity as C++ string macros and as version resource defines. Returns the resource flags. +fn addBuildIdentity(ctx: *const Ctx, module: *std.Build.Module) []const []const u8 { + const b = ctx.b; + var defines: [5][2][]const u8 = undefined; + // Each value comes from -D