# Copyright 2026 Aarav Ravindra Kharade # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # ═══════════════════════════════════════════════════════════════════ # ArkOS Build System v4.0 — Top-Level Makefile # ═══════════════════════════════════════════════════════════════════ # # Setup: # source envsetup.sh — Load build environment # type arm64 — Select ARM64 target (Raspberry Pi 4) # type x86_64 — Select x86_64 target (PC / QEMU) # # Build Targets: # make — Full incremental build for selected target # make clean — Remove all build artifacts and caches # # Test Targets (cross-architecture): # make test-uefi — x86_64 UEFI (auto-detects host arch) # make test-bios — x86_64 BIOS (auto-detects host arch) # make test-uefi-arm64 — ARM64 UEFI via QEMU # make test-bios-arm64 — ARM64 direct kernel boot via QEMU # # ═══════════════════════════════════════════════════════════════════ # Project root is one level above this Makefile (arkos/Makefile) ROOT := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))/.. ) TOOLS := $(ROOT)/tools ARKOS := $(ROOT)/arkos # ── Host Architecture Detection ─────────────────────────────────── HOST_ARCH := $(shell uname -m) # ── Clang Toolchain (all compilation uses clang) ────────────────── # Prefer prebuilt clang, fall back to system clang CLANG := $(shell if [ -x $(ARKOS)/prebuilts/clang/bin/clang ]; then \ echo $(ARKOS)/prebuilts/clang/bin/clang; \ else echo clang; fi) CLANGXX := $(shell if [ -x $(ARKOS)/prebuilts/clang/bin/clang++ ]; then \ echo $(ARKOS)/prebuilts/clang/bin/clang++; \ else echo clang++; fi) # ── Target Architecture (set by envsetup.sh type command) ───────── # Default to x86_64 if no target selected TARGET_ARCH ?= x86_64 TARGET_TRIPLE ?= x86_64-linux-gnu # ── Architecture-Specific Compiler Flags ────────────────────────── X86_CC := $(CLANG) --target=x86_64-linux-gnu X86_CXX := $(CLANGXX) --target=x86_64-linux-gnu ARM64_CC := $(CLANG) --target=aarch64-linux-gnu -mcpu=cortex-a72 -mno-outline-atomics ARM64_CXX := $(CLANGXX) --target=aarch64-linux-gnu -mcpu=cortex-a72 -mno-outline-atomics .PHONY: build clean \ test-uefi test-bios test-uefi-arm64 test-bios-arm64 # ── Build ────────────────────────────────────────────────────────── # Reads TARGET_ARCH from envsetup.sh type command. # Defaults to x86_64 if no target was selected. # Set NO_IMAGE=1 to skip assembling individual .img files into rpi4.img build: @$(MAKE) --no-print-directory -C $(TOOLS) && chmod +x $(TOOLS)/build ifeq ($(TARGET_ARCH),aarch64) ifeq ($(NO_IMAGE),1) @$(TOOLS)/build $(ARKOS) --device rpi4 --no-image else @$(TOOLS)/build $(ARKOS) --device rpi4 endif else @$(TOOLS)/build $(ARKOS) endif # ── Clean ────────────────────────────────────────────────────────── clean: rm -rf out_staging finished boot/assets @$(MAKE) --no-print-directory -C $(TOOLS) clean # ═══════════════════════════════════════════════════════════════════ # Test Targets — Cross-Architecture QEMU Emulation # ═══════════════════════════════════════════════════════════════════ # These targets auto-detect the host CPU architecture and use # KVM when possible (same arch), or TCG software emulation when # running cross-architecture (e.g., x86_64 on ARM64 host). # ═══════════════════════════════════════════════════════════════════ # ── test-uefi: Boot x86_64 UEFI image ──────────────────────────── # On ARM64 host: uses qemu-system-x86_64 with TCG (no KVM) # On x86_64 host: uses KVM for near-native speed test-uefi: @echo "Testing ArkOS x86_64 UEFI (host: $(HOST_ARCH))..." @if [ "$(HOST_ARCH)" = "x86_64" ] || [ "$(HOST_ARCH)" = "amd64" ]; then \ ACCEL="-enable-kvm"; \ else \ ACCEL="-accel tcg"; \ fi; \ qemu-system-x86_64 \ $$ACCEL \ -bios /usr/share/edk2/x64/OVMF.4m.fd \ -m 2048 -smp 2 \ -drive file=finished/boot.img,format=raw,index=0,media=disk,if=virtio \ -drive file=finished/sys.img,format=raw,index=1,media=disk,if=virtio \ -drive file=finished/vend.img,format=raw,index=2,media=disk,if=virtio \ -device virtio-vga,edid=on,xres=1920,yres=1080 \ -debugcon file:ovmf.log -global isa-debugcon.iobase=0x402 \ -usb -device usb-tablet \ -netdev user,id=net0 \ -device virtio-net-pci,netdev=net0 \ -serial stdio # ── test-bios: Boot x86_64 BIOS image ──────────────────────────── test-bios: @echo "Testing ArkOS x86_64 BIOS (host: $(HOST_ARCH))..." @if [ "$(HOST_ARCH)" = "x86_64" ] || [ "$(HOST_ARCH)" = "amd64" ]; then \ ACCEL="-enable-kvm"; \ else \ ACCEL="-accel tcg"; \ fi; \ qemu-system-x86_64 \ $$ACCEL \ -m 2048 -smp 2 \ -drive file=finished/boot.img,format=raw,index=0,media=disk,if=virtio \ -drive file=finished/sys.img,format=raw,index=1,media=disk,if=virtio \ -drive file=finished/vend.img,format=raw,index=2,media=disk,if=virtio \ -vga std \ -debugcon file:ovmf.log -global isa-debugcon.iobase=0x402 \ -usb -device usb-tablet \ -netdev user,id=net0 \ -device virtio-net-pci,netdev=net0 \ -serial stdio # ── test-uefi-arm64: Boot ARM64 image with UEFI ────────────────── # On x86_64 host: uses qemu-system-aarch64 with TCG # On ARM64 host: uses KVM for near-native speed test-uefi-arm64: @echo "Testing ArkOS ARM64 UEFI (host: $(HOST_ARCH))..." @if [ "$(HOST_ARCH)" = "aarch64" ] || [ "$(HOST_ARCH)" = "arm64" ]; then \ ACCEL="-enable-kvm"; \ else \ ACCEL="-accel tcg"; \ fi; \ qemu-system-aarch64 \ $$ACCEL \ -M virt -cpu cortex-a72 \ -m 2048 -smp 4 \ -bios /usr/share/AAVMF/AAVMF_CODE.fd \ -drive file=finished/rpi4/rpi4.img,format=raw,if=virtio \ -device virtio-gpu-pci \ -device usb-ehci -device usb-kbd -device usb-mouse \ -netdev user,id=net0 \ -device virtio-net-pci,netdev=net0 \ -serial stdio # ── test-bios-arm64: Boot ARM64 direct kernel (RPi4 style) ─────── test-bios-arm64: @echo "Testing ArkOS ARM64 direct kernel boot (host: $(HOST_ARCH))..." @if [ "$(HOST_ARCH)" = "aarch64" ] || [ "$(HOST_ARCH)" = "arm64" ]; then \ ACCEL="-enable-kvm"; \ else \ ACCEL="-accel tcg"; \ fi; \ qemu-system-aarch64 \ $$ACCEL \ -M raspi4b \ -m 2048 \ -kernel finished/rpi4/kernel8.img \ -dtb kernel/prebuilts/bcm2711-rpi-4-b.dtb \ -initrd finished/rpi4/initramfs.img \ -append "console=ttyAMA0,115200 loglevel=0 logo.nologo quiet init=/init rw vt.global_cursor_default=0" \ -serial mon:stdio \ -usb -device usb-kbd -device usb-mouse \ -device usb-net,netdev=net0 \ -netdev user,id=net0 # ═══════════════════════════════════════════════════════════════════ # ARM64 (Raspberry Pi 4) Binary Compilation Targets # ═══════════════════════════════════════════════════════════════════ # These are invoked by tools/build via `make -C ` # when building with --device rpi4. # All C/C++ compilation uses clang with --target=aarch64-linux-gnu. # ═══════════════════════════════════════════════════════════════════ # ── ARM64 fb_helper.o — Framebuffer ioctl bridge ───────────────── out_staging/rpi4/fb_helper.o: system/core/fb_helper.c @mkdir -p out_staging/rpi4 $(ARM64_CC) -c system/core/fb_helper.c -o out_staging/rpi4/fb_helper.o # ── ARM64 ArkFontRobotoBoldData.o — Font data ──────────────────── out_staging/rpi4/ArkFontRobotoBoldData.o: arkrt/ark.display.graphics/ArkFontRobotoBoldData.c @mkdir -p out_staging/rpi4 $(ARM64_CC) -O3 -c arkrt/ark.display.graphics/ArkFontRobotoBoldData.c -o out_staging/rpi4/ArkFontRobotoBoldData.o # ── ARM64 init — PID 1 process ─────────────────────────────────── out_staging/rpi4/init: system/core/init.c vendor/verify/sha256.c @mkdir -p out_staging/rpi4 $(ARM64_CC) -static vendor/verify/sha256.c system/core/init.c \ -Ivendor/verify -DARK_KEY=\""$(ARK_KEY)"\" \ -o out_staging/rpi4/init SWIFT_AARCH64_SDK := $(shell if [ -d $(HOME)/.swiftpm/swift-sdks/swift-6.3.2-RELEASE_static-linux.artifactbundle/swift-6.3.2-RELEASE_static-linux-0.1.0/swift-linux-musl/musl-1.2.5.sdk/aarch64 ]; then \ echo $(HOME)/.swiftpm/swift-sdks/swift-6.3.2-RELEASE_static-linux.artifactbundle/swift-6.3.2-RELEASE_static-linux-0.1.0/swift-linux-musl/musl-1.2.5.sdk/aarch64; \ else echo $(CURDIR)/prebuilts/Swift/swift-6.3.2-RELEASE_static-linux-0.1.0/swift-linux-musl/musl-1.2.5.sdk/aarch64; fi) SWIFT_AARCH64_LIB := $(SWIFT_AARCH64_SDK)/usr/lib/swift_static/linux-static SWIFT_AARCH64_LINK := $(ARM64_CC) -static \ $(SWIFT_AARCH64_LIB)/aarch64/swiftrt.o \ $(CURDIR)/prebuilts/mimalloc.o \ -L$(SWIFT_AARCH64_SDK)/usr/lib \ -L$(SWIFT_AARCH64_LIB) # Foundation and other modules live in swift_static/ which swiftc doesn't # auto-search. We must add explicit -I flags for module discovery. SWIFT_AARCH64_SWIFTC := swiftc -c -whole-module-optimization -O \ -package-name arkos \ -target aarch64-swift-linux-musl -target-cpu cortex-a72 \ -Xcc -mno-outline-atomics \ -sdk $(SWIFT_AARCH64_SDK) \ -I $(SWIFT_AARCH64_LIB) \ -I $(SWIFT_AARCH64_LIB)/aarch64 SWIFT_AARCH64_LIBS := -Wl,--start-group -lswiftCore -lswiftMusl -lswiftDispatch -ldispatch -lBlocksRuntime \ -lFoundation -lFoundationEssentials -l_FoundationCShims -l_FoundationCollections \ -l_FoundationICU -lFoundationInternationalization -lFoundationNetworking -lFoundationXML \ -lCoreFoundation -l_CFURLSessionInterface -l_CFXMLInterface -lswift_Concurrency \ -lswiftRuntime -lswift_StringProcessing -lswiftSynchronization -lswift_RegexParser \ -lfts -lunwind -lc++ -lc++abi -lc -Wl,--end-group -lpthread -ldl -lm # ── ARM64 arkrt — ArkOS Runtime Daemon ─────────────────────────── out_staging/rpi4/early_init.o: arkrt/early_init.c @mkdir -p out_staging/rpi4 $(ARM64_CC) -c arkrt/early_init.c -o out_staging/rpi4/early_init.o out_staging/rpi4/graphics_c_built: $(TOOLS)/build_graphics_c.sh @mkdir -p out_staging/rpi4 $(TOOLS)/build_graphics_c.sh aarch64 "$(ARM64_CC)" out_staging/rpi4 touch out_staging/rpi4/graphics_c_built WAYLAND_OBJS_ARM = out_staging/rpi4/wl_client.o out_staging/rpi4/wl_os.o out_staging/rpi4/wl_util.o out_staging/rpi4/wl_conn.o out_staging/rpi4/wl_proto.o out_staging/rpi4/wl_ffi.o out_staging/rpi4/wl_server.o out_staging/rpi4/wl_event_loop.o out_staging/rpi4/wl_shm.o out_staging/rpi4/xdg_shell.o DRM_OBJS_ARM = out_staging/rpi4/drm1.o out_staging/rpi4/drm2.o out_staging/rpi4/drm3.o out_staging/rpi4/drm4.o out_staging/rpi4/drm5.o out_staging/rpi4/arkrt: $(shell find arkrt -name "*.swift") out_staging/rpi4/early_init.o out_staging/rpi4/graphics_c_built @mkdir -p out_staging/rpi4 @$(SWIFT_AARCH64_SWIFTC) -I arkrt/wayland/src -I arkrt/libdrm -I arkrt/libdrm/include/drm -Xcc -fmodule-map-file=arkrt/wayland/src/module.modulemap -Xcc -fmodule-map-file=arkrt/libdrm/module.modulemap $(filter %.swift,$^) -o out_staging/rpi4/arkrt.o && \ $(SWIFT_AARCH64_LINK) out_staging/rpi4/arkrt.o out_staging/rpi4/early_init.o $(WAYLAND_OBJS_ARM) $(DRM_OBJS_ARM) -o $@ $(SWIFT_AARCH64_LIBS) || \ echo " \033[1;33m[NOTICE]\033[0m Swift aarch64 target stdlib missing. Skipping arkrt (ARM64) binary." # ── ARM64 ui_daemon — Display Compositor ───────────────────────── out_staging/rpi4/system/ui_daemon: system/display/main.swift system/display/splash.swift out_staging/rpi4/fb_helper.o @mkdir -p out_staging/rpi4/system @$(SWIFT_AARCH64_SWIFTC) system/display/main.swift system/display/splash.swift -o out_staging/rpi4/system/ui_daemon.o && \ $(SWIFT_AARCH64_LINK) out_staging/rpi4/system/ui_daemon.o out_staging/rpi4/fb_helper.o -o $@ $(SWIFT_AARCH64_LIBS) || \ echo " \033[1;33m[NOTICE]\033[0m Swift aarch64 target stdlib missing. Skipping ui_daemon (ARM64) binary." # ═══════════════════════════════════════════════════════════════════ # x86_64 Binary Compilation Targets # ═══════════════════════════════════════════════════════════════════ # These are invoked by tools/build via `make -C `. # All C/C++ compilation uses clang. # ═══════════════════════════════════════════════════════════════════ # Extract the Verified Boot signing key from vendor config ARK_KEY := $(shell if [ -f vendor/verify/securebuild.ark ]; then \ grep "^ARK-OS-" vendor/verify/securebuild.ark | tr -d '[:space:]'; \ else echo "NO_KEY"; fi) SWIFT_X86_64_SDK := $(CURDIR)/prebuilts/Swift/swift-6.3.2-RELEASE_static-linux-0.1.0/swift-linux-musl/musl-1.2.5.sdk/x86_64 SWIFT_X86_64_LIB := $(SWIFT_X86_64_SDK)/usr/lib/swift_static/linux-static SWIFT_X86_64_SWIFTC := swiftc -O -package-name arkos -static-executable -target x86_64-swift-linux-musl -sdk $(SWIFT_X86_64_SDK) -resource-dir $(SWIFT_X86_64_SDK)/usr/lib/swift_static -I $(SWIFT_X86_64_LIB) -I $(SWIFT_X86_64_LIB)/x86_64 -I system/modules # ── fb_helper.o — Framebuffer ioctl bridge (C → Swift interop) ──── out_staging/fb_helper.o: system/core/fb_helper.c $(X86_CC) -c system/core/fb_helper.c -o out_staging/fb_helper.o # ── arkrt — ArkOS Runtime Daemon (PID 2) ────────────────────────── ARKRT_SRCS := $(shell find arkrt -name "*.swift" | grep -v "\.docc" | grep -v "MetricsTestKit") out_staging/early_init.o: arkrt/early_init.c $(X86_CC) -c arkrt/early_init.c -o out_staging/early_init.o out_staging/graphics_c_built: $(TOOLS)/build_graphics_c.sh $(TOOLS)/build_graphics_c.sh x86_64 "$(CLANG) --target=x86_64-linux-musl --sysroot=$(SWIFT_X86_64_SDK)" out_staging touch out_staging/graphics_c_built out_staging/ark_wayland_server.o: arkrt/ark.display.graphics/ark_wayland_server.c $(X86_CC) -c arkrt/ark.display.graphics/ark_wayland_server.c -o out_staging/ark_wayland_server.o -I arkrt/libdrm -I arkrt/libdrm/include/drm -I arkrt/wayland/src -I arkrt/libinput/src -I arkrt/libxkbcommon/include/xkbcommon out_staging/ark_wayland_client.o: arkrt/ark.display.graphics/ark_wayland_client.c $(X86_CC) -c arkrt/ark.display.graphics/ark_wayland_client.c -o out_staging/ark_wayland_client.o -I arkrt/libdrm -I arkrt/libdrm/include/drm -I arkrt/wayland/src -I arkrt/libinput/src -I arkrt/libxkbcommon/include/xkbcommon out_staging/CSystem.o: arkrt/swift-system/CSystem/shims.c $(X86_CC) -c arkrt/swift-system/CSystem/shims.c -o out_staging/CSystem.o -I arkrt/swift-system/CSystem/include WAYLAND_OBJS_X86 = out_staging/wl_client.o out_staging/wl_os.o out_staging/wl_util.o out_staging/wl_conn.o out_staging/wl_proto.o out_staging/wl_ffi.o out_staging/wl_server.o out_staging/wl_event_loop.o out_staging/wl_shm.o out_staging/xdg_shell.o DRM_OBJS_X86 = out_staging/drm1.o out_staging/drm2.o out_staging/drm3.o out_staging/drm4.o out_staging/drm5.o out_staging/arkrt: $(ARKRT_SRCS) out_staging/early_init.o out_staging/ark_wayland_server.o out_staging/ark_wayland_client.o out_staging/CSystem.o out_staging/ArkFontRobotoBoldData.o out_staging/graphics_c_built $(SWIFT_X86_64_SWIFTC) -I arkrt/wayland/src -I arkrt/libdrm -I arkrt/libdrm/include -I arkrt/libdrm/include/drm -Xcc -fmodule-map-file=arkrt/wayland/src/module.modulemap -Xcc -fmodule-map-file=arkrt/libdrm/module.modulemap -I arkrt/swift-system/CSystem/include -Xcc -fmodule-map-file=arkrt/swift-system/CSystem/include/module.modulemap $(ARKRT_SRCS) out_staging/early_init.o out_staging/ark_wayland_server.o out_staging/ark_wayland_client.o out_staging/CSystem.o out_staging/ArkFontRobotoBoldData.o $(WAYLAND_OBJS_X86) $(DRM_OBJS_X86) -o out_staging/arkrt out_staging/init: system/core/init.c vendor/verify/sha256.c $(X86_CC) -static vendor/verify/sha256.c system/core/init.c \ -Ivendor/verify -DARK_KEY=\""$(ARK_KEY)"\" \ -o out_staging/init # ── Bootloader binaries (BIOS + UEFI) ──────────────────────────── out_staging/bootloader.bin: boot/source/bootloader.asm nasm -f bin boot/source/bootloader.asm -o out_staging/bootloader.bin out_staging/stage2.bin: boot/source/stage2.asm nasm -f bin boot/source/stage2.asm -o out_staging/stage2.bin out_staging/BOOTX64.EFI: boot/source/bootloader.c $(X86_CC) -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol \ -fno-stack-protector -fpic -fshort-wchar -mno-red-zone -DEFI_FUNCTION_WRAPPER \ -c boot/source/bootloader.c -o out_staging/bootloader_uefi.o ld -nostdlib -znocombreloc -T /usr/lib/elf_x86_64_efi.lds -shared -Bsymbolic \ /usr/lib/crt0-efi-x86_64.o out_staging/bootloader_uefi.o \ -o out_staging/bootloader_uefi.so -lgnuefi -lefi -L/usr/lib objcopy -j .text -j .sdata -j .data -j .rodata -j .dynamic -j .dynsym \ -j .rel -j .rela -j .reloc -j .eh_frame \ -O efi-app-x86_64 out_staging/bootloader_uefi.so out_staging/BOOTX64.EFI # ── ui_daemon — Display Compositor ───────────────────────────────── out_staging/system/ui_daemon: system/display/main.swift system/display/splash.swift system/display/wayland_client.swift arkrt/compositor/WireProtocol.swift arkrt/compositor/ArkSocket.swift arkrt/ArkSys/*.swift @mkdir -p out_staging/system @$(SWIFT_X86_64_SWIFTC) \ system/display/main.swift system/display/splash.swift system/display/wayland_client.swift arkrt/compositor/WireProtocol.swift arkrt/compositor/ArkSocket.swift arkrt/ArkSys/ArkSys.swift arkrt/ArkSys/ArkSysFile.swift arkrt/ArkSys/ArkSysTime.swift \ -o out_staging/system/ui_daemon # ── setup_app — Setup / Welcome app ──────────────────────────────── UI_BASIC_SRCS := $(shell find arkrt/ark.ui.basic -name "*.swift" -type f | grep -v "\.docc" | grep -v "ArkGraphicsBackend") arkrt/ark.sys.libc/ArkCInterop.swift arkrt/ark.sys.proc/ArkUtils.swift out_staging/system/ui_test: setup_app/setup_app.swift arkrt/ark.ui.basic/Sources/Backend/GtkBackend.swift $(UI_BASIC_SRCS) out_staging/ArkFontRobotoBoldData.o out_staging/CSystem.o @mkdir -p out_staging/system @$(SWIFT_X86_64_SWIFTC) -I arkrt/swift-system/CSystem/include -Xcc -fmodule-map-file=arkrt/swift-system/CSystem/include/module.modulemap setup_app/setup_app.swift $(UI_BASIC_SRCS) out_staging/CSystem.o -o out_staging/system/ui_test out_staging/ArkFontRobotoBoldData.o: arkrt/ark.display.graphics/ArkFontRobotoBoldData.c @mkdir -p out_staging @$(X86_CC) -O3 -c arkrt/ark.display.graphics/ArkFontRobotoBoldData.c -o out_staging/ArkFontRobotoBoldData.o