HyperDbg/hyperdbg/Kbuild
Max Raulea 2f59ad7c70 Kernel Module now Links and compiles!!
The kernel module now links and compiles, there are still a lot of empty
TODOs left, there are empty stubs for hypertrace, assembly files and
kdserial etc. these can be introduced one by one. My first step will be
loading the kernel module from the userspace cli.

Big step forward! :)
2026-08-24 11:20:24 +02:00

381 lines
22 KiB
Makefile

# SPDX-License-Identifier: GPL-3.0
#
# Kbuild for the HyperDbg Linux kernel module.
#
# This file is read by the kernel build system when it is invoked with
# M= pointing at this directory (the hyperdbg/ repo root):
#
# make -C /lib/modules/$(uname -r)/build M=<hyperdbg root> modules
#
# It is driven by linux/kernel/Makefile. kbuild prefers a file named "Kbuild"
# over "Makefile" in the M= directory, so the CMake-generated ./Makefile (which
# builds the *user-mode* CLI) is left untouched — the two build systems coexist.
#
# ---------------------------------------------------------------------------
# DESIGN
# ---------------------------------------------------------------------------
# Windows builds SEVEN separate kernel binaries (hyperkd.sys + hyperhv/hyperlog/
# hyperevade/hypertrace/hyperperf/kdserial as KMDF "export driver" DLLs that link
# against each other's import .libs). Linux has no equivalent of that idiom, so
# everything collapses into a SINGLE module: HyperDbg.ko. All the cross-module
# __declspec(dllexport/dllimport) plumbing and the DllInitialize/DllUnload unload
# trick simply disappear (one link unit, all symbols internal). kdserial is
# dropped entirely (Windows-only serial transport).
#
# Because M= is the repo root, every source the module needs already lives under
# it — no copying/symlinking, and full relative object paths mean the several
# same-named files (Common.c, DpcRoutines.c, UnloadDll.c, Broadcast.c ...) never
# collide.
#
# ---------------------------------------------------------------------------
# STATUS
# ---------------------------------------------------------------------------
# Only the objects under "ACTIVE" below actually compile as kernel code today
# (the Platform* memory/intrinsic wrappers, proven by linux/mock/kernel). Every
# other object is listed but COMMENTED OUT: the source still targets the Windows
# WDK (ntoskrnl/WDF/ntifs.h) and will not compile until its dependencies are
# routed through the platform layer. Uncomment each line as its translation unit
# is ported — the module still links and loads in the meantime.
#
# The list mirrors the .c files actually present on disk (the per-module
# CMakeLists.txt files are stale and were NOT trusted).
# ===========================================================================
obj-m += HyperDbg.o
# ---------------------------------------------------------------------------
# INCLUDE MODEL
# ---------------------------------------------------------------------------
# Every TU says `#include "pch.h"` and MUST get its OWN module's pch, the way
# each .vcxproj's /I ordering arranges it on Windows. That is not cosmetic:
# hyperkd and hyperhv each define _NT_KPROCESS and _PAGE_ENTRY, so a single pch
# that pulled in both would not compile.
#
# Therefore the module roots are NOT global — they are attached per object at
# the bottom of this file. Only the genuinely shared roots live in ccflags-y.
#
# The Linux side that no module pch can carry (kernel headers + the scope macros
# a .vcxproj would pass as /D) is force-included in front of every TU instead.
ccflags-y += -include $(src)/linux/kernel/LinuxPrelude.h
ccflags-y += -I$(src)/include
ccflags-y += -I$(src)/dependencies
# Zydis: hyperhv's disassembler. The Windows build compiles it for kernel mode
# with these same defines (no libc, static), see hyperhv.vcxproj.
ccflags-y += -I$(src)/dependencies/zydis/include
ccflags-y += -I$(src)/dependencies/zydis/dependencies/zycore/include
# zydis's own data tables are pulled with angle-bracket includes (<Generated/*.inc>),
# so its src/ dir must be on the search path — zydis's CMake adds it as PRIVATE "src".
ccflags-y += -I$(src)/dependencies/zydis/src
ccflags-y += -DZYDIS_STATIC_BUILD -DZYCORE_STATIC_BUILD -DZYAN_NO_LIBC -DZYDIS_NO_LIBC
# Windows-origin sources declare no-argument functions as `f()` rather than the
# ISO C `f(void)`; the kernel builds with -Werror=strict-prototypes, so silence
# it module-wide rather than editing every shared signature.
ccflags-y += -Wno-strict-prototypes
# hyperhv passes DPC routines of several shapes (VOID- and BOOLEAN-returning, and
# some with a typed 2nd parameter) to KeGenericCallDpc(), whose prototype is the
# WDK PKDEFERRED_ROUTINE. MSVC accepts this with a warning (C4113); GCC makes
# incompatible-pointer-types a hard error. Rewriting the call sites would edit
# shared Windows code, which the port forbids, so downgrade it to a WARNING
# (-Wno-error=, not -Wno-) — the mismatch stays visible, exactly as on Windows.
ccflags-y += -Wno-error=incompatible-pointer-types
# Each module keeps its globals as bare tentative definitions in a header that
# its pch pulls into EVERY TU (hyperkd/header/globals/Global.h: `KEVENT g_Foo;`).
# MSVC merges those; GCC has defaulted to -fno-common since 10, which turns them
# into "multiple definition" at link. -fcommon restores the model the source was
# written against, instead of rewriting every globals header to extern + one
# defining TU (that would be a refactor of shared Windows code).
ccflags-y += -fcommon
# ===========================================================================
# ACTIVE — compiles + links today
# ===========================================================================
HyperDbg-objs += linux/kernel/Entry.o
HyperDbg-objs += include/platform/kernel/code/PlatformMem.o
HyperDbg-objs += include/platform/kernel/code/PlatformIntrinsics.o
HyperDbg-objs += include/platform/kernel/code/PlatformIntrinsicsVmx.o
# ===========================================================================
# PENDING — uncomment as each is ported off the WDK
# ===========================================================================
# --- platform/kernel (OS abstraction layer) --------------------------------
# These are ported and compile clean:
HyperDbg-objs += include/platform/kernel/code/PlatformBroadcast.o
HyperDbg-objs += include/platform/kernel/code/PlatformCpu.o
HyperDbg-objs += include/platform/kernel/code/PlatformDbg.o
HyperDbg-objs += include/platform/kernel/code/PlatformDpc.o
HyperDbg-objs += include/platform/kernel/code/PlatformEvent.o
HyperDbg-objs += include/platform/kernel/code/PlatformIo.o
HyperDbg-objs += include/platform/kernel/code/PlatformIrql.o
HyperDbg-objs += include/platform/kernel/code/PlatformProcess.o
HyperDbg-objs += include/platform/kernel/code/PlatformSpinlock.o
HyperDbg-objs += include/platform/kernel/code/PlatformStr.o
HyperDbg-objs += include/platform/kernel/code/PlatformTime.o
# --- hyperlog (message logging/tracing) ------------------------------------
HyperDbg-objs += hyperlog/code/Logging.o
HyperDbg-objs += hyperlog/code/UnloadDll.o
# --- components (shared, header-driven) ------------------------------------
# Self-contained (compile clean today):
HyperDbg-objs += include/components/spinlock/code/Spinlock.o
HyperDbg-objs += include/components/optimizations/code/AvlTree.o
HyperDbg-objs += include/components/optimizations/code/InsertionSort.o
# Need the logging layer (Log/LogInfo), so they came online with hyperlog:
HyperDbg-objs += include/components/optimizations/code/BinarySearch.o
HyperDbg-objs += include/components/optimizations/code/OptimizationsExamples.o
# DROPPED (Windows-only): callback/HyperLogCallback.c DEFINES the same
# LogCallback* entry points as hyperlog/Logging.c. On Windows that is the
# per-DLL forwarding shim — hyperhv/hypertrace/hyperperf cannot call into
# hyperlog.dll directly, so each compiles this file to bounce through its own
# g_Callbacks table. In the single Linux module the real implementation is
# already linked in, so this file is both redundant and a duplicate symbol.
# HyperDbg-objs += include/components/callback/code/HyperLogCallback.o
# --- script-eval (script engine kernel eval) -------------------------------
# Compile-gated on hyperhv/hyperkd/hypertrace: with SCRIPT_ENGINE_KERNEL_MODE now
# defined (see linux/kernel/pch.h) these TUs select their kernel arms, which call
# into the VMM (VmFunc*, MemoryMapper*, CheckAccessValidityAndSafety, ...), the
# debugger (g_DbgState, Debugger*Event, Kd/Ud*, Tracing*) and hypertrace
# (HyperTraceLbr*). Keep commented out until those modules land.
HyperDbg-objs += script-eval/code/Functions.o
HyperDbg-objs += script-eval/code/Keywords.o
HyperDbg-objs += script-eval/code/PseudoRegisters.o
HyperDbg-objs += script-eval/code/Regs.o
HyperDbg-objs += script-eval/code/ScriptEngineEval.o
# --- hyperhv (hypervisor: VMX/EPT) -----------------------------------------
HyperDbg-objs += hyperhv/code/broadcast/Broadcast.o
HyperDbg-objs += hyperhv/code/broadcast/DpcRoutines.o
HyperDbg-objs += hyperhv/code/common/Bitwise.o
HyperDbg-objs += hyperhv/code/common/Common.o
# HyperDbg-objs += hyperhv/code/common/UnloadDll.o
HyperDbg-objs += hyperhv/code/components/registers/DebugRegisters.o
HyperDbg-objs += hyperhv/code/devices/Apic.o
HyperDbg-objs += hyperhv/code/devices/Pci.o
HyperDbg-objs += hyperhv/code/disassembler/Disassembler.o
# ZydisKernel.c is the Windows-only Zydis sample driver (dead code, WDK PE deps) —
# Linux swaps the whole TU for an empty stub, ZydisKernel-linux.c (see that file).
HyperDbg-objs += hyperhv/code/disassembler/ZydisKernel-linux.o
HyperDbg-objs += hyperhv/code/features/CompatibilityChecks.o
HyperDbg-objs += hyperhv/code/features/DirtyLogging.o
HyperDbg-objs += hyperhv/code/globals/GlobalVariableManagement.o
HyperDbg-objs += hyperhv/code/hooks/ept-hook/EptHook.o
HyperDbg-objs += hyperhv/code/hooks/ept-hook/ExecTrap.o
HyperDbg-objs += hyperhv/code/hooks/ept-hook/ModeBasedExecHook.o
HyperDbg-objs += hyperhv/code/hooks/syscall-hook/EferHook.o
HyperDbg-objs += hyperhv/code/hooks/syscall-hook/SyscallCallback.o
HyperDbg-objs += hyperhv/code/interface/Callback.o
HyperDbg-objs += hyperhv/code/interface/Configuration.o
HyperDbg-objs += hyperhv/code/interface/DirectVmcall.o
HyperDbg-objs += hyperhv/code/interface/Dispatch.o
HyperDbg-objs += hyperhv/code/interface/Export.o
HyperDbg-objs += hyperhv/code/interface/HyperEvade.o
# hyperevade itself is Windows-only and dropped from this module (see below), but
# hyperhv calls its Transparent* symbols unconditionally — this Linux-only TU
# supplies them as no-ops so the .ko links.
HyperDbg-objs += hyperhv/code/interface/HyperEvadeStubs-linux.o
HyperDbg-objs += hyperhv/code/memory/AddressCheck.o
HyperDbg-objs += hyperhv/code/memory/Conversion.o
HyperDbg-objs += hyperhv/code/memory/Layout.o
HyperDbg-objs += hyperhv/code/memory/MemoryManager.o
HyperDbg-objs += hyperhv/code/memory/MemoryMapper.o
HyperDbg-objs += hyperhv/code/memory/Segmentation.o
HyperDbg-objs += hyperhv/code/memory/SwitchLayout.o
HyperDbg-objs += hyperhv/code/mmio/MmioShadowing.o
HyperDbg-objs += hyperhv/code/processor/Idt.o
HyperDbg-objs += hyperhv/code/processor/Smm.o
HyperDbg-objs += hyperhv/code/vmm/ept/Ept.o
HyperDbg-objs += hyperhv/code/vmm/ept/Invept.o
HyperDbg-objs += hyperhv/code/vmm/ept/Vpid.o
HyperDbg-objs += hyperhv/code/vmm/vmx/Counters.o
HyperDbg-objs += hyperhv/code/vmm/vmx/CrossVmcalls.o
HyperDbg-objs += hyperhv/code/vmm/vmx/CrossVmexits.o
HyperDbg-objs += hyperhv/code/vmm/vmx/Events.o
HyperDbg-objs += hyperhv/code/vmm/vmx/Hv.o
HyperDbg-objs += hyperhv/code/vmm/vmx/IdtEmulation.o
HyperDbg-objs += hyperhv/code/vmm/vmx/IoHandler.o
HyperDbg-objs += hyperhv/code/vmm/vmx/ManageRegs.o
HyperDbg-objs += hyperhv/code/vmm/vmx/MsrHandlers.o
HyperDbg-objs += hyperhv/code/vmm/vmx/Mtf.o
HyperDbg-objs += hyperhv/code/vmm/vmx/ProtectedHv.o
HyperDbg-objs += hyperhv/code/vmm/vmx/Vmcall.o
HyperDbg-objs += hyperhv/code/vmm/vmx/Vmexit.o
HyperDbg-objs += hyperhv/code/vmm/vmx/Vmx.o
HyperDbg-objs += hyperhv/code/vmm/vmx/VmxBroadcast.o
HyperDbg-objs += hyperhv/code/vmm/vmx/VmxMechanisms.o
HyperDbg-objs += hyperhv/code/vmm/vmx/VmxRegions.o
# hyperhv assembly: the *.asm (MASM) are ported to *.S (GAS) as EMPTY STUBS —
# every symbol is a bare `ret` placeholder so the module links; real bodies are
# still TODO(Linux) in each .S. Active because the stubs are self-contained
# (define symbols, reference nothing) so the module stays loadable.
HyperDbg-objs += hyperhv/code/assembly/AsmCommon-linux.o
HyperDbg-objs += hyperhv/code/assembly/AsmEpt-linux.o
HyperDbg-objs += hyperhv/code/assembly/AsmHooks-linux.o
HyperDbg-objs += hyperhv/code/assembly/AsmInterruptHandlers-linux.o
HyperDbg-objs += hyperhv/code/assembly/AsmSegmentRegs-linux.o
HyperDbg-objs += hyperhv/code/assembly/AsmVmexitHandler-linux.o
HyperDbg-objs += hyperhv/code/assembly/AsmVmxContextState-linux.o
HyperDbg-objs += hyperhv/code/assembly/AsmVmxOperation-linux.o
# --- hyperkd (the driver: device/IOCTL + debugger core) --------------------
HyperDbg-objs += hyperkd/code/common/Common.o
HyperDbg-objs += hyperkd/code/common/Synchronization.o
HyperDbg-objs += hyperkd/code/debugger/broadcast/DpcRoutines.o
HyperDbg-objs += hyperkd/code/debugger/broadcast/HaltedBroadcast.o
HyperDbg-objs += hyperkd/code/debugger/broadcast/HaltedRoutines.o
HyperDbg-objs += hyperkd/code/debugger/commands/BreakpointCommands.o
HyperDbg-objs += hyperkd/code/debugger/commands/Callstack.o
HyperDbg-objs += hyperkd/code/debugger/commands/DebuggerCommands.o
HyperDbg-objs += hyperkd/code/debugger/commands/ExtensionCommands.o
HyperDbg-objs += hyperkd/code/debugger/communication/SerialConnection.o
HyperDbg-objs += hyperkd/code/debugger/communication/KdSerial-linux.o
HyperDbg-objs += hyperkd/code/debugger/core/Debugger.o
HyperDbg-objs += hyperkd/code/debugger/core/DebuggerVmcalls.o
HyperDbg-objs += hyperkd/code/debugger/core/HaltedCore.o
HyperDbg-objs += hyperkd/code/debugger/events/ApplyEvents.o
HyperDbg-objs += hyperkd/code/debugger/events/DebuggerEvents.o
HyperDbg-objs += hyperkd/code/debugger/events/Termination.o
HyperDbg-objs += hyperkd/code/debugger/events/ValidateEvents.o
HyperDbg-objs += hyperkd/code/debugger/kernel-level/Kd.o
HyperDbg-objs += hyperkd/code/debugger/memory/Allocations.o
HyperDbg-objs += hyperkd/code/debugger/memory/PoolManager.o
HyperDbg-objs += hyperkd/code/debugger/meta-events/MetaDispatch.o
HyperDbg-objs += hyperkd/code/debugger/meta-events/Tracing.o
HyperDbg-objs += hyperkd/code/debugger/objects/Process.o
HyperDbg-objs += hyperkd/code/debugger/objects/Thread.o
HyperDbg-objs += hyperkd/code/debugger/script-engine/ScriptEngine.o
HyperDbg-objs += hyperkd/code/debugger/tests/KernelTests.o
HyperDbg-objs += hyperkd/code/debugger/user-level/Attaching.o
HyperDbg-objs += hyperkd/code/debugger/user-level/ThreadHolder.o
HyperDbg-objs += hyperkd/code/debugger/user-level/Ud.o
HyperDbg-objs += hyperkd/code/debugger/user-level/UserAccess.o
# Driver.c is the Windows-only WDM bootstrap (DriverEntry/DRIVER_OBJECT/IRP_MJ
# dispatch) — Linux swaps the whole TU for the Driver-linux.c skeleton (see that
# file). The char-device layer (module_init/file_operations) is still TODO there.
HyperDbg-objs += hyperkd/code/driver/Driver-linux.o
HyperDbg-objs += hyperkd/code/driver/Ioctl.o
HyperDbg-objs += hyperkd/code/driver/Loader.o
# hyperkd assembly: AsmDebugger.asm (MASM) is ported to AsmDebugger-linux.S (GAS)
# as EMPTY STUBS — every symbol is a bare `ret` placeholder so the module links;
# real bodies are still TODO(Linux). Matches the hyperhv Asm*-linux.S stubs.
HyperDbg-objs += hyperkd/code/assembly/AsmDebugger-linux.o
# HyperDbg-objs += hyperkd/code/assembly/AsmDebugger.o
# --- hyperevade (transparency / anti-detection) ----------------------------
# DROPPED from the Linux kernel module. hyperevade is Windows-only transparency/
# anti-detection code (ActivateHyperEvadeProject is FALSE in
# include/config/Configuration.h) and does not need to compile here. Its sources
# stay on their Windows original — the port-mechanical platform swaps were
# reverted — and it is left out of the build entirely.
# HyperDbg-objs += hyperevade/code/SyscallFootprints.o
# HyperDbg-objs += hyperevade/code/Transparency.o
# HyperDbg-objs += hyperevade/code/VmxFootprints.o
# HyperDbg-objs += hyperevade/code/UnloadDll.o
# --- hyperperf (PMU) -------------------------------------------------------
# HyperDbg-objs += hyperperf/code/api/PerfApi.o
# HyperDbg-objs += hyperperf/code/broadcast/Broadcast.o
# HyperDbg-objs += hyperperf/code/broadcast/DpcRoutines.o
# HyperDbg-objs += hyperperf/code/common/UnloadDll.o
# --- hypertrace (LBR / Intel PT) -------------------------------------------
# DEFERRED, not dropped: real Intel LBR + Intel PT hardware tracing that Linux will
# want (unlike hyperevade, which is Windows-only). ~4700 lines not ported yet; LBR is
# the natural first milestone, Intel PT's ToPA output buffers are the hard part. Until
# then, active TUs reference ~10 of its exported entry points, so this one Linux stub
# TU defines them as no-ops purely so the .ko links (see TraceApi-linux.c).
HyperDbg-objs += hypertrace/code/api/TraceApi-linux.o
# HyperDbg-objs += hypertrace/code/api/LbrApi.o
# HyperDbg-objs += hypertrace/code/api/PtApi.o
# HyperDbg-objs += hypertrace/code/api/TraceApi.o
# HyperDbg-objs += hypertrace/code/broadcast/Broadcast.o
# HyperDbg-objs += hypertrace/code/broadcast/DpcRoutines.o
# HyperDbg-objs += hypertrace/code/common/UnloadDll.o
# HyperDbg-objs += hypertrace/code/lbr/Lbr.o
# HyperDbg-objs += hypertrace/code/pt/Pt.o
# --- zydis (kernel disassembler, needed by hyperhv/disassembler) -----------
# Built with ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYDIS_STATIC_BUILD;ZYCORE_STATIC_BUILD
# (defines + include paths in the ccflags-y block above). Self-contained: no
# external symbols, so it links into the .ko on its own even before hyperhv
# calls it. Windows builds zydis as a separate static lib; Linux has one module,
# so the sources compile straight in.
# zycore (zydis's support library)
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/Allocator.o
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/ArgParse.o
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/Bitset.o
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/Format.o
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/List.o
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/String.o
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/Vector.o
HyperDbg-objs += dependencies/zydis/dependencies/zycore/src/Zycore.o
# zydis proper
HyperDbg-objs += dependencies/zydis/src/Decoder.o
HyperDbg-objs += dependencies/zydis/src/DecoderData.o
HyperDbg-objs += dependencies/zydis/src/Disassembler.o
HyperDbg-objs += dependencies/zydis/src/Encoder.o
HyperDbg-objs += dependencies/zydis/src/EncoderData.o
HyperDbg-objs += dependencies/zydis/src/FormatterATT.o
HyperDbg-objs += dependencies/zydis/src/FormatterBase.o
HyperDbg-objs += dependencies/zydis/src/FormatterBuffer.o
HyperDbg-objs += dependencies/zydis/src/Formatter.o
HyperDbg-objs += dependencies/zydis/src/FormatterIntel.o
HyperDbg-objs += dependencies/zydis/src/MetaInfo.o
HyperDbg-objs += dependencies/zydis/src/Mnemonic.o
HyperDbg-objs += dependencies/zydis/src/Register.o
HyperDbg-objs += dependencies/zydis/src/Segment.o
HyperDbg-objs += dependencies/zydis/src/SharedData.o
HyperDbg-objs += dependencies/zydis/src/String.o
HyperDbg-objs += dependencies/zydis/src/Utils.o
HyperDbg-objs += dependencies/zydis/src/Zydis.o
# ===========================================================================
# PER-OBJECT INCLUDE ROOTS
# ===========================================================================
# Mirrors the /I list of each .vcxproj so every TU resolves "pch.h" to its own
# module. kbuild appends CFLAGS_<obj> after ccflags-y, and GCC takes the FIRST
# -I that matches, which is why no module root may appear in ccflags-y above.
#
# Shared TUs (the platform layer, components/, linux/kernel/Entry.c) have no
# module of their own and use the unified linux/kernel/pch.h.
hyperkd-roots := -I$(src)/hyperkd/header -I$(src)/hyperkd
# 7-into-1 collision fix: hyperkd and hyperhv each carry their OWN copy of a few
# private helpers (same name, slightly different bodies — e.g. hyperkd's
# CommonGetProcessNameFromProcessControlBlock calls PsGetProcessImageFileName while
# hyperhv's calls PlatformProcessGetImageFileName). On Windows they live in separate
# DLLs and never collide; in the single .ko they are duplicate definitions. None are
# cross-module (absent from SDK/imports), so each module must keep its own. Rename
# hyperkd's copies module-wide (definition + all its callers, script-eval included)
# so the token stays self-consistent within hyperkd; hyperhv keeps the originals.
# Linux/Kbuild-only — no source edits, Windows untouched.
hyperkd-roots += -DCommonGetProcessNameFromProcessControlBlock=Kd_CommonGetProcessNameFromProcessControlBlock
hyperkd-roots += -DCommonCpuidInstruction=Kd_CommonCpuidInstruction
hyperkd-roots += -DDpcRoutineRunTaskOnSingleCore=Kd_DpcRoutineRunTaskOnSingleCore
hyperhv-roots := -I$(src)/hyperhv -I$(src)/hyperhv/header -I$(src)/hyperhv/code
hyperlog-roots := -I$(src)/hyperlog/header
# hyperevade is dropped from the Linux module (Windows-only), so no roots for it.
hypertrace-roots := -I$(src)/hypertrace/header
hyperperf-roots := -I$(src)/hyperperf/header
shared-roots := -I$(src)/linux/kernel
# Driven off the files on disk, not off HyperDbg-objs, so that
# `make one FILE=<path>` works for a TU that is still commented out above —
# that is the whole porting loop.
mod-sources = $(patsubst $(src)/%.c,%.o,$(shell find $(src)/$(1) -name '*.c' 2>/dev/null))
$(foreach o,$(call mod-sources,hyperkd),$(eval CFLAGS_$(o) += $(hyperkd-roots)))
$(foreach o,$(call mod-sources,hyperhv),$(eval CFLAGS_$(o) += $(hyperhv-roots)))
$(foreach o,$(call mod-sources,hyperlog),$(eval CFLAGS_$(o) += $(hyperlog-roots)))
$(foreach o,$(call mod-sources,hypertrace),$(eval CFLAGS_$(o) += $(hypertrace-roots)))
$(foreach o,$(call mod-sources,hyperperf),$(eval CFLAGS_$(o) += $(hyperperf-roots)))
# script-eval is compiled INSIDE hyperkd on Windows, so it takes hyperkd's roots
$(foreach o,$(call mod-sources,script-eval),$(eval CFLAGS_$(o) += $(hyperkd-roots)))
$(foreach o,$(call mod-sources,include),$(eval CFLAGS_$(o) += $(shared-roots)))
$(foreach o,$(call mod-sources,linux),$(eval CFLAGS_$(o) += $(shared-roots)))