From 3ed3f6acfe9e3c265ff4f8133a72eca1ba89a4a2 Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Thu, 23 Apr 2026 19:30:12 +0800 Subject: [PATCH] =?UTF-8?q?CLKS=E6=8B=86=E5=88=86=EF=BC=9A=E7=AC=AC?= =?UTF-8?q?=E4=B8=80=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 266 +++++++++++------- Makefile | 81 +++++- .../c}/include/cleonos_version.h | 1 - clks/Makefile | 47 ++++ clks/include/clks/version.h | 6 + clks/kernel/runtime/syscall.c | 2 +- cmake/check_tools.cmake | 13 +- scripts/menuconfig.py | 150 +++++++--- 8 files changed, 421 insertions(+), 145 deletions(-) rename {common => cleonos/c}/include/cleonos_version.h (71%) create mode 100644 clks/Makefile create mode 100644 clks/include/clks/version.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ea4d7e..132f7d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,20 @@ set(READELF_FOR_TARGET "llvm-readelf" CACHE STRING "readelf tool for limine conf set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable") +set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos") +if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt") + set(_cleonos_enable_default ON) +else() + set(_cleonos_enable_default OFF) +endif() +set(CLEONOS_ENABLE ${_cleonos_enable_default} CACHE BOOL "Enable CLeonOS userland/ramdisk/iso integration") +if(CLEONOS_ENABLE AND NOT EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt") + cl_log_error("CLEONOS_ENABLE=ON but missing ${CLEONOS_SOURCE_DIR}/CMakeLists.txt") +endif() +if(NOT CLEONOS_ENABLE) + cl_log_warn("CLEONOS_ENABLE=OFF, running in CLKS-only build mode") +endif() + set(LIMINE_DIR "limine" CACHE STRING "Limine source directory") set(LIMINE_REPO "https://gh-proxy.com/https://github.com/limine-bootloader/limine.git" CACHE STRING "Limine git repository") set(LIMINE_REF "" CACHE STRING "Optional Limine branch or tag") @@ -108,8 +122,10 @@ set(KERNEL_RUST_LIB "${BUILD_ROOT}/libclks_kernel_rust.a") resolve_tool_with_fallback(CC gcc cc clang) resolve_tool_with_fallback(KERNEL_CXX g++ clang++ x86_64-elf-g++) resolve_tool_with_fallback(LD ld.lld ld) -resolve_tool_with_fallback(USER_CC cc gcc clang) -resolve_tool_with_fallback(USER_LD ld.lld ld) +if(CLEONOS_ENABLE) + resolve_tool_with_fallback(USER_CC cc gcc clang) + resolve_tool_with_fallback(USER_LD ld.lld ld) +endif() resolve_tool_with_fallback(NM llvm-nm x86_64-elf-nm nm) resolve_tool_with_fallback(ADDR2LINE llvm-addr2line x86_64-elf-addr2line addr2line) resolve_tool_with_fallback(OBJCOPY_FOR_TARGET llvm-objcopy x86_64-linux-gnu-objcopy objcopy) @@ -211,6 +227,13 @@ cl_set_bool_cache(CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG ON "Print scheduler t cl_set_bool_cache(CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG ON "Print interrupt ready log after IDT/PIC init") cl_set_bool_cache(CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG ON "Print default shell mode log during boot") +if(NOT CLEONOS_ENABLE) + set(CLEONOS_CLKS_ENABLE_KELF OFF CACHE BOOL "Enable KELF app dispatcher" FORCE) + set(CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC OFF CACHE BOOL "Auto exec /shell/shell.elf on boot" FORCE) + set(CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE OFF CACHE BOOL "Probe /shell/init.cmd during userland init" FORCE) + set(CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE OFF CACHE BOOL "Probe /system apps (elfrunner/memc) during userland init" FORCE) +endif() + cl_bool_to_int(CLEONOS_CLKS_ENABLE_AUDIO CLKS_CFG_AUDIO_INT) cl_bool_to_int(CLEONOS_CLKS_ENABLE_MOUSE CLKS_CFG_MOUSE_INT) cl_bool_to_int(CLEONOS_CLKS_ENABLE_DESKTOP CLKS_CFG_DESKTOP_INT) @@ -267,7 +290,6 @@ set(CFLAGS_COMMON -Wextra -Werror "-I${CMAKE_SOURCE_DIR}/clks/include" - "-I${CMAKE_SOURCE_DIR}/common/include" ) set(CXXFLAGS_COMMON @@ -284,7 +306,6 @@ set(CXXFLAGS_COMMON -Wextra -Werror "-I${CMAKE_SOURCE_DIR}/clks/include" - "-I${CMAKE_SOURCE_DIR}/common/include" ) set(ARCH_CFLAGS @@ -361,7 +382,6 @@ set(USER_CFLAGS -Wextra -Werror "-I${CMAKE_SOURCE_DIR}/cleonos/c/include" - "-I${CMAKE_SOURCE_DIR}/common/include" ) set(USER_CFLAGS_DOOM @@ -377,7 +397,6 @@ set(USER_CFLAGS_DOOM -Wno-sign-compare -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L - "-I${CMAKE_SOURCE_DIR}/common/include" "-I${CMAKE_SOURCE_DIR}/cleonos/third-party/doomgeneric/doomgeneric" "-include" "${CMAKE_SOURCE_DIR}/cleonos/c/apps/doom/doom_shim.h" @@ -404,10 +423,13 @@ if(NOT CLKS_ARCH STREQUAL "x86_64") endif() include("${CMAKE_SOURCE_DIR}/clks/CMakeLists.txt") -include("${CMAKE_SOURCE_DIR}/cleonos/CMakeLists.txt") +if(CLEONOS_ENABLE) + include("${CMAKE_SOURCE_DIR}/cleonos/CMakeLists.txt") +endif() add_custom_target(setup-tools COMMAND ${CMAKE_COMMAND} + "-DCLEONOS_ENABLE=${CLEONOS_ENABLE}" "-DGIT_TOOL=${GIT_TOOL}" "-DTAR_TOOL=${TAR}" "-DXORRISO_TOOL=${XORRISO}" @@ -459,84 +481,88 @@ add_custom_command( -P "${CL_LOG_EMIT_SCRIPT}" ) -add_custom_target(disk-image - COMMAND ${CMAKE_COMMAND} - "-DDISK_IMAGE=${DISK_IMAGE}" - "-DDISK_MB=${CLEONOS_DISK_IMAGE_MB}" - -P "${CMAKE_SOURCE_DIR}/cmake/ensure_disk_image.cmake" - BYPRODUCTS "${DISK_IMAGE}" - VERBATIM -) +if(CLEONOS_ENABLE) + add_custom_target(disk-image + COMMAND ${CMAKE_COMMAND} + "-DDISK_IMAGE=${DISK_IMAGE}" + "-DDISK_MB=${CLEONOS_DISK_IMAGE_MB}" + -P "${CMAKE_SOURCE_DIR}/cmake/ensure_disk_image.cmake" + BYPRODUCTS "${DISK_IMAGE}" + VERBATIM + ) -add_custom_command( - OUTPUT "${ISO_IMAGE}" - COMMAND ${CMAKE_COMMAND} -E rm -rf "${ISO_ROOT}" - COMMAND ${CMAKE_COMMAND} -E make_directory "${ISO_ROOT}/boot/limine" "${ISO_ROOT}/EFI/BOOT" - COMMAND ${CMAKE_COMMAND} -E copy "${KERNEL_ELF}" "${ISO_ROOT}/boot/clks_kernel.elf" - COMMAND ${CMAKE_COMMAND} -E copy "${RAMDISK_IMAGE}" "${ISO_ROOT}/boot/cleonos_ramdisk.tar" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/configs/limine.conf" "${ISO_ROOT}/boot/limine/limine.conf" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/configs/limine.conf" "${ISO_ROOT}/EFI/BOOT/limine.conf" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/configs/limine.conf" "${ISO_ROOT}/limine.conf" - COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-bios.sys" "${ISO_ROOT}/boot/limine/limine-bios.sys" - COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-bios-cd.bin" "${ISO_ROOT}/boot/limine/limine-bios-cd.bin" - COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-uefi-cd.bin" "${ISO_ROOT}/boot/limine/limine-uefi-cd.bin" - COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/BOOTX64.EFI" "${ISO_ROOT}/EFI/BOOT/BOOTX64.EFI" - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/build" - COMMAND ${CMAKE_COMMAND} - "-DNO_COLOR=${NO_COLOR}" - "-DLOG_LEVEL=STEP" - "-DLOG_TEXT=building iso -> ${ISO_IMAGE}" - -P "${CL_LOG_EMIT_SCRIPT}" - COMMAND ${XORRISO} -as mkisofs - -b boot/limine/limine-bios-cd.bin - -no-emul-boot - -boot-load-size 4 - -boot-info-table - --efi-boot boot/limine/limine-uefi-cd.bin - -efi-boot-part - --efi-boot-image - --protective-msdos-label - "${ISO_ROOT}" - -o "${ISO_IMAGE}" - COMMAND ${CMAKE_COMMAND} - "-DNO_COLOR=${NO_COLOR}" - "-DLOG_LEVEL=STEP" - "-DLOG_TEXT=installing limine boot sectors" - -P "${CL_LOG_EMIT_SCRIPT}" - COMMAND "${LIMINE_BIN_DIR_ABS}/limine" bios-install "${ISO_IMAGE}" - COMMAND ${CMAKE_COMMAND} - "-DNO_COLOR=${NO_COLOR}" - "-DLOG_LEVEL=INFO" - "-DLOG_TEXT=iso ready: ${ISO_IMAGE}" - -P "${CL_LOG_EMIT_SCRIPT}" - DEPENDS "${KERNEL_ELF}" "${RAMDISK_IMAGE}" "${CMAKE_SOURCE_DIR}/configs/limine.conf" - VERBATIM -) + add_custom_command( + OUTPUT "${ISO_IMAGE}" + COMMAND ${CMAKE_COMMAND} -E rm -rf "${ISO_ROOT}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${ISO_ROOT}/boot/limine" "${ISO_ROOT}/EFI/BOOT" + COMMAND ${CMAKE_COMMAND} -E copy "${KERNEL_ELF}" "${ISO_ROOT}/boot/clks_kernel.elf" + COMMAND ${CMAKE_COMMAND} -E copy "${RAMDISK_IMAGE}" "${ISO_ROOT}/boot/cleonos_ramdisk.tar" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/configs/limine.conf" "${ISO_ROOT}/boot/limine/limine.conf" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/configs/limine.conf" "${ISO_ROOT}/EFI/BOOT/limine.conf" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/configs/limine.conf" "${ISO_ROOT}/limine.conf" + COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-bios.sys" "${ISO_ROOT}/boot/limine/limine-bios.sys" + COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-bios-cd.bin" "${ISO_ROOT}/boot/limine/limine-bios-cd.bin" + COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-uefi-cd.bin" "${ISO_ROOT}/boot/limine/limine-uefi-cd.bin" + COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/BOOTX64.EFI" "${ISO_ROOT}/EFI/BOOT/BOOTX64.EFI" + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/build" + COMMAND ${CMAKE_COMMAND} + "-DNO_COLOR=${NO_COLOR}" + "-DLOG_LEVEL=STEP" + "-DLOG_TEXT=building iso -> ${ISO_IMAGE}" + -P "${CL_LOG_EMIT_SCRIPT}" + COMMAND ${XORRISO} -as mkisofs + -b boot/limine/limine-bios-cd.bin + -no-emul-boot + -boot-load-size 4 + -boot-info-table + --efi-boot boot/limine/limine-uefi-cd.bin + -efi-boot-part + --efi-boot-image + --protective-msdos-label + "${ISO_ROOT}" + -o "${ISO_IMAGE}" + COMMAND ${CMAKE_COMMAND} + "-DNO_COLOR=${NO_COLOR}" + "-DLOG_LEVEL=STEP" + "-DLOG_TEXT=installing limine boot sectors" + -P "${CL_LOG_EMIT_SCRIPT}" + COMMAND "${LIMINE_BIN_DIR_ABS}/limine" bios-install "${ISO_IMAGE}" + COMMAND ${CMAKE_COMMAND} + "-DNO_COLOR=${NO_COLOR}" + "-DLOG_LEVEL=INFO" + "-DLOG_TEXT=iso ready: ${ISO_IMAGE}" + -P "${CL_LOG_EMIT_SCRIPT}" + DEPENDS "${KERNEL_ELF}" "${RAMDISK_IMAGE}" "${CMAKE_SOURCE_DIR}/configs/limine.conf" + VERBATIM + ) -add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}") -add_dependencies(iso setup-tools setup-limine kernel ramdisk) + add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}") + add_dependencies(iso setup-tools setup-limine kernel ramdisk) -add_custom_target(run - COMMAND ${CMAKE_COMMAND} - "-DNO_COLOR=${NO_COLOR}" - "-DLOG_LEVEL=STEP" - "-DLOG_TEXT=launching qemu run" - -P "${CL_LOG_EMIT_SCRIPT}" - COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=ide,index=0,media=disk" -serial stdio - DEPENDS iso disk-image - USES_TERMINAL -) + add_custom_target(run + COMMAND ${CMAKE_COMMAND} + "-DNO_COLOR=${NO_COLOR}" + "-DLOG_LEVEL=STEP" + "-DLOG_TEXT=launching qemu run" + -P "${CL_LOG_EMIT_SCRIPT}" + COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=ide,index=0,media=disk" -serial stdio + DEPENDS iso disk-image + USES_TERMINAL + ) -add_custom_target(debug - COMMAND ${CMAKE_COMMAND} - "-DNO_COLOR=${NO_COLOR}" - "-DLOG_LEVEL=STEP" - "-DLOG_TEXT=launching qemu debug (-s -S)" - -P "${CL_LOG_EMIT_SCRIPT}" - COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=ide,index=0,media=disk" -serial stdio -s -S - DEPENDS iso disk-image - USES_TERMINAL -) + add_custom_target(debug + COMMAND ${CMAKE_COMMAND} + "-DNO_COLOR=${NO_COLOR}" + "-DLOG_LEVEL=STEP" + "-DLOG_TEXT=launching qemu debug (-s -S)" + -P "${CL_LOG_EMIT_SCRIPT}" + COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=ide,index=0,media=disk" -serial stdio -s -S + DEPENDS iso disk-image + USES_TERMINAL + ) +else() + add_custom_target(clks-default ALL DEPENDS kernel) +endif() add_custom_target(clean-x86 COMMAND ${CMAKE_COMMAND} @@ -568,12 +594,31 @@ add_custom_target(clean-all find_package(Python3 COMPONENTS Interpreter QUIET) if(Python3_Interpreter_FOUND) - add_custom_target(menuconfig - COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" + if(CLEONOS_ENABLE) + add_custom_target(menuconfig + COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" + USES_TERMINAL + ) + add_custom_target(menuconfig-gui + COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui + USES_TERMINAL + ) + else() + add_custom_target(menuconfig + COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --clks-only + USES_TERMINAL + ) + add_custom_target(menuconfig-gui + COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui --clks-only + USES_TERMINAL + ) + endif() + add_custom_target(menuconfig-clks + COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --clks-only USES_TERMINAL ) - add_custom_target(menuconfig-gui - COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui + add_custom_target(menuconfig-gui-clks + COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui --clks-only USES_TERMINAL ) else() @@ -585,18 +630,45 @@ else() COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --gui manually" USES_TERMINAL ) + add_custom_target(menuconfig-clks + COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --clks-only manually" + USES_TERMINAL + ) + add_custom_target(menuconfig-gui-clks + COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --gui --clks-only manually" + USES_TERMINAL + ) endif() -add_custom_target(cleonos-help - COMMAND ${CMAKE_COMMAND} -E echo "CLeonOS CMake build system (x86_64 only)" - COMMAND ${CMAKE_COMMAND} -E echo " cmake -S . -B build-cmake" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target setup" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target userapps" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target iso" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target run" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target debug" - COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target disk-image" -) +if(CLEONOS_ENABLE) + add_custom_target(cleonos-help + COMMAND ${CMAKE_COMMAND} -E echo "CLeonOS CMake build system (x86_64 only)" + COMMAND ${CMAKE_COMMAND} -E echo " CLEONOS_ENABLE=${CLEONOS_ENABLE}" + COMMAND ${CMAKE_COMMAND} -E echo " cmake -S . -B build-cmake" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-clks" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui-clks" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target setup" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target kernel" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target userapps" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target iso" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target run" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target debug" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target disk-image" + ) +else() + add_custom_target(cleonos-help + COMMAND ${CMAKE_COMMAND} -E echo "CLeonOS CMake build system (x86_64 only)" + COMMAND ${CMAKE_COMMAND} -E echo " CLEONOS_ENABLE=${CLEONOS_ENABLE}" + COMMAND ${CMAKE_COMMAND} -E echo " cmake -S . -B build-cmake" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-clks" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui-clks" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target setup" + COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target kernel" + COMMAND ${CMAKE_COMMAND} -E echo " (CLKS-only mode: userapps/iso/run/debug/disk-image are disabled)" + ) +endif() diff --git a/Makefile b/Makefile index 52675e5..21c7a55 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ PYTHON ?= python3 MENUCONFIG_ARGS ?= MENUCONFIG_PRESET ?= DISK_IMAGE_MB ?= +CLEONOS_ENABLE ?= auto ifeq ($(strip $(CMAKE_GENERATOR)),) GEN_ARG := @@ -28,6 +29,32 @@ endif CMAKE_PASSTHROUGH_ARGS := MENUCONFIG_PRESET_ARG := $(if $(strip $(MENUCONFIG_PRESET)),--preset $(MENUCONFIG_PRESET),) +CLEONOS_SOURCE_PRESENT := $(if $(wildcard cleonos/CMakeLists.txt),1,0) + +ifeq ($(strip $(CLEONOS_ENABLE)),auto) +ifeq ($(CLEONOS_SOURCE_PRESENT),1) +CLEONOS_ENABLE_EFFECTIVE := ON +else +CLEONOS_ENABLE_EFFECTIVE := OFF +endif +else +CLEONOS_ENABLE_EFFECTIVE := $(CLEONOS_ENABLE) +endif + +ifneq ($(filter 1 ON on TRUE true YES yes Y y,$(CLEONOS_ENABLE_EFFECTIVE)),) +CLEONOS_ENABLED_BOOL := 1 +CLEONOS_MODE_LABEL := full +else +CLEONOS_ENABLED_BOOL := 0 +CLEONOS_MODE_LABEL := clks-only +endif + +MENUCONFIG_SCOPE_ARG := +ifeq ($(CLEONOS_ENABLED_BOOL),0) +MENUCONFIG_SCOPE_ARG += --clks-only +endif + +CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_ENABLE=$(CLEONOS_ENABLE_EFFECTIVE) ifneq ($(strip $(LIMINE_SKIP_CONFIGURE)),) CMAKE_PASSTHROUGH_ARGS += -DLIMINE_SKIP_CONFIGURE=$(LIMINE_SKIP_CONFIGURE) @@ -57,38 +84,64 @@ ifneq ($(strip $(DISK_IMAGE_MB)),) CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_DISK_IMAGE_MB=$(DISK_IMAGE_MB) endif -.PHONY: all configure reconfigure menuconfig menuconfig-gui setup setup-tools setup-limine kernel userapps ramdisk-root ramdisk disk-image iso run debug clean clean-all help +.PHONY: all configure reconfigure menuconfig menuconfig-gui menuconfig-clks menuconfig-gui-clks setup setup-tools setup-limine kernel userapps ramdisk-root ramdisk disk-image iso run debug clean clean-all help +ifeq ($(CLEONOS_ENABLED_BOOL),1) all: iso +else +all: kernel +endif configure: > @$(CMAKE) -S . -B $(CMAKE_BUILD_DIR) $(GEN_ARG) -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DNO_COLOR=$(NO_COLOR) $(CMAKE_EXTRA_ARGS) $(CMAKE_PASSTHROUGH_ARGS) reconfigure: > @rm -rf $(CMAKE_BUILD_DIR) -> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" +> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)" menuconfig: > @if command -v $(PYTHON) >/dev/null 2>&1; then \ -> $(PYTHON) scripts/menuconfig.py $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> $(PYTHON) scripts/menuconfig.py $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > elif command -v python >/dev/null 2>&1; then \ -> python scripts/menuconfig.py $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> python scripts/menuconfig.py $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > else \ > echo "python3/python not found"; \ > exit 1; \ > fi -> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" +> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)" menuconfig-gui: > @if command -v $(PYTHON) >/dev/null 2>&1; then \ -> $(PYTHON) scripts/menuconfig.py --gui $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> $(PYTHON) scripts/menuconfig.py --gui $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > elif command -v python >/dev/null 2>&1; then \ -> python scripts/menuconfig.py --gui $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> python scripts/menuconfig.py --gui $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > else \ > echo "python3/python not found"; \ > exit 1; \ > fi -> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" +> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)" + +menuconfig-clks: +> @if command -v $(PYTHON) >/dev/null 2>&1; then \ +> $(PYTHON) scripts/menuconfig.py --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> elif command -v python >/dev/null 2>&1; then \ +> python scripts/menuconfig.py --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> else \ +> echo "python3/python not found"; \ +> exit 1; \ +> fi +> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)" + +menuconfig-gui-clks: +> @if command -v $(PYTHON) >/dev/null 2>&1; then \ +> $(PYTHON) scripts/menuconfig.py --gui --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> elif command -v python >/dev/null 2>&1; then \ +> python scripts/menuconfig.py --gui --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ +> else \ +> echo "python3/python not found"; \ +> exit 1; \ +> fi +> @$(MAKE) configure CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" NO_COLOR="$(NO_COLOR)" LIMINE_SKIP_CONFIGURE="$(LIMINE_SKIP_CONFIGURE)" LIMINE_REF="$(LIMINE_REF)" LIMINE_REPO="$(LIMINE_REPO)" LIMINE_DIR="$(LIMINE_DIR)" LIMINE_BIN_DIR="$(LIMINE_BIN_DIR)" OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)" setup: configure > @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target setup @@ -102,6 +155,7 @@ setup-limine: configure kernel: configure > @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target kernel +ifeq ($(CLEONOS_ENABLED_BOOL),1) userapps: configure > @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target userapps @@ -122,6 +176,11 @@ run: configure debug: configure > @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target debug +else +userapps ramdisk-root ramdisk disk-image iso run debug: +> @echo "target '$@' requires CLEONOS_ENABLE=ON and cleonos sources present" +> @exit 1 +endif clean: > @if [ -d "$(CMAKE_BUILD_DIR)" ]; then \ @@ -139,9 +198,12 @@ clean-all: help: > @echo "CLeonOS (CMake-backed wrapper)" +> @echo "Mode: CLEONOS_ENABLE=$(CLEONOS_ENABLE_EFFECTIVE) ($(CLEONOS_MODE_LABEL))" > @echo " make configure" > @echo " make menuconfig" > @echo " make menuconfig-gui" +> @echo " make menuconfig-clks" +> @echo " make menuconfig-gui-clks" > @echo " make setup" > @echo " make userapps" > @echo " make disk-image" @@ -155,6 +217,9 @@ help: > @echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'" > @echo "Direct passthrough is also supported:" > @echo " make run LIMINE_SKIP_CONFIGURE=1" +> @echo "Kernel-only mode:" +> @echo " make kernel CLEONOS_ENABLE=OFF" +> @echo " make -C clks kernel" > @echo "Disk image size example:" > @echo " make run DISK_IMAGE_MB=128" > @echo "Preset examples:" diff --git a/common/include/cleonos_version.h b/cleonos/c/include/cleonos_version.h similarity index 71% rename from common/include/cleonos_version.h rename to cleonos/c/include/cleonos_version.h index 6186e5c..4011f0e 100644 --- a/common/include/cleonos_version.h +++ b/cleonos/c/include/cleonos_version.h @@ -1,7 +1,6 @@ #ifndef CLEONOS_VERSION_H #define CLEONOS_VERSION_H -#define CLKS_VERSION_STRING "1.0.0-alpha" #define CLEONOS_VERSION_STRING "1.0.0-alpha" #endif diff --git a/clks/Makefile b/clks/Makefile new file mode 100644 index 0000000..04c2f06 --- /dev/null +++ b/clks/Makefile @@ -0,0 +1,47 @@ +.RECIPEPREFIX := > +MAKEFLAGS += --no-print-directory + +ROOT_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..) + +.PHONY: all configure reconfigure kernel menuconfig menuconfig-gui setup setup-tools setup-limine clean clean-all help + +all: kernel + +configure: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF configure + +reconfigure: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF reconfigure + +kernel: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF kernel + +menuconfig: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF menuconfig-clks + +menuconfig-gui: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF menuconfig-gui-clks + +setup: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF setup + +setup-tools: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF setup-tools + +setup-limine: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF setup-limine + +clean: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF clean + +clean-all: +> @$(MAKE) -C "$(ROOT_DIR)" CLEONOS_ENABLE=OFF clean-all + +help: +> @echo "CLKS standalone wrapper" +> @echo " make -C clks kernel" +> @echo " make -C clks menuconfig" +> @echo " make -C clks menuconfig-gui" +> @echo " make -C clks configure" +> @echo " make -C clks clean" +> @echo " make -C clks clean-all" diff --git a/clks/include/clks/version.h b/clks/include/clks/version.h new file mode 100644 index 0000000..56e00bc --- /dev/null +++ b/clks/include/clks/version.h @@ -0,0 +1,6 @@ +#ifndef CLKS_VERSION_H +#define CLKS_VERSION_H + +#define CLKS_VERSION_STRING "1.0.0-alpha" + +#endif diff --git a/clks/kernel/runtime/syscall.c b/clks/kernel/runtime/syscall.c index 7b7f2f2..0c13046 100644 --- a/clks/kernel/runtime/syscall.c +++ b/clks/kernel/runtime/syscall.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include /* Yes, this file is a syscall kitchen sink and nobody is pretending otherwise. */ diff --git a/cmake/check_tools.cmake b/cmake/check_tools.cmake index e5a266b..8b745a6 100644 --- a/cmake/check_tools.cmake +++ b/cmake/check_tools.cmake @@ -20,10 +20,11 @@ function(require_tool TOOL_VALUE) endfunction() cl_log_step("checking host tools") +if(NOT DEFINED CLEONOS_ENABLE) + set(CLEONOS_ENABLE ON) +endif() require_tool("${GIT_TOOL}") -require_tool("${TAR_TOOL}") -require_tool("${XORRISO_TOOL}") require_tool("${CC_TOOL}") require_tool("${LD_TOOL}") require_tool("${OBJCOPY_TOOL}") @@ -31,10 +32,14 @@ require_tool("${OBJDUMP_TOOL}") require_tool("${READELF_TOOL}") require_tool("${NM_TOOL}") require_tool("${ADDR2LINE_TOOL}") -require_tool("${USER_CC_TOOL}") -require_tool("${USER_LD_TOOL}") require_tool("${RUSTC_TOOL}") require_tool("${MAKE_TOOL}") require_tool("${SH_TOOL}") +if(CLEONOS_ENABLE) + require_tool("${TAR_TOOL}") + require_tool("${XORRISO_TOOL}") + require_tool("${USER_CC_TOOL}") + require_tool("${USER_LD_TOOL}") +endif() cl_log_info("required tools are available") diff --git a/scripts/menuconfig.py b/scripts/menuconfig.py index 155f6ad..4aef2b7 100644 --- a/scripts/menuconfig.py +++ b/scripts/menuconfig.py @@ -5,6 +5,10 @@ CLeonOS menuconfig Interactive feature selector that writes: - configs/menuconfig/.config.json - configs/menuconfig/config.cmake + - configs/menuconfig/.config.clks.json + - configs/menuconfig/config.clks.cmake + - configs/menuconfig/.config.cleonos.json + - configs/menuconfig/config.cleonos.cmake Design: - CLKS options come from configs/menuconfig/clks_features.json @@ -44,6 +48,10 @@ MENUCONFIG_DIR = ROOT_DIR / "configs" / "menuconfig" CLKS_FEATURES_PATH = MENUCONFIG_DIR / "clks_features.json" CONFIG_JSON_PATH = MENUCONFIG_DIR / ".config.json" CONFIG_CMAKE_PATH = MENUCONFIG_DIR / "config.cmake" +CONFIG_CLKS_JSON_PATH = MENUCONFIG_DIR / ".config.clks.json" +CONFIG_CLEONOS_JSON_PATH = MENUCONFIG_DIR / ".config.cleonos.json" +CONFIG_CLKS_CMAKE_PATH = MENUCONFIG_DIR / "config.clks.cmake" +CONFIG_CLEONOS_CMAKE_PATH = MENUCONFIG_DIR / "config.cleonos.cmake" @dataclass(frozen=True) @@ -388,11 +396,11 @@ def discover_user_apps() -> List[OptionItem]: return options -def load_previous_values() -> Dict[str, int]: - if not CONFIG_JSON_PATH.exists(): +def _load_values_from_json(path: Path) -> Dict[str, int]: + if not path.exists(): return {} try: - raw = json.loads(CONFIG_JSON_PATH.read_text(encoding="utf-8")) + raw = json.loads(path.read_text(encoding="utf-8")) except Exception: return {} @@ -407,6 +415,16 @@ def load_previous_values() -> Dict[str, int]: return out +def load_previous_values(include_user: bool) -> Dict[str, int]: + out: Dict[str, int] = {} + # Merge order: legacy combined -> split CLKS -> split CLeonOS. + out.update(_load_values_from_json(CONFIG_JSON_PATH)) + out.update(_load_values_from_json(CONFIG_CLKS_JSON_PATH)) + if include_user: + out.update(_load_values_from_json(CONFIG_CLEONOS_JSON_PATH)) + return out + + def init_values(options: Iterable[OptionItem], previous: Dict[str, int], use_defaults: bool) -> Dict[str, int]: values: Dict[str, int] = {} for item in options: @@ -1368,12 +1386,15 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List total_items = len(clks_options) + len(user_options) total_on = clks_on + user_on - items = [ - f"CLKS features ({clks_on}/{len(clks_options)} enabled)", - f"User apps ({user_on}/{len(user_options)} enabled)", - "Save and Exit", - "Quit without Saving", + menu_entries: List[Tuple[str, str]] = [ + ("clks", f"CLKS features ({clks_on}/{len(clks_options)} enabled)"), ] + if user_options: + menu_entries.append(("user", f"User apps ({user_on}/{len(user_options)} enabled)")) + else: + menu_entries.append(("user-disabled", "User apps (CLKS-only mode)")) + menu_entries.append(("save", "Save and Exit")) + menu_entries.append(("quit", "Quit without Saving")) if h < 12 or w < 58: _safe_addnstr(stdscr, 0, 0, "Terminal too small for menuconfig (need >= 58x12).", theme["status_warn"]) @@ -1387,7 +1408,7 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List _draw_box(stdscr, 2, 0, h - 5, w, "Main", theme["panel_border"], theme["panel_title"]) base = 4 - for i, text in enumerate(items): + for i, (_action, text) in enumerate(menu_entries): prefix = ">" if i == selected else " " row_text = f"{prefix} {text}" attr = theme["selected"] if i == selected else theme["value_label"] @@ -1406,7 +1427,10 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List ) _safe_addnstr(stdscr, h - 2, 0, " Arrows/jk move Enter select s save q quit ", theme["help"]) - _safe_addnstr(stdscr, h - 1, 0, " Tip: open CLKS/USER section then use Space to toggle options. ", theme["help"]) + if user_options: + _safe_addnstr(stdscr, h - 1, 0, " Tip: open CLKS/USER section then use Space to toggle options. ", theme["help"]) + else: + _safe_addnstr(stdscr, h - 1, 0, " Tip: CLKS-only mode, open CLKS section then use Space to toggle options. ", theme["help"]) stdscr.refresh() key = stdscr.getch() @@ -1416,20 +1440,23 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List if key in (ord("s"), ord("S")): return True if key in (curses.KEY_UP, ord("k"), ord("K")): - selected = (selected - 1) % len(items) + selected = (selected - 1) % len(menu_entries) continue if key in (curses.KEY_DOWN, ord("j"), ord("J")): - selected = (selected + 1) % len(items) + selected = (selected + 1) % len(menu_entries) continue if key in (curses.KEY_ENTER, 10, 13): - if selected == 0: + action = menu_entries[selected][0] + if action == "clks": _run_ncurses_grouped_section(stdscr, theme, "CLKS", clks_options, all_options, values) - elif selected == 1: + elif action == "user": _run_ncurses_section(stdscr, theme, "USER", user_options, all_options, values) - elif selected == 2: + elif action == "save": return True - else: + elif action == "quit": return False + else: + continue continue @@ -1501,7 +1528,10 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti header_title.setFont(header_font) root_layout.addWidget(header_title) - root_layout.addWidget(QtWidgets.QLabel("Window mode (PySide): configure CLKS features and user apps, then save.")) + if user_options: + root_layout.addWidget(QtWidgets.QLabel("Window mode (PySide): configure CLKS features and user apps, then save.")) + else: + root_layout.addWidget(QtWidgets.QLabel("Window mode (PySide): CLKS-only mode (user app options unavailable).")) summary_label = QtWidgets.QLabel("") root_layout.addWidget(summary_label) @@ -1743,9 +1773,10 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti for group_name, group_items in clks_groups: clks_tabs.addTab(_SectionPanel(f"CLKS Features / {group_name}", group_items), group_name) - user_panel = _SectionPanel("User Apps", user_options) tabs.addTab(clks_panel, "CLKS") - tabs.addTab(user_panel, "USER") + if user_options: + user_panel = _SectionPanel("User Apps", user_options) + tabs.addTab(user_panel, "USER") update_summary() footer = QtWidgets.QHBoxLayout() @@ -1777,31 +1808,31 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti return result["save"] -def write_outputs(all_values: Dict[str, int], ordered_options: List[OptionItem]) -> None: - MENUCONFIG_DIR.mkdir(parents=True, exist_ok=True) - +def _write_json_config(path: Path, values: Dict[str, int], options: List[OptionItem]) -> None: output_values: Dict[str, object] = {} - for item in ordered_options: - if item.key not in all_values: + for item in options: + if item.key not in values: continue - value = normalize_tri(all_values[item.key], item.default, item.kind) + value = normalize_tri(values[item.key], item.default, item.kind) if item.kind == "bool": output_values[item.key] = value == TRI_Y else: output_values[item.key] = tri_char(value) - CONFIG_JSON_PATH.write_text( + path.write_text( json.dumps(output_values, ensure_ascii=True, indent=2, sort_keys=True) + "\n", encoding="utf-8", ) + +def _write_cmake_config(path: Path, values: Dict[str, int], options: List[OptionItem], loaded_var: str) -> None: lines = [ "# Auto-generated by scripts/menuconfig.py", "# Do not edit manually unless you know what you are doing.", - 'set(CLEONOS_MENUCONFIG_LOADED ON CACHE BOOL "CLeonOS menuconfig loaded" FORCE)', + f'set({loaded_var} ON CACHE BOOL "CLeonOS menuconfig loaded" FORCE)', ] - for item in ordered_options: - value = normalize_tri(all_values.get(item.key, item.default), item.default, item.kind) + for item in options: + value = normalize_tri(values.get(item.key, item.default), item.default, item.kind) if item.kind == "bool": cmake_value = "ON" if value == TRI_Y else "OFF" lines.append(f'set({item.key} {cmake_value} CACHE BOOL "{item.title}" FORCE)') @@ -1813,6 +1844,39 @@ def write_outputs(all_values: Dict[str, int], ordered_options: List[OptionItem]) f'CACHE BOOL "{item.title} enabled(y|m)" FORCE)' ) + path.write_text("\n".join(lines) + "\n", encoding="utf-8") + + +def write_outputs(all_values: Dict[str, int], clks_options: List[OptionItem], user_options: List[OptionItem]) -> None: + MENUCONFIG_DIR.mkdir(parents=True, exist_ok=True) + ordered_options = clks_options + user_options + + _write_json_config(CONFIG_JSON_PATH, all_values, ordered_options) + _write_json_config(CONFIG_CLKS_JSON_PATH, all_values, clks_options) + _write_cmake_config(CONFIG_CLKS_CMAKE_PATH, all_values, clks_options, "CLEONOS_MENUCONFIG_CLKS_LOADED") + + if user_options: + _write_json_config(CONFIG_CLEONOS_JSON_PATH, all_values, user_options) + _write_cmake_config( + CONFIG_CLEONOS_CMAKE_PATH, + all_values, + user_options, + "CLEONOS_MENUCONFIG_CLEONOS_LOADED", + ) + else: + if CONFIG_CLEONOS_JSON_PATH.exists(): + CONFIG_CLEONOS_JSON_PATH.unlink() + if CONFIG_CLEONOS_CMAKE_PATH.exists(): + CONFIG_CLEONOS_CMAKE_PATH.unlink() + + # Backward-compatible aggregator for existing CMake include path. + lines = [ + "# Auto-generated by scripts/menuconfig.py", + "# Backward-compatible aggregate include.", + 'set(CLEONOS_MENUCONFIG_LOADED ON CACHE BOOL "CLeonOS menuconfig loaded" FORCE)', + 'include("${CMAKE_CURRENT_LIST_DIR}/config.clks.cmake" OPTIONAL)', + 'include("${CMAKE_CURRENT_LIST_DIR}/config.cleonos.cmake" OPTIONAL)', + ] CONFIG_CMAKE_PATH.write_text("\n".join(lines) + "\n", encoding="utf-8") @@ -1826,22 +1890,29 @@ def show_summary(clks_options: List[OptionItem], user_options: List[OptionItem], print() print("========== CLeonOS menuconfig ==========") print(f"1) CLKS features : on={clks_on} m={clks_m} total={len(clks_options)}") - print(f"2) User features : on={user_on} m={user_m} total={len(user_options)}") + if user_options: + print(f"2) User features : on={user_on} m={user_m} total={len(user_options)}") + else: + print("2) User features : unavailable (CLKS-only mode)") print("s) Save and exit") print("q) Quit without saving") def interactive_menu(clks_options: List[OptionItem], user_options: List[OptionItem], values: Dict[str, int]) -> bool: all_options = clks_options + user_options + has_user = len(user_options) > 0 while True: show_summary(clks_options, user_options, values) choice = input("Select> ").strip().lower() if choice == "1": grouped_section_loop("CLKS", clks_options, all_options, values) continue - if choice == "2": + if choice == "2" and has_user: section_loop("USER", user_options, all_options, values) continue + if choice == "2" and not has_user: + print("user features unavailable in CLKS-only mode") + continue if choice in {"s", "save"}: return True if choice in {"q", "quit"}: @@ -1870,6 +1941,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--non-interactive", action="store_true", help="save config without opening interactive menu") parser.add_argument("--plain", action="store_true", help="use legacy plain-text menu instead of ncurses") parser.add_argument("--gui", action="store_true", help="use GUI window mode (PySide)") + parser.add_argument("--clks-only", action="store_true", help="only expose CLKS options and emit CLKS-only config") parser.add_argument( "--preset", choices=["full", "minimal", "dev"], @@ -1892,10 +1964,13 @@ def main() -> int: raise RuntimeError("--gui and --plain cannot be used together") clks_options = load_clks_options() - user_options = discover_user_apps() + clks_only_mode = args.clks_only or not APPS_DIR.exists() + if clks_only_mode and not args.clks_only: + print(f"menuconfig: cleonos app directory not found, switching to CLKS-only mode ({APPS_DIR})") + user_options = [] if clks_only_mode else discover_user_apps() all_options = clks_options + user_options - previous = load_previous_values() + previous = load_previous_values(include_user=not clks_only_mode) values = init_values(all_options, previous, use_defaults=args.defaults) if args.preset: @@ -1921,9 +1996,16 @@ def main() -> int: return 0 final_eval = evaluate_config(all_options, values) - write_outputs(final_eval.effective, all_options) + write_outputs(final_eval.effective, clks_options, user_options) print(f"menuconfig: wrote {CONFIG_JSON_PATH}") print(f"menuconfig: wrote {CONFIG_CMAKE_PATH}") + print(f"menuconfig: wrote {CONFIG_CLKS_JSON_PATH}") + print(f"menuconfig: wrote {CONFIG_CLKS_CMAKE_PATH}") + if user_options: + print(f"menuconfig: wrote {CONFIG_CLEONOS_JSON_PATH}") + print(f"menuconfig: wrote {CONFIG_CLEONOS_CMAKE_PATH}") + else: + print("menuconfig: CLeonOS app config skipped (CLKS-only mode)") return 0