# port.mk - Shared rules for MontaukOS ports. # # A port builds against a MontaukOS checkout (the SDK) and produces an app # bundle in $(OUTDIR)/apps// containing: # # .elf the binary # manifest.toml launcher metadata (name, binary, icon, category) # .svg the launcher icon # .port marker so the OS release step can tell ports from # in-tree apps (see MontaukOS scripts/install_apps.sh) # # The desktop readdirs 0:/apps/ at runtime and parses each manifest.toml, so a # bundle dropped into the ramdisk needs no changes anywhere in the OS tree. # # A port Makefile sets PORT_NAME, PORT_ICON and its own sources/flags, then # includes this file and uses $(BUNDLE_DIR) as its link target directory. MAKEFLAGS += -rR .SUFFIXES: # This file defines rules before the including Makefile does, so pin the # default goal rather than letting the first bundle rule claim it. .DEFAULT_GOAL := all # ==== Repo root ======================================================= # Derived from this file's own location so a port builds the same whether it # is invoked from the top-level Makefile or directly with `make -C /`, # and regardless of how deeply categories nest it. PORT_MK_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) MTKPORTS_ROOT := $(abspath $(PORT_MK_DIR)/..) # ==== SDK location ==================================================== # Ports build against a live MontaukOS checkout rather than a copied # sysroot, so libc/header changes are picked up without a sync step. MONTAUKOS ?= $(HOME)/dev/MontaukOS ifeq ($(wildcard $(MONTAUKOS)/programs/link.ld),) $(error MontaukOS tree not found at $(MONTAUKOS). Pass MONTAUKOS=/path/to/MontaukOS) endif # ==== Toolchain ======================================================= TOOLCHAIN_PREFIX := $(MONTAUKOS)/toolchain/local/bin/x86_64-montauk- ifeq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),) $(error x86_64-montauk toolchain not found. Run $(MONTAUKOS)/toolchain/build-montauk-toolchain.sh first) endif CC := $(TOOLCHAIN_PREFIX)gcc CXX := $(TOOLCHAIN_PREFIX)g++ AR := $(TOOLCHAIN_PREFIX)ar LD := $(TOOLCHAIN_PREFIX)gcc # ==== SDK paths ======================================================= SDK_INC := $(MONTAUKOS)/programs/include SDK_LIBC_INC:= $(MONTAUKOS)/programs/include/libc SDK_LIB := $(MONTAUKOS)/programs/lib SDK_LINK_LD := $(MONTAUKOS)/programs/link.ld LIBC_A := $(SDK_LIB)/libc/liblibc.a LIBLOADER_A := $(SDK_LIB)/libloader/liblibloader.a LIBTLS_A := $(SDK_LIB)/tls/libtls.a LIBBEARSSL_A:= $(SDK_LIB)/bearssl/libbearssl.a LIBJPEG_A := $(SDK_LIB)/libjpeg/libjpeg.a # The kernel ABI version this port is being built against. Recorded in the # bundle so a stale port can be spotted after a syscall/ABI bump rather than # crashing mysteriously at runtime. SDK_API_VERSION := $(shell sed -n 's/.*apiVersion = \([0-9]\+\);.*/\1/p' \ $(MONTAUKOS)/kernel/src/Api/Info.hpp 2>/dev/null | head -1) # ==== Output ========================================================== OUTDIR ?= $(MTKPORTS_ROOT)/out BUNDLE_DIR := $(OUTDIR)/apps/$(PORT_NAME) OBJDIR ?= obj TARGET := $(BUNDLE_DIR)/$(PORT_NAME).elf # ==== Common flags ==================================================== # Mirrors the in-tree convention: freestanding, no stdlib, linked with the # shared program link script. PORT_CFLAGS_COMMON := \ -g -O2 -pipe \ -ffreestanding \ -fno-stack-protector \ -fno-stack-check \ -ffunction-sections \ -fdata-sections \ -msse \ -msse2 \ -isystem $(SDK_LIBC_INC) \ -I $(SDK_INC) PORT_LDFLAGS_COMMON := \ -nostdlib \ -Wl,--gc-sections \ -T $(SDK_LINK_LD) # ==== Bundle assembly ================================================= # Ports depend on $(BUNDLE_FILES) to get manifest + icon + marker staged # alongside the ELF their link rule produces. BUNDLE_FILES := $(BUNDLE_DIR)/manifest.toml $(BUNDLE_DIR)/.port ifneq ($(PORT_ICON),) BUNDLE_FILES += $(BUNDLE_DIR)/$(PORT_ICON) endif $(BUNDLE_DIR)/manifest.toml: manifest.toml | $(BUNDLE_DIR) cp $< $@ $(BUNDLE_DIR)/$(PORT_ICON): $(PORT_ICON) | $(BUNDLE_DIR) cp $< $@ # Marker file consumed by the MontaukOS release step to prune ports from a # base ISO. Carries the ABI version so mismatches are diagnosable. $(BUNDLE_DIR)/.port: Makefile | $(BUNDLE_DIR) printf 'port = "%s"\napi_version = "%s"\n' '$(PORT_NAME)' '$(SDK_API_VERSION)' > $@ $(BUNDLE_DIR): mkdir -p $@ .PHONY: bundle bundle: $(TARGET) $(BUNDLE_FILES) .PHONY: clean-bundle clean-bundle: rm -rf $(OBJDIR) $(BUNDLE_DIR)