Files
LithosAnanake/mk/Kconfig.mk
T

162 lines
7.3 KiB
Makefile

# ==============================================================================
# mk/Kconfig.mk — shared Kconfig bridge for Makefile and Makefile.starkernel
# ==============================================================================
#
# Included by both build systems, after each has finished resolving its own
# ARCH. The two Makefiles canonicalize aarch64 differently (hosted Makefile:
# aarch64 -> arm64, for ARCH_DIR; kernel Makefile: aarch64 -> aarch64, for
# ARCH) -- so rather than this file re-deriving an architecture directory
# name of its own, the including Makefile must set KCONFIG_ARCH_DIR to
# whatever *it* already builds objects under, immediately before the
# `include mk/Kconfig.mk` line.
#
# Config lives per-architecture under build/$(KCONFIG_ARCH_DIR)/ rather than
# a single root .config, because this project's own QEMU acceptance workflow
# builds all three kernel architectures back-to-back in one script, in the
# same working directory -- a shared root .config would desync from whichever
# arch is actually being built the moment any symbol has an arch-conditional
# default. build/ is already gitignored and already per-arch.
#
# Phase 2 status: this bridge is wired but genuinely inert for anyone who
# hasn't opted in. Nothing in either Makefile reads a $(CONFIG_FOO) variable
# yet -- see the `ifneq ($(wildcard $(KCONFIG_CONFIG_FILE)),)` guard below.
# Until a developer runs one of the targets this file defines (menuconfig,
# xconfig, config, oldconfig, a *_defconfig), no build/$(ARCH)/.config exists,
# the guard is false, and this file contributes nothing to a build -- today's
# plain `?=` knobs remain the only thing driving -D flags. Later phases
# repoint specific knob families from $(VAR) to $(CONFIG_VAR) one at a time;
# this file does not change when they do.
ifndef KCONFIG_ARCH_DIR
$(error mk/Kconfig.mk: KCONFIG_ARCH_DIR must be set by the including Makefile before `include mk/Kconfig.mk`)
endif
KCONFIG_TOOLDIR := tools/kconfig
KCONFIG_CONF := $(KCONFIG_TOOLDIR)/conf
KCONFIG_MCONF := $(KCONFIG_TOOLDIR)/mconf
KCONFIG_QCONF := $(KCONFIG_TOOLDIR)/qconf
KCONFIG_ROOT := Kconfig
KCONFIG_BUILD_DIR := build/$(KCONFIG_ARCH_DIR)
KCONFIG_CONFIG_FILE := $(KCONFIG_BUILD_DIR)/.config
KCONFIG_AUTOCONF_FILE := $(KCONFIG_BUILD_DIR)/include/config/auto.conf
KCONFIG_AUTOHEADER_FILE := $(KCONFIG_BUILD_DIR)/include/generated/autoconf.h
KCONFIG_RUSTCCFG_FILE := $(KCONFIG_BUILD_DIR)/include/generated/rustc_cfg
# conf/confdata.c honors these four env vars directly (getenv("KCONFIG_CONFIG")
# / KCONFIG_AUTOCONFIG / KCONFIG_AUTOHEADER / KCONFIG_RUSTCCFG) -- without all
# four set, the split per-symbol files, auto.conf/autoconf.h, and rustc_cfg
# fall back to bare include/config, include/generated relative to $(CURDIR),
# which pollutes the real source tree. Confirmed by observation while
# validating this file -- rustc_cfg is easy to miss since StarForth has no
# Rust code; conf.c writes it unconditionally regardless.
export KCONFIG_CONFIG := $(KCONFIG_CONFIG_FILE)
export KCONFIG_AUTOCONFIG := $(KCONFIG_AUTOCONF_FILE)
export KCONFIG_AUTOHEADER := $(KCONFIG_AUTOHEADER_FILE)
export KCONFIG_RUSTCCFG := $(KCONFIG_RUSTCCFG_FILE)
# Build the vendored host tools on demand. tools/kconfig/Makefile builds each
# frontend independently, so `oldconfig`/`config`/`defconfig`/`menuconfig`
# never pull in qconf's Qt dependency unless xconfig is actually requested.
$(KCONFIG_CONF):
$(MAKE) -C $(KCONFIG_TOOLDIR) conf
$(KCONFIG_MCONF):
$(MAKE) -C $(KCONFIG_TOOLDIR) mconf
$(KCONFIG_QCONF):
$(MAKE) -C $(KCONFIG_TOOLDIR) qconf
.PHONY: menuconfig xconfig config oldconfig savedefconfig
menuconfig: $(KCONFIG_MCONF)
@mkdir -p $(KCONFIG_BUILD_DIR)
$(KCONFIG_MCONF) $(KCONFIG_ROOT)
xconfig: $(KCONFIG_QCONF)
@mkdir -p $(KCONFIG_BUILD_DIR)
$(KCONFIG_QCONF) $(KCONFIG_ROOT)
config: $(KCONFIG_CONF)
@mkdir -p $(KCONFIG_BUILD_DIR)
$(KCONFIG_CONF) $(KCONFIG_ROOT)
oldconfig: $(KCONFIG_CONF)
@mkdir -p $(KCONFIG_BUILD_DIR)
$(KCONFIG_CONF) --oldconfig $(KCONFIG_ROOT)
savedefconfig: $(KCONFIG_CONF)
$(KCONFIG_CONF) --savedefconfig=defconfig.out $(KCONFIG_ROOT)
@echo "Wrote defconfig.out -- review and move into configs/ if it should be kept"
# make hosted_standard_defconfig / make kernel_amd64_defconfig / etc.
# Filename under configs/ matches the target name exactly, same convention
# as the upstream kernel's arch/*/configs/*_defconfig.
%_defconfig: $(KCONFIG_CONF)
@mkdir -p $(KCONFIG_BUILD_DIR)
$(KCONFIG_CONF) --defconfig=configs/$@ $(KCONFIG_ROOT)
# Auto-remake bridge: a genuine `include`, not an order-only prerequisite,
# so Make's native "remake included makefiles, then restart before
# dispatching any -jN jobs" behavior fully serializes "regenerate config"
# before "compile anything" -- for free, with no hand-maintained
# prerequisite list. Deliberately not the include/version.h-style
# order-only pattern (Makefile.starkernel:49-53/656-658), which needed its
# own special-cased -j/clean workaround once already.
#
# Guarded on the config file already existing: until a developer opts in via
# one of the targets above, build/$(ARCH)/.config does not exist, this
# include is skipped entirely, and the bridge contributes zero behavior
# change to a plain `make`/`make clean`. This is what keeps Phase 2 honestly
# inert rather than inert-in-name-only.
KCONFIG_ACTIVE :=
ifneq ($(wildcard $(KCONFIG_CONFIG_FILE)),)
KCONFIG_ACTIVE := 1
$(KCONFIG_AUTOCONF_FILE): $(KCONFIG_CONFIG_FILE) $(KCONFIG_CONF)
@mkdir -p $(KCONFIG_BUILD_DIR)
$(KCONFIG_CONF) --syncconfig $(KCONFIG_ROOT)
include $(KCONFIG_AUTOCONF_FILE)
endif
# ==============================================================================
# Per-knob bridge macros for repointing a Makefile's own $(VAR) from a bare
# historical default to the Kconfig-fed $(CONFIG_VAR), one knob family at a
# time (see the phased cutover in the Kconfig migration plan). Both preserve
# today's behavior exactly when KCONFIG_ACTIVE is unset (no .config yet) --
# in that branch this is just $(VAR) ?= default, same as before the knob was
# ever touched. Command-line/environment overrides of $(VAR) always win
# regardless of which branch fires: Make never lets an in-makefile
# assignment, `?=` or `:=`, override a value already supplied on the command
# line, so `make ROLLING_WINDOW_SIZE=8192` keeps working identically whether
# or not a .config is present.
#
# $(eval $(call kconfig_bool,STRICT_PTR,1))
# -- for Kconfig `bool` symbols; auto.conf writes CONFIG_FOO=y or omits
# the line entirely for n, so this maps y -> 1, anything else -> 0 (the
# C side has always taken 0/1 integers here, never y/n).
#
# $(eval $(call kconfig_int,ROLLING_WINDOW_SIZE,4096))
# -- for Kconfig `int` (and, since auto.conf writes `string` defaults
# unquoted too, `string`-typed numeric-literal symbols like the SSM_*
# thresholds) symbols. $(or ...) covers both "Kconfig inactive" and
# "Kconfig active but this symbol's `depends on` was unmet, so it never
# appears in auto.conf at all" (e.g. TRANSITION_WINDOW_SIZE when
# ENABLE_PIPELINING=n) -- both fall back to the same historical default
# rather than emitting an empty -D value.
define kconfig_bool
ifeq ($(KCONFIG_ACTIVE),1)
$1 := $$(if $$(filter y,$$(CONFIG_$1)),1,0)
else
$1 ?= $2
endif
endef
define kconfig_int
ifeq ($(KCONFIG_ACTIVE),1)
$1 := $$(or $$(CONFIG_$1),$2)
else
$1 ?= $2
endif
endef