This commit is contained in:
2026-04-24 19:24:04 +08:00
parent 89cf6b030c
commit 78fdc87366
11 changed files with 1572 additions and 1105 deletions

View File

@@ -1,208 +1,208 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(CLeonOS NONE) project(CLeonOS NONE)
# User-configurable toolchain and tool variables (Makefile-compatible defaults). # User-configurable toolchain and tool variables (Makefile-compatible defaults).
set(NO_COLOR 0 CACHE STRING "Disable colored log output when set to 1") set(NO_COLOR 0 CACHE STRING "Disable colored log output when set to 1")
include("${CMAKE_SOURCE_DIR}/cmake/log.cmake") include("${CMAKE_SOURCE_DIR}/cmake/log.cmake")
set(CL_LOG_EMIT_SCRIPT "${CMAKE_SOURCE_DIR}/cmake/log_emit.cmake") set(CL_LOG_EMIT_SCRIPT "${CMAKE_SOURCE_DIR}/cmake/log_emit.cmake")
set(CC "x86_64-elf-gcc" CACHE STRING "Kernel C compiler") set(CC "x86_64-elf-gcc" CACHE STRING "Kernel C compiler")
set(KERNEL_CXX "g++" CACHE STRING "Kernel C++ compiler") set(KERNEL_CXX "g++" CACHE STRING "Kernel C++ compiler")
set(LD "x86_64-elf-ld" CACHE STRING "Kernel linker") set(LD "x86_64-elf-ld" CACHE STRING "Kernel linker")
set(USER_CC "cc" CACHE STRING "User-space C compiler") set(USER_CC "cc" CACHE STRING "User-space C compiler")
set(USER_LD "ld" CACHE STRING "User-space linker") set(USER_LD "ld" CACHE STRING "User-space linker")
set(RUSTC "rustc" CACHE STRING "Rust compiler") set(RUSTC "rustc" CACHE STRING "Rust compiler")
set(NM "nm" CACHE STRING "nm executable") set(NM "nm" CACHE STRING "nm executable")
set(ADDR2LINE "addr2line" CACHE STRING "addr2line executable") set(ADDR2LINE "addr2line" CACHE STRING "addr2line executable")
set(XORRISO "xorriso" CACHE STRING "xorriso executable") set(XORRISO "xorriso" CACHE STRING "xorriso executable")
set(TAR "tar" CACHE STRING "tar executable") set(TAR "tar" CACHE STRING "tar executable")
set(GIT_TOOL "git" CACHE STRING "git executable") set(GIT_TOOL "git" CACHE STRING "git executable")
set(MAKE_TOOL "make" CACHE STRING "make executable") set(MAKE_TOOL "make" CACHE STRING "make executable")
set(SH_TOOL "sh" CACHE STRING "POSIX shell executable") set(SH_TOOL "sh" CACHE STRING "POSIX shell executable")
set(OBJCOPY_FOR_TARGET "llvm-objcopy" CACHE STRING "objcopy tool for limine configure") set(OBJCOPY_FOR_TARGET "llvm-objcopy" CACHE STRING "objcopy tool for limine configure")
set(OBJDUMP_FOR_TARGET "llvm-objdump" CACHE STRING "objdump tool for limine configure") set(OBJDUMP_FOR_TARGET "llvm-objdump" CACHE STRING "objdump tool for limine configure")
set(READELF_FOR_TARGET "llvm-readelf" CACHE STRING "readelf tool for limine configure") set(READELF_FOR_TARGET "llvm-readelf" CACHE STRING "readelf tool for limine configure")
set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable") set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable")
set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos") set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos")
if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt") if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt")
set(_cleonos_enable_default ON) set(_cleonos_enable_default ON)
else() else()
set(_cleonos_enable_default OFF) set(_cleonos_enable_default OFF)
endif() endif()
set(CLEONOS_ENABLE ${_cleonos_enable_default} CACHE BOOL "Enable CLeonOS userland/ramdisk/iso integration") 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") if(CLEONOS_ENABLE AND NOT EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt")
cl_log_error("CLEONOS_ENABLE=ON but missing ${CLEONOS_SOURCE_DIR}/CMakeLists.txt") cl_log_error("CLEONOS_ENABLE=ON but missing ${CLEONOS_SOURCE_DIR}/CMakeLists.txt")
endif() endif()
if(NOT CLEONOS_ENABLE) if(NOT CLEONOS_ENABLE)
cl_log_warn("CLEONOS_ENABLE=OFF, running in CLKS-only build mode") cl_log_warn("CLEONOS_ENABLE=OFF, running in CLKS-only build mode")
endif() endif()
set(LIMINE_DIR "limine" CACHE STRING "Limine source directory") 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_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") set(LIMINE_REF "" CACHE STRING "Optional Limine branch or tag")
set(LIMINE_BIN_DIR "${LIMINE_DIR}/bin" CACHE STRING "Limine bin directory") set(LIMINE_BIN_DIR "${LIMINE_DIR}/bin" CACHE STRING "Limine bin directory")
set(LIMINE_CONFIGURE_FLAGS "--enable-bios-cd --enable-uefi-cd --enable-uefi-x86-64" CACHE STRING "Limine configure flags") set(LIMINE_CONFIGURE_FLAGS "--enable-bios-cd --enable-uefi-cd --enable-uefi-x86-64" CACHE STRING "Limine configure flags")
set(LIMINE_SKIP_CONFIGURE 0 CACHE BOOL "Skip Limine configure step") set(LIMINE_SKIP_CONFIGURE 0 CACHE BOOL "Skip Limine configure step")
function(resolve_path INPUT_PATH OUTPUT_VAR) function(resolve_path INPUT_PATH OUTPUT_VAR)
if(IS_ABSOLUTE "${INPUT_PATH}") if(IS_ABSOLUTE "${INPUT_PATH}")
set(${OUTPUT_VAR} "${INPUT_PATH}" PARENT_SCOPE) set(${OUTPUT_VAR} "${INPUT_PATH}" PARENT_SCOPE)
else() else()
set(${OUTPUT_VAR} "${CMAKE_SOURCE_DIR}/${INPUT_PATH}" PARENT_SCOPE) set(${OUTPUT_VAR} "${CMAKE_SOURCE_DIR}/${INPUT_PATH}" PARENT_SCOPE)
endif() endif()
endfunction() endfunction()
function(resolve_tool_with_fallback VAR_NAME) function(resolve_tool_with_fallback VAR_NAME)
set(_fallbacks ${ARGN}) set(_fallbacks ${ARGN})
set(_requested "${${VAR_NAME}}") set(_requested "${${VAR_NAME}}")
if("${_requested}" STREQUAL "") if("${_requested}" STREQUAL "")
cl_log_error("empty tool variable: ${VAR_NAME}") cl_log_error("empty tool variable: ${VAR_NAME}")
endif() endif()
if(IS_ABSOLUTE "${_requested}") if(IS_ABSOLUTE "${_requested}")
if(NOT EXISTS "${_requested}") if(NOT EXISTS "${_requested}")
cl_log_error("${VAR_NAME} not found: ${_requested}") cl_log_error("${VAR_NAME} not found: ${_requested}")
endif() endif()
set(_resolved "${_requested}") set(_resolved "${_requested}")
else() else()
unset(_requested_path CACHE) unset(_requested_path CACHE)
unset(_requested_path) unset(_requested_path)
find_program(_requested_path NAMES "${_requested}") find_program(_requested_path NAMES "${_requested}")
if(_requested_path) if(_requested_path)
set(_resolved "${_requested_path}") set(_resolved "${_requested_path}")
else() else()
set(_resolved "") set(_resolved "")
foreach(_cand IN LISTS _fallbacks) foreach(_cand IN LISTS _fallbacks)
unset(_cand_path CACHE) unset(_cand_path CACHE)
unset(_cand_path) unset(_cand_path)
find_program(_cand_path NAMES "${_cand}") find_program(_cand_path NAMES "${_cand}")
if(_cand_path) if(_cand_path)
cl_log_warn("${VAR_NAME} '${_requested}' not found; fallback to '${_cand}'") cl_log_warn("${VAR_NAME} '${_requested}' not found; fallback to '${_cand}'")
set(_resolved "${_cand_path}") set(_resolved "${_cand_path}")
break() break()
endif() endif()
endforeach() endforeach()
if("${_resolved}" STREQUAL "") if("${_resolved}" STREQUAL "")
cl_log_error("${VAR_NAME} tool not found: '${_requested}', fallbacks='${_fallbacks}'") cl_log_error("${VAR_NAME} tool not found: '${_requested}', fallbacks='${_fallbacks}'")
endif() endif()
endif() endif()
endif() endif()
get_property(_help CACHE "${VAR_NAME}" PROPERTY HELPSTRING) get_property(_help CACHE "${VAR_NAME}" PROPERTY HELPSTRING)
if("${_help}" STREQUAL "") if("${_help}" STREQUAL "")
set(_help "tool path/name") set(_help "tool path/name")
endif() endif()
set(${VAR_NAME} "${_resolved}" CACHE STRING "${_help}" FORCE) set(${VAR_NAME} "${_resolved}" CACHE STRING "${_help}" FORCE)
set(${VAR_NAME} "${_resolved}" PARENT_SCOPE) set(${VAR_NAME} "${_resolved}" PARENT_SCOPE)
endfunction() endfunction()
set(BUILD_ROOT "${CMAKE_SOURCE_DIR}/build/x86_64") set(BUILD_ROOT "${CMAKE_SOURCE_DIR}/build/x86_64")
set(OBJ_ROOT "${BUILD_ROOT}/obj") set(OBJ_ROOT "${BUILD_ROOT}/obj")
set(ISO_ROOT "${BUILD_ROOT}/iso_root") set(ISO_ROOT "${BUILD_ROOT}/iso_root")
set(RAMDISK_ROOT "${BUILD_ROOT}/ramdisk_root") set(RAMDISK_ROOT "${BUILD_ROOT}/ramdisk_root")
set(KERNEL_ELF "${BUILD_ROOT}/clks_kernel.elf") set(KERNEL_ELF "${BUILD_ROOT}/clks_kernel.elf")
set(RAMDISK_IMAGE "${BUILD_ROOT}/cleonos_ramdisk.tar") set(RAMDISK_IMAGE "${BUILD_ROOT}/cleonos_ramdisk.tar")
set(DISK_IMAGE "${BUILD_ROOT}/cleonos_disk.img") set(DISK_IMAGE "${BUILD_ROOT}/cleonos_disk.img")
set(CLEONOS_DISK_IMAGE_MB "64" CACHE STRING "Default runtime disk image size in MB") set(CLEONOS_DISK_IMAGE_MB "64" CACHE STRING "Default runtime disk image size in MB")
set(ISO_IMAGE "${CMAKE_SOURCE_DIR}/build/CLeonOS-x86_64.iso") set(ISO_IMAGE "${CMAKE_SOURCE_DIR}/build/CLeonOS-x86_64.iso")
set(KERNEL_SYMBOLS_FILE "${BUILD_ROOT}/kernel.sym") set(KERNEL_SYMBOLS_FILE "${BUILD_ROOT}/kernel.sym")
set(USER_BUILD_ROOT "${BUILD_ROOT}/user") set(USER_BUILD_ROOT "${BUILD_ROOT}/user")
set(USER_OBJ_ROOT "${USER_BUILD_ROOT}/obj") set(USER_OBJ_ROOT "${USER_BUILD_ROOT}/obj")
set(USER_APP_DIR "${USER_BUILD_ROOT}/apps") set(USER_APP_DIR "${USER_BUILD_ROOT}/apps")
set(USER_LIB_DIR "${USER_BUILD_ROOT}/lib") set(USER_LIB_DIR "${USER_BUILD_ROOT}/lib")
set(USER_RUST_LIB "${USER_LIB_DIR}/libcleonos_user_rust.a") set(USER_RUST_LIB "${USER_LIB_DIR}/libcleonos_user_rust.a")
set(KERNEL_RUST_LIB "${BUILD_ROOT}/libclks_kernel_rust.a") set(KERNEL_RUST_LIB "${BUILD_ROOT}/libclks_kernel_rust.a")
resolve_tool_with_fallback(CC gcc cc clang) resolve_tool_with_fallback(CC gcc cc clang)
resolve_tool_with_fallback(KERNEL_CXX g++ clang++ x86_64-elf-g++) resolve_tool_with_fallback(KERNEL_CXX g++ clang++ x86_64-elf-g++)
resolve_tool_with_fallback(LD ld.lld ld) resolve_tool_with_fallback(LD ld.lld ld)
if(CLEONOS_ENABLE) if(CLEONOS_ENABLE)
resolve_tool_with_fallback(USER_CC cc gcc clang) resolve_tool_with_fallback(USER_CC cc gcc clang)
resolve_tool_with_fallback(USER_LD ld.lld ld) resolve_tool_with_fallback(USER_LD ld.lld ld)
endif() endif()
resolve_tool_with_fallback(NM llvm-nm x86_64-elf-nm nm) 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(ADDR2LINE llvm-addr2line x86_64-elf-addr2line addr2line)
resolve_tool_with_fallback(OBJCOPY_FOR_TARGET llvm-objcopy x86_64-linux-gnu-objcopy objcopy) resolve_tool_with_fallback(OBJCOPY_FOR_TARGET llvm-objcopy x86_64-linux-gnu-objcopy objcopy)
resolve_tool_with_fallback(OBJDUMP_FOR_TARGET llvm-objdump x86_64-linux-gnu-objdump objdump) resolve_tool_with_fallback(OBJDUMP_FOR_TARGET llvm-objdump x86_64-linux-gnu-objdump objdump)
resolve_tool_with_fallback(READELF_FOR_TARGET llvm-readelf x86_64-linux-gnu-readelf readelf) resolve_tool_with_fallback(READELF_FOR_TARGET llvm-readelf x86_64-linux-gnu-readelf readelf)
resolve_path("${LIMINE_DIR}" LIMINE_DIR_ABS) resolve_path("${LIMINE_DIR}" LIMINE_DIR_ABS)
resolve_path("${LIMINE_BIN_DIR}" LIMINE_BIN_DIR_ABS) resolve_path("${LIMINE_BIN_DIR}" LIMINE_BIN_DIR_ABS)
set(LIMINE_SETUP_STAMP "${LIMINE_DIR_ABS}/.cleonos-limine-setup.stamp") set(LIMINE_SETUP_STAMP "${LIMINE_DIR_ABS}/.cleonos-limine-setup.stamp")
set(LIMINE_BUILD_STAMP "${LIMINE_DIR_ABS}/.cleonos-limine-build.stamp") set(LIMINE_BUILD_STAMP "${LIMINE_DIR_ABS}/.cleonos-limine-build.stamp")
set(CLKS_ARCH "x86_64" CACHE STRING "Target CLKS arch") set(CLKS_ARCH "x86_64" CACHE STRING "Target CLKS arch")
set(USER_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/cleonos/c/user.ld") set(USER_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/cleonos/c/user.ld")
set(KELF_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/cleonos/c/kelf.ld") set(KELF_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/cleonos/c/kelf.ld")
set(CLEONOS_MENUCONFIG_CMAKE "${CMAKE_SOURCE_DIR}/configs/menuconfig/config.cmake" CACHE FILEPATH "menuconfig generated CMake config") set(CLEONOS_MENUCONFIG_CMAKE "${CMAKE_SOURCE_DIR}/configs/menuconfig/config.cmake" CACHE FILEPATH "menuconfig generated CMake config")
if(EXISTS "${CLEONOS_MENUCONFIG_CMAKE}") if(EXISTS "${CLEONOS_MENUCONFIG_CMAKE}")
include("${CLEONOS_MENUCONFIG_CMAKE}") include("${CLEONOS_MENUCONFIG_CMAKE}")
cl_log_info("menuconfig loaded from ${CLEONOS_MENUCONFIG_CMAKE}") cl_log_info("menuconfig loaded from ${CLEONOS_MENUCONFIG_CMAKE}")
endif() endif()
# CLKS compile flags and feature-to-macro expansion now live in the CLKS submodule build system. # CLKS compile flags and feature-to-macro expansion now live in the CLKS submodule build system.
set(USER_CFLAGS set(USER_CFLAGS
-std=c11 -std=c11
-ffreestanding -ffreestanding
-fno-stack-protector -fno-stack-protector
-fno-builtin -fno-builtin
-Wall -Wall
-Wextra -Wextra
-Werror -Werror
"-I${CMAKE_SOURCE_DIR}/cleonos/c/include" "-I${CMAKE_SOURCE_DIR}/cleonos/c/include"
) )
set(USER_CFLAGS_DOOM set(USER_CFLAGS_DOOM
-std=c11 -std=c11
-ffreestanding -ffreestanding
-fno-stack-protector -fno-stack-protector
-fno-builtin -fno-builtin
-Wall -Wall
-Wextra -Wextra
-Wno-error -Wno-error
-Wno-unused-parameter -Wno-unused-parameter
-Wno-missing-field-initializers -Wno-missing-field-initializers
-Wno-sign-compare -Wno-sign-compare
-D_DEFAULT_SOURCE -D_DEFAULT_SOURCE
-D_POSIX_C_SOURCE=200809L -D_POSIX_C_SOURCE=200809L
"-I${CMAKE_SOURCE_DIR}/cleonos/third-party/doomgeneric/doomgeneric" "-I${CMAKE_SOURCE_DIR}/cleonos/third-party/doomgeneric/doomgeneric"
"-include" "-include"
"${CMAKE_SOURCE_DIR}/cleonos/c/apps/doom/doom_shim.h" "${CMAKE_SOURCE_DIR}/cleonos/c/apps/doom/doom_shim.h"
) )
set(USER_LDFLAGS set(USER_LDFLAGS
-nostdlib -nostdlib
-z -z
max-page-size=0x1000 max-page-size=0x1000
-T -T
"${USER_LINKER_SCRIPT}" "${USER_LINKER_SCRIPT}"
) )
set(KELF_LDFLAGS set(KELF_LDFLAGS
-nostdlib -nostdlib
-z -z
max-page-size=0x1000 max-page-size=0x1000
-T -T
"${KELF_LINKER_SCRIPT}" "${KELF_LINKER_SCRIPT}"
) )
if(NOT CLKS_ARCH STREQUAL "x86_64") if(NOT CLKS_ARCH STREQUAL "x86_64")
cl_log_error("CLKS_ARCH=${CLKS_ARCH} is not supported by this CMake build yet; use x86_64") cl_log_error("CLKS_ARCH=${CLKS_ARCH} is not supported by this CMake build yet; use x86_64")
endif() endif()
set(CLKS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/clks") set(CLKS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/clks")
set(CLKS_CMAKE_BUILD_DIR "${CMAKE_BINARY_DIR}/clks-cmake") set(CLKS_CMAKE_BUILD_DIR "${CMAKE_BINARY_DIR}/clks-cmake")
if(NOT EXISTS "${CLKS_SOURCE_DIR}/CMakeLists.txt") if(NOT EXISTS "${CLKS_SOURCE_DIR}/CMakeLists.txt")
cl_log_error("missing CLKS submodule CMakeLists: ${CLKS_SOURCE_DIR}/CMakeLists.txt") cl_log_error("missing CLKS submodule CMakeLists: ${CLKS_SOURCE_DIR}/CMakeLists.txt")
endif() endif()
set(CLKS_SUBMODULE_CMAKE_ARGS set(CLKS_SUBMODULE_CMAKE_ARGS
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DCLKS_ARCH=${CLKS_ARCH}" "-DCLKS_ARCH=${CLKS_ARCH}"
@@ -211,273 +211,273 @@ set(CLKS_SUBMODULE_CMAKE_ARGS
"-DCC=${CC}" "-DCC=${CC}"
"-DKERNEL_CXX=${KERNEL_CXX}" "-DKERNEL_CXX=${KERNEL_CXX}"
"-DLD=${LD}" "-DLD=${LD}"
"-DRUSTC=${RUSTC}" "-DRUSTC=${RUSTC}"
"-DNM=${NM}" "-DNM=${NM}"
"-DADDR2LINE=${ADDR2LINE}" "-DADDR2LINE=${ADDR2LINE}"
"-DOBJCOPY_FOR_TARGET=${OBJCOPY_FOR_TARGET}" "-DOBJCOPY_FOR_TARGET=${OBJCOPY_FOR_TARGET}"
"-DOBJDUMP_FOR_TARGET=${OBJDUMP_FOR_TARGET}" "-DOBJDUMP_FOR_TARGET=${OBJDUMP_FOR_TARGET}"
"-DREADELF_FOR_TARGET=${READELF_FOR_TARGET}" "-DREADELF_FOR_TARGET=${READELF_FOR_TARGET}"
) )
add_custom_target(kernel add_custom_target(kernel
COMMAND ${CMAKE_COMMAND} -S "${CLKS_SOURCE_DIR}" -B "${CLKS_CMAKE_BUILD_DIR}" ${CLKS_SUBMODULE_CMAKE_ARGS} COMMAND ${CMAKE_COMMAND} -S "${CLKS_SOURCE_DIR}" -B "${CLKS_CMAKE_BUILD_DIR}" ${CLKS_SUBMODULE_CMAKE_ARGS}
COMMAND ${CMAKE_COMMAND} --build "${CLKS_CMAKE_BUILD_DIR}" --target kernel COMMAND ${CMAKE_COMMAND} --build "${CLKS_CMAKE_BUILD_DIR}" --target kernel
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(kernel-symbols add_custom_target(kernel-symbols
COMMAND ${CMAKE_COMMAND} -S "${CLKS_SOURCE_DIR}" -B "${CLKS_CMAKE_BUILD_DIR}" ${CLKS_SUBMODULE_CMAKE_ARGS} COMMAND ${CMAKE_COMMAND} -S "${CLKS_SOURCE_DIR}" -B "${CLKS_CMAKE_BUILD_DIR}" ${CLKS_SUBMODULE_CMAKE_ARGS}
COMMAND ${CMAKE_COMMAND} --build "${CLKS_CMAKE_BUILD_DIR}" --target kernel-symbols COMMAND ${CMAKE_COMMAND} --build "${CLKS_CMAKE_BUILD_DIR}" --target kernel-symbols
USES_TERMINAL USES_TERMINAL
) )
add_dependencies(kernel-symbols kernel) add_dependencies(kernel-symbols kernel)
if(CLEONOS_ENABLE) if(CLEONOS_ENABLE)
include("${CMAKE_SOURCE_DIR}/cleonos/CMakeLists.txt") include("${CMAKE_SOURCE_DIR}/cleonos/CMakeLists.txt")
endif() endif()
add_custom_target(setup-tools add_custom_target(setup-tools
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DCLEONOS_ENABLE=${CLEONOS_ENABLE}" "-DCLEONOS_ENABLE=${CLEONOS_ENABLE}"
"-DGIT_TOOL=${GIT_TOOL}" "-DGIT_TOOL=${GIT_TOOL}"
"-DTAR_TOOL=${TAR}" "-DTAR_TOOL=${TAR}"
"-DXORRISO_TOOL=${XORRISO}" "-DXORRISO_TOOL=${XORRISO}"
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DCC_TOOL=${CC}" "-DCC_TOOL=${CC}"
"-DLD_TOOL=${LD}" "-DLD_TOOL=${LD}"
"-DOBJCOPY_TOOL=${OBJCOPY_FOR_TARGET}" "-DOBJCOPY_TOOL=${OBJCOPY_FOR_TARGET}"
"-DOBJDUMP_TOOL=${OBJDUMP_FOR_TARGET}" "-DOBJDUMP_TOOL=${OBJDUMP_FOR_TARGET}"
"-DREADELF_TOOL=${READELF_FOR_TARGET}" "-DREADELF_TOOL=${READELF_FOR_TARGET}"
"-DNM_TOOL=${NM}" "-DNM_TOOL=${NM}"
"-DADDR2LINE_TOOL=${ADDR2LINE}" "-DADDR2LINE_TOOL=${ADDR2LINE}"
"-DUSER_CC_TOOL=${USER_CC}" "-DUSER_CC_TOOL=${USER_CC}"
"-DUSER_LD_TOOL=${USER_LD}" "-DUSER_LD_TOOL=${USER_LD}"
"-DRUSTC_TOOL=${RUSTC}" "-DRUSTC_TOOL=${RUSTC}"
"-DMAKE_TOOL=${MAKE_TOOL}" "-DMAKE_TOOL=${MAKE_TOOL}"
"-DSH_TOOL=${SH_TOOL}" "-DSH_TOOL=${SH_TOOL}"
-P "${CMAKE_SOURCE_DIR}/cmake/check_tools.cmake" -P "${CMAKE_SOURCE_DIR}/cmake/check_tools.cmake"
) )
add_custom_target(setup-limine add_custom_target(setup-limine
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DGIT_TOOL=${GIT_TOOL}" "-DGIT_TOOL=${GIT_TOOL}"
"-DMAKE_TOOL=${MAKE_TOOL}" "-DMAKE_TOOL=${MAKE_TOOL}"
"-DSH_TOOL=${SH_TOOL}" "-DSH_TOOL=${SH_TOOL}"
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLIMINE_DIR=${LIMINE_DIR_ABS}" "-DLIMINE_DIR=${LIMINE_DIR_ABS}"
"-DLIMINE_REPO=${LIMINE_REPO}" "-DLIMINE_REPO=${LIMINE_REPO}"
"-DLIMINE_REF=${LIMINE_REF}" "-DLIMINE_REF=${LIMINE_REF}"
"-DLIMINE_BIN_DIR=${LIMINE_BIN_DIR_ABS}" "-DLIMINE_BIN_DIR=${LIMINE_BIN_DIR_ABS}"
"-DLIMINE_SETUP_STAMP=${LIMINE_SETUP_STAMP}" "-DLIMINE_SETUP_STAMP=${LIMINE_SETUP_STAMP}"
"-DLIMINE_BUILD_STAMP=${LIMINE_BUILD_STAMP}" "-DLIMINE_BUILD_STAMP=${LIMINE_BUILD_STAMP}"
"-DLIMINE_CONFIGURE_FLAGS=${LIMINE_CONFIGURE_FLAGS}" "-DLIMINE_CONFIGURE_FLAGS=${LIMINE_CONFIGURE_FLAGS}"
"-DLIMINE_SKIP_CONFIGURE=${LIMINE_SKIP_CONFIGURE}" "-DLIMINE_SKIP_CONFIGURE=${LIMINE_SKIP_CONFIGURE}"
"-DOBJCOPY_FOR_TARGET=${OBJCOPY_FOR_TARGET}" "-DOBJCOPY_FOR_TARGET=${OBJCOPY_FOR_TARGET}"
"-DOBJDUMP_FOR_TARGET=${OBJDUMP_FOR_TARGET}" "-DOBJDUMP_FOR_TARGET=${OBJDUMP_FOR_TARGET}"
"-DREADELF_FOR_TARGET=${READELF_FOR_TARGET}" "-DREADELF_FOR_TARGET=${READELF_FOR_TARGET}"
-P "${CMAKE_SOURCE_DIR}/cmake/setup_limine.cmake" -P "${CMAKE_SOURCE_DIR}/cmake/setup_limine.cmake"
) )
add_dependencies(setup-limine setup-tools) add_dependencies(setup-limine setup-tools)
add_custom_target(setup DEPENDS setup-tools setup-limine) add_custom_target(setup DEPENDS setup-tools setup-limine)
add_custom_command( add_custom_command(
TARGET setup TARGET setup
POST_BUILD POST_BUILD
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO" "-DLOG_LEVEL=INFO"
"-DLOG_TEXT=environment ready" "-DLOG_TEXT=environment ready"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
) )
if(CLEONOS_ENABLE) if(CLEONOS_ENABLE)
add_custom_target(disk-image add_custom_target(disk-image
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DDISK_IMAGE=${DISK_IMAGE}" "-DDISK_IMAGE=${DISK_IMAGE}"
"-DDISK_MB=${CLEONOS_DISK_IMAGE_MB}" "-DDISK_MB=${CLEONOS_DISK_IMAGE_MB}"
-P "${CMAKE_SOURCE_DIR}/cmake/ensure_disk_image.cmake" -P "${CMAKE_SOURCE_DIR}/cmake/ensure_disk_image.cmake"
BYPRODUCTS "${DISK_IMAGE}" BYPRODUCTS "${DISK_IMAGE}"
VERBATIM VERBATIM
) )
add_custom_command( add_custom_command(
OUTPUT "${ISO_IMAGE}" OUTPUT "${ISO_IMAGE}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${ISO_ROOT}" 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 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 "${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 "${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}/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}/EFI/BOOT/limine.conf"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/configs/limine.conf" "${ISO_ROOT}/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.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-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}/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 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} -E make_directory "${CMAKE_SOURCE_DIR}/build"
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP" "-DLOG_LEVEL=STEP"
"-DLOG_TEXT=building iso -> ${ISO_IMAGE}" "-DLOG_TEXT=building iso -> ${ISO_IMAGE}"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${XORRISO} -as mkisofs COMMAND ${XORRISO} -as mkisofs
-b boot/limine/limine-bios-cd.bin -b boot/limine/limine-bios-cd.bin
-no-emul-boot -no-emul-boot
-boot-load-size 4 -boot-load-size 4
-boot-info-table -boot-info-table
--efi-boot boot/limine/limine-uefi-cd.bin --efi-boot boot/limine/limine-uefi-cd.bin
-efi-boot-part -efi-boot-part
--efi-boot-image --efi-boot-image
--protective-msdos-label --protective-msdos-label
"${ISO_ROOT}" "${ISO_ROOT}"
-o "${ISO_IMAGE}" -o "${ISO_IMAGE}"
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP" "-DLOG_LEVEL=STEP"
"-DLOG_TEXT=installing limine boot sectors" "-DLOG_TEXT=installing limine boot sectors"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
COMMAND "${LIMINE_BIN_DIR_ABS}/limine" bios-install "${ISO_IMAGE}" COMMAND "${LIMINE_BIN_DIR_ABS}/limine" bios-install "${ISO_IMAGE}"
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO" "-DLOG_LEVEL=INFO"
"-DLOG_TEXT=iso ready: ${ISO_IMAGE}" "-DLOG_TEXT=iso ready: ${ISO_IMAGE}"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
DEPENDS "${KERNEL_ELF}" "${RAMDISK_IMAGE}" "${CMAKE_SOURCE_DIR}/configs/limine.conf" DEPENDS "${KERNEL_ELF}" "${RAMDISK_IMAGE}" "${CMAKE_SOURCE_DIR}/configs/limine.conf"
VERBATIM VERBATIM
) )
add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}") add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}")
add_dependencies(iso setup-tools setup-limine kernel ramdisk) add_dependencies(iso setup-tools setup-limine kernel ramdisk)
add_custom_target(run add_custom_target(run
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP" "-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu run" "-DLOG_TEXT=launching qemu run"
-P "${CL_LOG_EMIT_SCRIPT}" -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 COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -serial stdio
DEPENDS iso disk-image DEPENDS iso disk-image
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(debug add_custom_target(debug
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP" "-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu debug (-s -S)" "-DLOG_TEXT=launching qemu debug (-s -S)"
-P "${CL_LOG_EMIT_SCRIPT}" -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 COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -serial stdio -s -S
DEPENDS iso disk-image DEPENDS iso disk-image
USES_TERMINAL USES_TERMINAL
) )
else() else()
add_custom_target(clks-default ALL DEPENDS kernel) add_custom_target(clks-default ALL DEPENDS kernel)
endif() endif()
add_custom_target(clean-x86 add_custom_target(clean-x86
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP" "-DLOG_LEVEL=STEP"
"-DLOG_TEXT=cleaning ${BUILD_ROOT}" "-DLOG_TEXT=cleaning ${BUILD_ROOT}"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${BUILD_ROOT}" COMMAND ${CMAKE_COMMAND} -E rm -rf "${BUILD_ROOT}"
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO" "-DLOG_LEVEL=INFO"
"-DLOG_TEXT=clean done" "-DLOG_TEXT=clean done"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
) )
add_custom_target(clean-all add_custom_target(clean-all
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP" "-DLOG_LEVEL=STEP"
"-DLOG_TEXT=cleaning build" "-DLOG_TEXT=cleaning build"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${CMAKE_SOURCE_DIR}/build" COMMAND ${CMAKE_COMMAND} -E rm -rf "${CMAKE_SOURCE_DIR}/build"
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}" "-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO" "-DLOG_LEVEL=INFO"
"-DLOG_TEXT=clean-all done" "-DLOG_TEXT=clean-all done"
-P "${CL_LOG_EMIT_SCRIPT}" -P "${CL_LOG_EMIT_SCRIPT}"
) )
find_package(Python3 COMPONENTS Interpreter QUIET) find_package(Python3 COMPONENTS Interpreter QUIET)
if(Python3_Interpreter_FOUND) if(Python3_Interpreter_FOUND)
if(CLEONOS_ENABLE) if(CLEONOS_ENABLE)
add_custom_target(menuconfig add_custom_target(menuconfig
COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py"
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(menuconfig-gui add_custom_target(menuconfig-gui
COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui
USES_TERMINAL USES_TERMINAL
) )
else() else()
add_custom_target(menuconfig add_custom_target(menuconfig
COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --clks-only COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --clks-only
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(menuconfig-gui add_custom_target(menuconfig-gui
COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui --clks-only COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui --clks-only
USES_TERMINAL USES_TERMINAL
) )
endif() endif()
add_custom_target(menuconfig-clks add_custom_target(menuconfig-clks
COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --clks-only COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --clks-only
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(menuconfig-gui-clks add_custom_target(menuconfig-gui-clks
COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui --clks-only COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/menuconfig.py" --gui --clks-only
USES_TERMINAL USES_TERMINAL
) )
else() else()
add_custom_target(menuconfig add_custom_target(menuconfig
COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py manually" COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py manually"
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(menuconfig-gui add_custom_target(menuconfig-gui
COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --gui manually" COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --gui manually"
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(menuconfig-clks add_custom_target(menuconfig-clks
COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --clks-only manually" COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --clks-only manually"
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(menuconfig-gui-clks add_custom_target(menuconfig-gui-clks
COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --gui --clks-only manually" COMMAND ${CMAKE_COMMAND} -E echo "python3 not found; run scripts/menuconfig.py --gui --clks-only manually"
USES_TERMINAL USES_TERMINAL
) )
endif() endif()
if(CLEONOS_ENABLE) if(CLEONOS_ENABLE)
add_custom_target(cleonos-help add_custom_target(cleonos-help
COMMAND ${CMAKE_COMMAND} -E echo "CLeonOS CMake build system (x86_64 only)" 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 " CLEONOS_ENABLE=${CLEONOS_ENABLE}"
COMMAND ${CMAKE_COMMAND} -E echo " cmake -S . -B build-cmake" 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"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui" 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-clks"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui-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 setup"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target kernel" 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 userapps"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target iso" 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 run"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target debug" COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target debug"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target disk-image" COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target disk-image"
) )
else() else()
add_custom_target(cleonos-help add_custom_target(cleonos-help
COMMAND ${CMAKE_COMMAND} -E echo "CLeonOS CMake build system (x86_64 only)" 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 " CLEONOS_ENABLE=${CLEONOS_ENABLE}"
COMMAND ${CMAKE_COMMAND} -E echo " cmake -S . -B build-cmake" 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"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui" 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-clks"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target menuconfig-gui-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 setup"
COMMAND ${CMAKE_COMMAND} -E echo " cmake --build build-cmake --target kernel" 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)" COMMAND ${CMAKE_COMMAND} -E echo " (CLKS-only mode: userapps/iso/run/debug/disk-image are disabled)"
) )
endif() endif()

140
Makefile
View File

@@ -20,6 +20,19 @@ MENUCONFIG_ARGS ?=
MENUCONFIG_PRESET ?= MENUCONFIG_PRESET ?=
DISK_IMAGE_MB ?= DISK_IMAGE_MB ?=
CLEONOS_ENABLE ?= auto CLEONOS_ENABLE ?= auto
QEMU_DRIVE_IMAGE ?= build/x86_64/cleonos_disk.img
SHOW_COMMANDS ?= 0
V ?= 0
ifneq ($(filter 1 ON on TRUE true YES yes Y y,$(SHOW_COMMANDS) $(V)),)
Q :=
CMAKE_BUILD_VERBOSE_ARG := --verbose
CMAKE_CONFIG_VERBOSE_ARG := -DCMAKE_VERBOSE_MAKEFILE=ON
else
Q := @
CMAKE_BUILD_VERBOSE_ARG :=
CMAKE_CONFIG_VERBOSE_ARG :=
endif
ifeq ($(strip $(CMAKE_GENERATOR)),) ifeq ($(strip $(CMAKE_GENERATOR)),)
GEN_ARG := GEN_ARG :=
@@ -84,7 +97,7 @@ ifneq ($(strip $(DISK_IMAGE_MB)),)
CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_DISK_IMAGE_MB=$(DISK_IMAGE_MB) CMAKE_PASSTHROUGH_ARGS += -DCLEONOS_DISK_IMAGE_MB=$(DISK_IMAGE_MB)
endif endif
.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 .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-drive-image clean clean-all help
ifeq ($(CLEONOS_ENABLED_BOOL),1) ifeq ($(CLEONOS_ENABLED_BOOL),1)
all: iso all: iso
@@ -93,14 +106,14 @@ all: kernel
endif endif
configure: 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) > $(Q)$(CMAKE) -S . -B $(CMAKE_BUILD_DIR) $(GEN_ARG) -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DNO_COLOR=$(NO_COLOR) $(CMAKE_CONFIG_VERBOSE_ARG) $(CMAKE_EXTRA_ARGS) $(CMAKE_PASSTHROUGH_ARGS)
reconfigure: reconfigure:
> @rm -rf $(CMAKE_BUILD_DIR) > $(Q)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)" CLEONOS_ENABLE="$(CLEONOS_ENABLE)" > $(Q)$(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: menuconfig:
> @if command -v $(PYTHON) >/dev/null 2>&1; then \ > $(Q)if command -v $(PYTHON) >/dev/null 2>&1; then \
> $(PYTHON) scripts/menuconfig.py $(MENUCONFIG_SCOPE_ARG) $(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 \ > elif command -v python >/dev/null 2>&1; then \
> python scripts/menuconfig.py $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > python scripts/menuconfig.py $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \
@@ -108,10 +121,10 @@ menuconfig:
> echo "python3/python not found"; \ > echo "python3/python not found"; \
> exit 1; \ > exit 1; \
> fi > 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)" > $(Q)$(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: menuconfig-gui:
> @if command -v $(PYTHON) >/dev/null 2>&1; then \ > $(Q)if command -v $(PYTHON) >/dev/null 2>&1; then \
> $(PYTHON) scripts/menuconfig.py --gui $(MENUCONFIG_SCOPE_ARG) $(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 \ > elif command -v python >/dev/null 2>&1; then \
> python scripts/menuconfig.py --gui $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > python scripts/menuconfig.py --gui $(MENUCONFIG_SCOPE_ARG) $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \
@@ -119,10 +132,10 @@ menuconfig-gui:
> echo "python3/python not found"; \ > echo "python3/python not found"; \
> exit 1; \ > exit 1; \
> fi > 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)" > $(Q)$(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: menuconfig-clks:
> @if command -v $(PYTHON) >/dev/null 2>&1; then \ > $(Q)if command -v $(PYTHON) >/dev/null 2>&1; then \
> $(PYTHON) scripts/menuconfig.py --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > $(PYTHON) scripts/menuconfig.py --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \
> elif command -v python >/dev/null 2>&1; then \ > elif command -v python >/dev/null 2>&1; then \
> python scripts/menuconfig.py --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > python scripts/menuconfig.py --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \
@@ -130,10 +143,10 @@ menuconfig-clks:
> echo "python3/python not found"; \ > echo "python3/python not found"; \
> exit 1; \ > exit 1; \
> fi > 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)" > $(Q)$(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: menuconfig-gui-clks:
> @if command -v $(PYTHON) >/dev/null 2>&1; then \ > $(Q)if command -v $(PYTHON) >/dev/null 2>&1; then \
> $(PYTHON) scripts/menuconfig.py --gui --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > $(PYTHON) scripts/menuconfig.py --gui --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \
> elif command -v python >/dev/null 2>&1; then \ > elif command -v python >/dev/null 2>&1; then \
> python scripts/menuconfig.py --gui --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \ > python scripts/menuconfig.py --gui --clks-only $(MENUCONFIG_PRESET_ARG) $(MENUCONFIG_ARGS); \
@@ -141,88 +154,99 @@ menuconfig-gui-clks:
> echo "python3/python not found"; \ > echo "python3/python not found"; \
> exit 1; \ > exit 1; \
> fi > 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)" > $(Q)$(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 setup: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target setup > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target setup $(CMAKE_BUILD_VERBOSE_ARG)
setup-tools: configure setup-tools: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target setup-tools > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target setup-tools $(CMAKE_BUILD_VERBOSE_ARG)
setup-limine: configure setup-limine: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target setup-limine > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target setup-limine $(CMAKE_BUILD_VERBOSE_ARG)
kernel: configure kernel: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target kernel > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target kernel $(CMAKE_BUILD_VERBOSE_ARG)
ifeq ($(CLEONOS_ENABLED_BOOL),1) ifeq ($(CLEONOS_ENABLED_BOOL),1)
userapps: configure userapps: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target userapps > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target userapps $(CMAKE_BUILD_VERBOSE_ARG)
ramdisk-root: configure ramdisk-root: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target ramdisk-root > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target ramdisk-root $(CMAKE_BUILD_VERBOSE_ARG)
ramdisk: configure ramdisk: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target ramdisk > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target ramdisk $(CMAKE_BUILD_VERBOSE_ARG)
disk-image: configure disk-image: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target disk-image > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target disk-image $(CMAKE_BUILD_VERBOSE_ARG)
iso: configure iso: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target iso > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target iso $(CMAKE_BUILD_VERBOSE_ARG)
run: configure run: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target run > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target run $(CMAKE_BUILD_VERBOSE_ARG)
debug: configure debug: configure
> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target debug > $(Q)$(CMAKE) --build $(CMAKE_BUILD_DIR) --target debug $(CMAKE_BUILD_VERBOSE_ARG)
else else
userapps ramdisk-root ramdisk disk-image iso run debug: userapps ramdisk-root ramdisk disk-image iso run debug:
> @echo "target '$@' requires CLEONOS_ENABLE=ON and cleonos sources present" > $(Q)echo "target '$@' requires CLEONOS_ENABLE=ON and cleonos sources present"
> @exit 1 > $(Q)exit 1
endif endif
clean: clean:
> @if [ -d "$(CMAKE_BUILD_DIR)" ]; then \ > $(Q)if [ -d "$(CMAKE_BUILD_DIR)" ]; then \
> $(CMAKE) --build $(CMAKE_BUILD_DIR) --target clean-x86; \ > $(CMAKE) --build $(CMAKE_BUILD_DIR) --target clean-x86 $(CMAKE_BUILD_VERBOSE_ARG); \
> else \ > else \
> rm -rf build/x86_64; \ > rm -rf build/x86_64; \
> fi > fi
> $(Q)$(MAKE) clean-drive-image QEMU_DRIVE_IMAGE="$(QEMU_DRIVE_IMAGE)"
clean-all: clean-all:
> @if [ -d "$(CMAKE_BUILD_DIR)" ]; then \ > $(Q)if [ -d "$(CMAKE_BUILD_DIR)" ]; then \
> $(CMAKE) --build $(CMAKE_BUILD_DIR) --target clean-all; \ > $(CMAKE) --build $(CMAKE_BUILD_DIR) --target clean-all $(CMAKE_BUILD_VERBOSE_ARG); \
> else \ > else \
> rm -rf build build-cmake; \ > rm -rf build build-cmake; \
> fi > fi
> $(Q)$(MAKE) clean-drive-image QEMU_DRIVE_IMAGE="$(QEMU_DRIVE_IMAGE)"
clean-drive-image:
> $(Q)rm -f "$(QEMU_DRIVE_IMAGE)"
help: help:
> @echo "CLeonOS (CMake-backed wrapper)" > $(Q)echo "CLeonOS (CMake-backed wrapper)"
> @echo "Mode: CLEONOS_ENABLE=$(CLEONOS_ENABLE_EFFECTIVE) ($(CLEONOS_MODE_LABEL))" > $(Q)echo "Mode: CLEONOS_ENABLE=$(CLEONOS_ENABLE_EFFECTIVE) ($(CLEONOS_MODE_LABEL))"
> @echo " make configure" > $(Q)echo " make configure"
> @echo " make menuconfig" > $(Q)echo " make menuconfig"
> @echo " make menuconfig-gui" > $(Q)echo " make menuconfig-gui"
> @echo " make menuconfig-clks" > $(Q)echo " make menuconfig-clks"
> @echo " make menuconfig-gui-clks" > $(Q)echo " make menuconfig-gui-clks"
> @echo " make setup" > $(Q)echo " make setup"
> @echo " make userapps" > $(Q)echo " make userapps"
> @echo " make disk-image" > $(Q)echo " make disk-image"
> @echo " make iso" > $(Q)echo " make iso"
> @echo " make run" > $(Q)echo " make run"
> @echo " make debug" > $(Q)echo " make debug"
> @echo " make clean" > $(Q)echo " make clean-drive-image"
> @echo " make clean-all" > $(Q)echo " make clean"
> @echo "" > $(Q)echo " make clean-all"
> @echo "Pass custom CMake cache args via:" > $(Q)echo ""
> @echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'" > $(Q)echo "Show commands:"
> @echo "Direct passthrough is also supported:" > $(Q)echo " make run V=1"
> @echo " make run LIMINE_SKIP_CONFIGURE=1" > $(Q)echo " make run SHOW_COMMANDS=1"
> @echo "Kernel-only mode:" > $(Q)echo " (includes CMake build internals: compiler/linker command lines)"
> @echo " make kernel CLEONOS_ENABLE=OFF" > $(Q)echo ""
> @echo " make -C clks kernel" > $(Q)echo "Pass custom CMake cache args via:"
> @echo "Disk image size example:" > $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'"
> @echo " make run DISK_IMAGE_MB=128" > $(Q)echo "Direct passthrough is also supported:"
> @echo "Preset examples:" > $(Q)echo " make run LIMINE_SKIP_CONFIGURE=1"
> @echo " make menuconfig MENUCONFIG_PRESET=full" > $(Q)echo "Kernel-only mode:"
> @echo " make menuconfig MENUCONFIG_PRESET=minimal" > $(Q)echo " make kernel CLEONOS_ENABLE=OFF"
> @echo " make menuconfig-gui MENUCONFIG_PRESET=dev" > $(Q)echo " make -C clks kernel"
> $(Q)echo "Disk image size example:"
> $(Q)echo " make run DISK_IMAGE_MB=128"
> $(Q)echo "Preset examples:"
> $(Q)echo " make menuconfig MENUCONFIG_PRESET=full"
> $(Q)echo " make menuconfig MENUCONFIG_PRESET=minimal"
> $(Q)echo " make menuconfig-gui MENUCONFIG_PRESET=dev"

View File

@@ -0,0 +1,40 @@
#include <cleonos_syscall.h>
#include <stdio.h>
static void fdtest_tty_line(const char *text) {
u64 len = 0ULL;
if (text == (const char *)0) {
return;
}
while (text[len] != '\0') {
len++;
}
(void)cleonos_sys_tty_write(text, len);
(void)cleonos_sys_tty_write("\n", 1ULL);
}
int cleonos_app_main(void) {
(void)fputs("[fdtest] begin", 1);
(void)fputc('\n', 1);
(void)fputs("[fdtest] stdout fputs line", 1);
(void)fputc('\n', 1);
(void)printf("[fdtest] stdout printf value=%d hex=%X\n", 42, 0x2A);
(void)dprintf(1, "[fdtest] stdout dprintf line\n");
(void)fprintf(1, "[fdtest] stdout fprintf line\n");
(void)fputs("[fdtest] stdout split part A", 1);
(void)fputs(" + part B", 1);
(void)fputc('\n', 1);
(void)dprintf(2, "[fdtest] stderr dprintf line\n");
(void)fprintf(2, "[fdtest] stderr fprintf line\n");
fdtest_tty_line("[fdtest] tty syscall line");
fdtest_tty_line("[fdtest] end");
return 0;
}

View File

@@ -1,6 +1,14 @@
#include "cmd_runtime.h" #include "cmd_runtime.h"
#include <stdio.h> #include <stdio.h>
static void ush_mkfs_println(const char *text) {
if (text == (const char *)0) {
return;
}
ush_writeln(text);
}
static int ush_arg_parse_label(const char *arg, char *out_label, u64 out_label_size) { static int ush_arg_parse_label(const char *arg, char *out_label, u64 out_label_size) {
char first[USH_ARG_MAX]; char first[USH_ARG_MAX];
const char *rest = (const char *)0; const char *rest = (const char *)0;
@@ -34,30 +42,50 @@ static int ush_arg_parse_label(const char *arg, char *out_label, u64 out_label_s
static int ush_cmd_mkfsfat32(const char *arg) { static int ush_cmd_mkfsfat32(const char *arg) {
char label[16]; char label[16];
u64 ok; u64 ok;
u64 present;
u64 size_bytes;
u64 sectors;
u64 formatted;
u64 mounted;
if (cleonos_sys_disk_present() == 0ULL) { present = cleonos_sys_disk_present();
(void)fputs("mkfsfat32: disk not present\n", 1); if (present == 0ULL) {
ush_mkfs_println("mkfsfat32: disk not present");
return 0; return 0;
} }
if (ush_arg_parse_label(arg, label, (u64)sizeof(label)) == 0) { if (ush_arg_parse_label(arg, label, (u64)sizeof(label)) == 0) {
(void)fputs("mkfsfat32: usage mkfsfat32 [label]\n", 1); ush_mkfs_println("mkfsfat32: usage mkfsfat32 [label]");
return 0; return 0;
} }
ok = cleonos_sys_disk_format_fat32((label[0] != '\0') ? label : (const char *)0); ok = cleonos_sys_disk_format_fat32((label[0] != '\0') ? label : (const char *)0);
if (ok == 0ULL) { if (ok == 0ULL) {
(void)fputs("mkfsfat32: format failed\n", 1); char line[USH_LINE_MAX];
size_bytes = cleonos_sys_disk_size_bytes();
sectors = cleonos_sys_disk_sector_count();
formatted = cleonos_sys_disk_formatted();
mounted = cleonos_sys_disk_mounted();
ush_mkfs_println("mkfsfat32: format failed");
(void)snprintf(line, (unsigned long)sizeof(line),
"mkfsfat32: disk.present=%llu size=%llu sectors=%llu formatted=%llu mounted=%llu",
(unsigned long long)present, (unsigned long long)size_bytes, (unsigned long long)sectors,
(unsigned long long)formatted, (unsigned long long)mounted);
ush_mkfs_println(line);
return 0; return 0;
} }
if (label[0] != '\0') { if (label[0] != '\0') {
(void)printf("mkfsfat32: formatted (label=%s)\n", label); char line[USH_LINE_MAX];
(void)snprintf(line, (unsigned long)sizeof(line), "mkfsfat32: formatted (label=%s)", label);
ush_mkfs_println(line);
} else { } else {
(void)fputs("mkfsfat32: formatted\n", 1); ush_mkfs_println("mkfsfat32: formatted");
} }
(void)fputs("mkfsfat32: now run 'mount /temp/disk' (or another mount path)\n", 1); ush_mkfs_println("mkfsfat32: now run 'mount /temp/disk' (or another mount path)");
return 1; return 1;
} }

2
clks

Submodule clks updated: 6bc15d6aba...015c8d9d70

View File

@@ -18,6 +18,7 @@
"CLEONOS_USER_APP_EXEC": true, "CLEONOS_USER_APP_EXEC": true,
"CLEONOS_USER_APP_EXIT": true, "CLEONOS_USER_APP_EXIT": true,
"CLEONOS_USER_APP_FASTFETCH": true, "CLEONOS_USER_APP_FASTFETCH": true,
"CLEONOS_USER_APP_FDTEST": true,
"CLEONOS_USER_APP_FG": true, "CLEONOS_USER_APP_FG": true,
"CLEONOS_USER_APP_FSSTAT": true, "CLEONOS_USER_APP_FSSTAT": true,
"CLEONOS_USER_APP_GREP": true, "CLEONOS_USER_APP_GREP": true,

View File

@@ -19,12 +19,21 @@
"CLEONOS_CLKS_ENABLE_KEYBOARD": true, "CLEONOS_CLKS_ENABLE_KEYBOARD": true,
"CLEONOS_CLKS_ENABLE_KLOGD_TASK": true, "CLEONOS_CLKS_ENABLE_KLOGD_TASK": true,
"CLEONOS_CLKS_ENABLE_KWORKER_TASK": true, "CLEONOS_CLKS_ENABLE_KWORKER_TASK": true,
"CLEONOS_CLKS_ENABLE_LOG_LEVEL_DEBUG": true,
"CLEONOS_CLKS_ENABLE_LOG_LEVEL_ERROR": true,
"CLEONOS_CLKS_ENABLE_LOG_LEVEL_INFO": true,
"CLEONOS_CLKS_ENABLE_LOG_LEVEL_WARN": true,
"CLEONOS_CLKS_ENABLE_LOG_OUTPUT_JOURNAL": true,
"CLEONOS_CLKS_ENABLE_LOG_OUTPUT_SERIAL": true,
"CLEONOS_CLKS_ENABLE_LOG_OUTPUT_TTY": true,
"CLEONOS_CLKS_ENABLE_MOUSE": true, "CLEONOS_CLKS_ENABLE_MOUSE": true,
"CLEONOS_CLKS_ENABLE_PMM_STATS_LOG": "m", "CLEONOS_CLKS_ENABLE_PMM_STATS_LOG": "m",
"CLEONOS_CLKS_ENABLE_PROCFS": true, "CLEONOS_CLKS_ENABLE_PROCFS": true,
"CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG": "y", "CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG": "y",
"CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG": "m", "CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG": "m",
"CLEONOS_CLKS_ENABLE_SYSCALL_SERIAL_LOG": false,
"CLEONOS_CLKS_ENABLE_SYSCALL_TICK_QUERY": true, "CLEONOS_CLKS_ENABLE_SYSCALL_TICK_QUERY": true,
"CLEONOS_CLKS_ENABLE_SYSCALL_USERID_SERIAL_LOG": false,
"CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK": true, "CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK": true,
"CLEONOS_CLKS_ENABLE_TTY_READY_LOG": "m", "CLEONOS_CLKS_ENABLE_TTY_READY_LOG": "m",
"CLEONOS_CLKS_ENABLE_USC": true, "CLEONOS_CLKS_ENABLE_USC": true,

View File

@@ -1,376 +1,578 @@
{ {
"features": [ "features": [
{ {
"key": "CLEONOS_CLKS_ENABLE_AUDIO", "key": "CLEONOS_CLKS_ENABLE_AUDIO",
"title": "Audio Driver Init", "title": "Audio Driver Init",
"description": "Initialize kernel audio subsystem during boot.", "title_zh": "音频驱动初始化",
"type": "bool", "description": "Initialize kernel audio subsystem during boot.",
"default": true "description_zh": "在启动阶段初始化内核音频子系统。",
}, "type": "bool",
{ "default": true
"key": "CLEONOS_CLKS_ENABLE_MOUSE", },
"title": "PS/2 Mouse Input", {
"description": "Initialize kernel PS/2 mouse input subsystem.", "key": "CLEONOS_CLKS_ENABLE_MOUSE",
"type": "bool", "title": "PS/2 Mouse Input",
"default": true "title_zh": "PS/2 鼠标输入",
}, "description": "Initialize kernel PS/2 mouse input subsystem.",
{ "description_zh": "初始化内核 PS/2 鼠标输入子系统。",
"key": "CLEONOS_CLKS_ENABLE_DESKTOP", "type": "bool",
"title": "TTY2 Desktop", "default": true
"description": "Enable desktop compositor tick/update path on TTY2.", },
"type": "bool", {
"default": true, "key": "CLEONOS_CLKS_ENABLE_DESKTOP",
"depends_on": "CLEONOS_CLKS_ENABLE_MOUSE" "title": "TTY2 Desktop",
}, "title_zh": "TTY2 桌面",
{ "description": "Enable desktop compositor tick/update path on TTY2.",
"key": "CLEONOS_CLKS_ENABLE_DRIVER_MANAGER", "description_zh": "在 TTY2 启用桌面合成器 tick/更新路径。",
"title": "Driver Manager", "type": "bool",
"description": "Initialize kernel ELF driver manager.", "default": true,
"type": "bool", "depends_on": "CLEONOS_CLKS_ENABLE_MOUSE"
"default": true },
}, {
{ "key": "CLEONOS_CLKS_ENABLE_DRIVER_MANAGER",
"key": "CLEONOS_CLKS_ENABLE_KELF", "title": "Driver Manager",
"title": "KELF Executor", "title_zh": "驱动管理器",
"description": "Enable kernel ELF app dispatcher and kelfd task.", "description": "Initialize kernel ELF driver manager.",
"type": "bool", "description_zh": "初始化内核 ELF 驱动管理器。",
"default": true, "type": "bool",
"depends_on": "CLEONOS_CLKS_ENABLE_DRIVER_MANAGER && CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT", "default": true
"imply": [ },
"CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE", {
"CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE" "key": "CLEONOS_CLKS_ENABLE_KELF",
] "title": "KELF Executor",
}, "title_zh": "KELF 执行器",
{ "description": "Enable kernel ELF app dispatcher and kelfd task.",
"key": "CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC", "description_zh": "启用内核 ELF 应用分发器和 kelfd 任务。",
"title": "Auto Enter User Shell", "type": "bool",
"description": "Auto-exec /shell/shell.elf after kernel boot.", "default": true,
"type": "bool", "depends_on": "CLEONOS_CLKS_ENABLE_DRIVER_MANAGER && CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT",
"default": true, "imply": [
"depends_on": "CLEONOS_CLKS_ENABLE_USRD_TASK && CLEONOS_CLKS_ENABLE_KEYBOARD", "CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE",
"select": [ "CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE"
"CLEONOS_CLKS_ENABLE_USRD_TASK", ]
"CLEONOS_CLKS_ENABLE_KEYBOARD" },
], {
"imply": [ "key": "CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC",
"CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE", "title": "Auto Enter User Shell",
"CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG" "title_zh": "自动进入用户 Shell",
] "description": "Auto-exec /shell/shell.elf after kernel boot.",
}, "description_zh": "内核启动后自动执行 /shell/shell.elf。",
{ "type": "bool",
"key": "CLEONOS_CLKS_ENABLE_HEAP_SELFTEST", "default": true,
"title": "Heap Selftest", "depends_on": "CLEONOS_CLKS_ENABLE_USRD_TASK && CLEONOS_CLKS_ENABLE_KEYBOARD",
"description": "Run kmalloc/kfree selftest during kernel boot.", "select": [
"type": "bool", "CLEONOS_CLKS_ENABLE_USRD_TASK",
"default": true "CLEONOS_CLKS_ENABLE_KEYBOARD"
}, ],
{ "imply": [
"key": "CLEONOS_CLKS_ENABLE_EXTERNAL_PSF", "CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE",
"title": "Load External PSF Font", "CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG"
"description": "Load /system/tty.psf and apply it to framebuffer TTY.", ]
"type": "bool", },
"default": true {
}, "key": "CLEONOS_CLKS_ENABLE_HEAP_SELFTEST",
{ "title": "Heap Selftest",
"key": "CLEONOS_CLKS_ENABLE_KEYBOARD", "title_zh": "堆自检",
"title": "PS/2 Keyboard Input", "description": "Run kmalloc/kfree selftest during kernel boot.",
"description": "Initialize PS/2 keyboard input subsystem.", "description_zh": "在内核启动期间运行 kmalloc/kfree 自检。",
"type": "bool", "type": "bool",
"default": true, "default": true
"imply": [ },
"CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY", {
"CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS" "key": "CLEONOS_CLKS_ENABLE_EXTERNAL_PSF",
] "title": "Load External PSF Font",
}, "title_zh": "加载外部 PSF 字体",
{ "description": "Load /system/tty.psf and apply it to framebuffer TTY.",
"key": "CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE", "description_zh": "加载 /system/tty.psf 并应用到 framebuffer TTY。",
"title": "ELFRUNNER Probe", "type": "bool",
"description": "Probe kernel ELF runtime metadata after ELFRUNNER init.", "default": true
"type": "bool", },
"default": true, {
"depends_on": "CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT && CLEONOS_CLKS_ENABLE_KELF" "key": "CLEONOS_CLKS_ENABLE_KEYBOARD",
}, "title": "PS/2 Keyboard Input",
{ "title_zh": "PS/2 键盘输入",
"key": "CLEONOS_CLKS_ENABLE_KLOGD_TASK", "description": "Initialize PS/2 keyboard input subsystem.",
"title": "Scheduler Task: klogd", "description_zh": "初始化 PS/2 键盘输入子系统。",
"description": "Enable periodic klogd maintenance task.", "type": "bool",
"type": "bool", "default": true,
"default": true "imply": [
}, "CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY",
{ "CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS"
"key": "CLEONOS_CLKS_ENABLE_KWORKER_TASK", ]
"title": "Scheduler Task: kworker", },
"description": "Enable periodic kernel worker service-heartbeat task.", {
"type": "bool", "key": "CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE",
"default": true "title": "ELFRUNNER Probe",
}, "title_zh": "ELFRUNNER 探测",
{ "description": "Probe kernel ELF runtime metadata after ELFRUNNER init.",
"key": "CLEONOS_CLKS_ENABLE_USRD_TASK", "description_zh": "在 ELFRUNNER 初始化后探测内核 ELF 运行时元数据。",
"title": "Scheduler Task: usrd", "type": "bool",
"description": "Enable user/runtime dispatch task (shell tick, tty tick, exec tick).", "default": true,
"type": "bool", "depends_on": "CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT && CLEONOS_CLKS_ENABLE_KELF"
"default": true },
}, {
{ "key": "CLEONOS_CLKS_ENABLE_KLOGD_TASK",
"key": "CLEONOS_CLKS_ENABLE_BOOT_VIDEO_LOG", "title": "Scheduler Task: klogd",
"title": "Boot Video Geometry Logs", "title_zh": "调度任务klogd",
"description": "Print framebuffer width/height/pitch/bpp logs at boot.", "description": "Enable periodic klogd maintenance task.",
"type": "tristate", "description_zh": "启用周期性 klogd 维护任务。",
"default": "y" "type": "bool",
}, "default": true
{ },
"key": "CLEONOS_CLKS_ENABLE_PMM_STATS_LOG", {
"title": "PMM Stats Logs", "key": "CLEONOS_CLKS_ENABLE_KWORKER_TASK",
"description": "Print PMM managed/free/used/dropped pages at boot.", "title": "Scheduler Task: kworker",
"type": "tristate", "title_zh": "调度任务kworker",
"default": "y" "description": "Enable periodic kernel worker service-heartbeat task.",
}, "description_zh": "启用周期性内核 worker 服务心跳任务。",
{ "type": "bool",
"key": "CLEONOS_CLKS_ENABLE_HEAP_STATS_LOG", "default": true
"title": "Heap Stats Logs", },
"description": "Print heap total/free bytes at boot.", {
"type": "tristate", "key": "CLEONOS_CLKS_ENABLE_USRD_TASK",
"default": "y" "title": "Scheduler Task: usrd",
}, "title_zh": "调度任务usrd",
{ "description": "Enable user/runtime dispatch task (shell tick, tty tick, exec tick).",
"key": "CLEONOS_CLKS_ENABLE_FS_ROOT_LOG", "description_zh": "启用用户/运行时分发任务shell tick、tty tick、exec tick",
"title": "FS Root Children Log", "type": "bool",
"description": "Print root directory children count during FS init.", "default": true
"type": "tristate", },
"default": "y", {
"depends_on": "CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK" "key": "CLEONOS_CLKS_ENABLE_BOOT_VIDEO_LOG",
}, "title": "Boot Video Geometry Logs",
{ "title_zh": "启动视频几何日志",
"key": "CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK", "description": "Print framebuffer width/height/pitch/bpp logs at boot.",
"title": "FS /SYSTEM Sanity Check", "description_zh": "在启动时打印 framebuffer 宽/高/pitch/bpp 日志。",
"description": "Require /system directory check during boot.", "type": "tristate",
"type": "bool", "default": "y"
"default": true },
}, {
{ "key": "CLEONOS_CLKS_ENABLE_PMM_STATS_LOG",
"key": "CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT", "title": "PMM Stats Logs",
"title": "ELFRUNNER Init", "title_zh": "PMM 统计日志",
"description": "Initialize ELFRUNNER framework in kernel boot path.", "description": "Print PMM managed/free/used/dropped pages at boot.",
"type": "bool", "description_zh": "在启动时打印 PMM 托管/空闲/已用/丢弃页数。",
"default": true "type": "tristate",
}, "default": "y"
{ },
"key": "CLEONOS_CLKS_ENABLE_SYSCALL_TICK_QUERY", {
"title": "SYSCALL Tick Query", "key": "CLEONOS_CLKS_ENABLE_HEAP_STATS_LOG",
"description": "Query timer ticks via syscall and log result during boot.", "title": "Heap Stats Logs",
"type": "bool", "title_zh": "堆统计日志",
"default": true, "description": "Print heap total/free bytes at boot.",
"depends_on": "CLEONOS_CLKS_ENABLE_PROCFS" "description_zh": "在启动时打印堆总字节/空闲字节。",
}, "type": "tristate",
{ "default": "y"
"key": "CLEONOS_CLKS_ENABLE_TTY_READY_LOG", },
"title": "TTY Ready Logs", {
"description": "Print TTY count/active/cursor ready logs.", "key": "CLEONOS_CLKS_ENABLE_FS_ROOT_LOG",
"type": "tristate", "title": "FS Root Children Log",
"default": "y" "title_zh": "FS 根目录子项日志",
}, "description": "Print root directory children count during FS init.",
{ "description_zh": "在文件系统初始化时打印根目录子项数量。",
"key": "CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG", "type": "tristate",
"title": "Idle Loop Debug Log", "default": "y",
"description": "Print debug log before entering kernel idle loop.", "depends_on": "CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK"
"type": "tristate", },
"default": "y" {
}, "key": "CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK",
{ "title": "FS /SYSTEM Sanity Check",
"key": "CLEONOS_CLKS_ENABLE_PROCFS", "title_zh": "FS /SYSTEM 健全性检查",
"title": "Virtual /proc", "description": "Require /system directory check during boot.",
"description": "Enable virtual procfs paths (/proc, /proc/list, /proc/self, /proc/<pid>) in syscall FS layer.", "description_zh": "在启动时要求通过 /system 目录检查。",
"type": "bool", "type": "bool",
"default": true "default": true
}, },
{ {
"key": "CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG", "key": "CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT",
"title": "EXEC Serial Logs", "title": "ELFRUNNER Init",
"description": "Print EXEC run/return/path logs to serial output.", "title_zh": "ELFRUNNER 初始化",
"type": "tristate", "description": "Initialize ELFRUNNER framework in kernel boot path.",
"default": "y" "description_zh": "在内核启动路径中初始化 ELFRUNNER 框架。",
}, "type": "bool",
{ "default": true
"key": "CLEONOS_CLKS_ENABLE_USC", },
"title": "UserSafeController (USC)", {
"description": "Prompt before dangerous user syscalls and remember per-app approval for current boot.", "key": "CLEONOS_CLKS_ENABLE_SYSCALL_TICK_QUERY",
"type": "bool", "title": "SYSCALL Tick Query",
"default": true, "title_zh": "SYSCALL Tick 查询",
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD", "description": "Query timer ticks via syscall and log result during boot.",
"group": "USC Syscall Policy" "description_zh": "在启动时通过 syscall 查询定时器 tick 并记录日志。",
}, "type": "bool",
{ "default": true,
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_MKDIR", "depends_on": "CLEONOS_CLKS_ENABLE_PROCFS"
"title": "Intercept FS_MKDIR", },
"description": "USC prompt for syscall FS_MKDIR.", {
"type": "bool", "key": "CLEONOS_CLKS_ENABLE_TTY_READY_LOG",
"default": true, "title": "TTY Ready Logs",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "title_zh": "TTY 就绪日志",
"group": "USC Syscall Policy" "description": "Print TTY count/active/cursor ready logs.",
}, "description_zh": "打印 TTY 数量/活动终端/光标就绪日志。",
{ "type": "tristate",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_WRITE", "default": "y"
"title": "Intercept FS_WRITE", },
"description": "USC prompt for syscall FS_WRITE.", {
"type": "bool", "key": "CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG",
"default": true, "title": "Idle Loop Debug Log",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "title_zh": "空闲循环调试日志",
"group": "USC Syscall Policy" "description": "Print debug log before entering kernel idle loop.",
}, "description_zh": "进入内核空闲循环前打印调试日志。",
{ "type": "tristate",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_APPEND", "default": "y"
"title": "Intercept FS_APPEND", },
"description": "USC prompt for syscall FS_APPEND.", {
"type": "bool", "key": "CLEONOS_CLKS_ENABLE_PROCFS",
"default": true, "title": "Virtual /proc",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "title_zh": "虚拟 /proc",
"group": "USC Syscall Policy" "description": "Enable virtual procfs paths (/proc, /proc/list, /proc/self, /proc/<pid>) in syscall FS layer.",
}, "description_zh": "在 syscall 文件系统层启用虚拟 procfs 路径(/proc、/proc/list、/proc/self、/proc/<pid>)。",
{ "type": "bool",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_REMOVE", "default": true
"title": "Intercept FS_REMOVE", },
"description": "USC prompt for syscall FS_REMOVE.", {
"type": "bool", "key": "CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG",
"default": true, "title": "EXEC Serial Logs",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "title_zh": "EXEC 串口日志",
"group": "USC Syscall Policy" "description": "Print EXEC run/return/path logs to serial output.",
}, "description_zh": "将 EXEC run/return/path 日志输出到串口。",
{ "type": "tristate",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATH", "default": "y"
"title": "Intercept EXEC_PATH", },
"description": "USC prompt for syscall EXEC_PATH.", {
"type": "bool", "key": "CLEONOS_CLKS_ENABLE_SYSCALL_SERIAL_LOG",
"default": true, "title": "SYSCALL Serial Logs",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "title_zh": "SYSCALL 串口日志",
"group": "USC Syscall Policy" "description": "Print user syscall CALL/RET trace logs to serial output.",
}, "description_zh": "将用户态 syscall 的 CALL/RET 跟踪日志输出到串口。",
{ "type": "bool",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV", "default": true,
"title": "Intercept EXEC_PATHV", "group": "Logging Controls",
"description": "USC prompt for syscall EXEC_PATHV.", "group_zh": "日志控制"
"type": "bool", },
"default": true, {
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "key": "CLEONOS_CLKS_ENABLE_SYSCALL_USERID_SERIAL_LOG",
"group": "USC Syscall Policy" "title": "SYSCALL USER_ID Serial Logs",
}, "title_zh": "SYSCALL USER_ID 串口日志",
{ "description": "Print USER_TRACE_BEGIN/END, PID, and USER_ID trace logs to serial output.",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV_IO", "description_zh": "将 USER_TRACE_BEGIN/END、PID 与 USER_ID 跟踪日志输出到串口。",
"title": "Intercept EXEC_PATHV_IO", "type": "bool",
"description": "USC prompt for syscall EXEC_PATHV_IO.", "default": true,
"type": "bool", "group": "Logging Controls",
"default": true, "group_zh": "日志控制"
"depends_on": "CLEONOS_CLKS_ENABLE_USC", },
"group": "USC Syscall Policy" {
}, "key": "CLEONOS_CLKS_ENABLE_LOG_LEVEL_DEBUG",
{ "title": "Kernel Log Level: DEBUG",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATH", "title_zh": "内核日志级别DEBUG",
"title": "Intercept SPAWN_PATH", "description": "Allow CLKS_LOG_DEBUG messages to be emitted by clks_log/clks_log_hex.",
"description": "USC prompt for syscall SPAWN_PATH.", "description_zh": "允许 clks_log/clks_log_hex 输出 CLKS_LOG_DEBUG 消息。",
"type": "bool", "type": "bool",
"default": true, "default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "group": "Logging Controls",
"group": "USC Syscall Policy" "group_zh": "日志控制"
}, },
{ {
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATHV", "key": "CLEONOS_CLKS_ENABLE_LOG_LEVEL_INFO",
"title": "Intercept SPAWN_PATHV", "title": "Kernel Log Level: INFO",
"description": "USC prompt for syscall SPAWN_PATHV.", "title_zh": "内核日志级别INFO",
"type": "bool", "description": "Allow CLKS_LOG_INFO messages to be emitted by clks_log/clks_log_hex.",
"default": true, "description_zh": "允许 clks_log/clks_log_hex 输出 CLKS_LOG_INFO 消息。",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "type": "bool",
"group": "USC Syscall Policy" "default": true,
}, "group": "Logging Controls",
{ "group_zh": "日志控制"
"key": "CLEONOS_CLKS_ENABLE_USC_SC_PROC_KILL", },
"title": "Intercept PROC_KILL", {
"description": "USC prompt for syscall PROC_KILL.", "key": "CLEONOS_CLKS_ENABLE_LOG_LEVEL_WARN",
"type": "bool", "title": "Kernel Log Level: WARN",
"default": true, "title_zh": "内核日志级别WARN",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "description": "Allow CLKS_LOG_WARN messages to be emitted by clks_log/clks_log_hex.",
"group": "USC Syscall Policy" "description_zh": "允许 clks_log/clks_log_hex 输出 CLKS_LOG_WARN 消息。",
}, "type": "bool",
{ "default": true,
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SHUTDOWN", "group": "Logging Controls",
"title": "Intercept SHUTDOWN", "group_zh": "日志控制"
"description": "USC prompt for syscall SHUTDOWN.", },
"type": "bool", {
"default": true, "key": "CLEONOS_CLKS_ENABLE_LOG_LEVEL_ERROR",
"depends_on": "CLEONOS_CLKS_ENABLE_USC", "title": "Kernel Log Level: ERROR",
"group": "USC Syscall Policy" "title_zh": "内核日志级别ERROR",
}, "description": "Allow CLKS_LOG_ERROR messages to be emitted by clks_log/clks_log_hex.",
{ "description_zh": "允许 clks_log/clks_log_hex 输出 CLKS_LOG_ERROR 消息。",
"key": "CLEONOS_CLKS_ENABLE_USC_SC_RESTART", "type": "bool",
"title": "Intercept RESTART", "default": true,
"description": "USC prompt for syscall RESTART.", "group": "Logging Controls",
"type": "bool", "group_zh": "日志控制"
"default": true, },
"depends_on": "CLEONOS_CLKS_ENABLE_USC", {
"group": "USC Syscall Policy" "key": "CLEONOS_CLKS_ENABLE_LOG_OUTPUT_SERIAL",
}, "title": "Kernel Log Output: Serial",
{ "title_zh": "内核日志输出:串口",
"key": "CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY", "description": "Send clks_log/clks_log_hex output to serial port.",
"title": "Keyboard TTY Switch Hotkey", "description_zh": "将 clks_log/clks_log_hex 输出发送到串口。",
"description": "Enable ALT+F1..F4 keyboard hotkey for active TTY switching.", "type": "bool",
"type": "bool", "default": true,
"default": true, "group": "Logging Controls",
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD" "group_zh": "日志控制"
}, },
{ {
"key": "CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS", "key": "CLEONOS_CLKS_ENABLE_LOG_OUTPUT_TTY",
"title": "Keyboard Ctrl Shortcuts", "title": "Kernel Log Output: TTY",
"description": "Enable Ctrl+A/C/V shortcuts for input selection/copy/paste.", "title_zh": "内核日志输出TTY",
"type": "bool", "description": "Render clks_log/clks_log_hex output to TTY with ANSI colors.",
"default": true, "description_zh": "将 clks_log/clks_log_hex 输出渲染到 TTY含 ANSI 颜色)。",
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD", "type": "bool",
"imply": [ "default": true,
"CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY" "group": "Logging Controls",
] "group_zh": "日志控制"
}, },
{ {
"key": "CLEONOS_CLKS_ENABLE_KBD_FORCE_STOP_HOTKEY", "key": "CLEONOS_CLKS_ENABLE_LOG_OUTPUT_JOURNAL",
"title": "Keyboard Force-Stop Hotkey", "title": "Kernel Log Output: Journal",
"description": "Enable Ctrl+Alt+C force-stop for current running user process.", "title_zh": "内核日志输出:日志缓冲",
"type": "bool", "description": "Store clks_log/clks_log_hex lines into in-memory log journal for dmesg/procfs reads.",
"default": true, "description_zh": "将 clks_log/clks_log_hex 行写入内存日志缓冲,供 dmesg/procfs 读取。",
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD && CLEONOS_CLKS_ENABLE_PROCFS" "type": "bool",
}, "default": true,
{ "group": "Logging Controls",
"key": "CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE", "group_zh": "日志控制"
"title": "User Init Script Probe", },
"description": "Probe and log /shell/init.cmd presence during userland init.", {
"type": "bool", "key": "CLEONOS_CLKS_ENABLE_USC",
"default": true, "title": "UserSafeController (USC)",
"depends_on": "CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC" "title_zh": "用户安全控制器USC",
}, "description": "Prompt before dangerous user syscalls and remember per-app approval for current boot.",
{ "description_zh": "在危险用户态 syscall 执行前弹出确认,并在本次启动期间按应用记住授权。",
"key": "CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE", "type": "bool",
"title": "User System App Probe", "default": true,
"description": "Probe /system/elfrunner.elf and /system/memc.elf during userland init.", "depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD",
"type": "bool", "group": "USC Syscall Policy",
"default": true, "group_zh": "USC 系统调用策略"
"depends_on": "CLEONOS_CLKS_ENABLE_KELF" },
}, {
{ "key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_MKDIR",
"key": "CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG", "title": "Intercept FS_MKDIR",
"title": "Scheduler Task Count Log", "title_zh": "拦截 FS_MKDIR",
"description": "Print scheduler task count after scheduler initialization.", "description": "USC prompt for syscall FS_MKDIR.",
"type": "tristate", "description_zh": "USC 对 FS_MKDIR syscall 弹出确认。",
"default": "y", "type": "bool",
"depends_on": "CLEONOS_CLKS_ENABLE_KLOGD_TASK || CLEONOS_CLKS_ENABLE_KWORKER_TASK || CLEONOS_CLKS_ENABLE_USRD_TASK" "default": true,
}, "depends_on": "CLEONOS_CLKS_ENABLE_USC",
{ "group": "USC Syscall Policy",
"key": "CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG", "group_zh": "USC 系统调用策略"
"title": "Interrupt Ready Log", },
"description": "Print IDT/PIC initialized log after interrupt setup.", {
"type": "tristate", "key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_WRITE",
"default": "y" "title": "Intercept FS_WRITE",
}, "title_zh": "拦截 FS_WRITE",
{ "description": "USC prompt for syscall FS_WRITE.",
"key": "CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG", "description_zh": "USC 对 FS_WRITE syscall 弹出确认。",
"title": "Shell Mode Log", "type": "bool",
"description": "Print whether boot default mode is user shell or kernel shell.", "default": true,
"type": "tristate", "depends_on": "CLEONOS_CLKS_ENABLE_USC",
"default": "y" "group": "USC Syscall Policy",
} "group_zh": "USC 系统调用策略"
] },
} {
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_APPEND",
"title": "Intercept FS_APPEND",
"title_zh": "拦截 FS_APPEND",
"description": "USC prompt for syscall FS_APPEND.",
"description_zh": "USC 对 FS_APPEND syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_REMOVE",
"title": "Intercept FS_REMOVE",
"title_zh": "拦截 FS_REMOVE",
"description": "USC prompt for syscall FS_REMOVE.",
"description_zh": "USC 对 FS_REMOVE syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATH",
"title": "Intercept EXEC_PATH",
"title_zh": "拦截 EXEC_PATH",
"description": "USC prompt for syscall EXEC_PATH.",
"description_zh": "USC 对 EXEC_PATH syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV",
"title": "Intercept EXEC_PATHV",
"title_zh": "拦截 EXEC_PATHV",
"description": "USC prompt for syscall EXEC_PATHV.",
"description_zh": "USC 对 EXEC_PATHV syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV_IO",
"title": "Intercept EXEC_PATHV_IO",
"title_zh": "拦截 EXEC_PATHV_IO",
"description": "USC prompt for syscall EXEC_PATHV_IO.",
"description_zh": "USC 对 EXEC_PATHV_IO syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATH",
"title": "Intercept SPAWN_PATH",
"title_zh": "拦截 SPAWN_PATH",
"description": "USC prompt for syscall SPAWN_PATH.",
"description_zh": "USC 对 SPAWN_PATH syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATHV",
"title": "Intercept SPAWN_PATHV",
"title_zh": "拦截 SPAWN_PATHV",
"description": "USC prompt for syscall SPAWN_PATHV.",
"description_zh": "USC 对 SPAWN_PATHV syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_PROC_KILL",
"title": "Intercept PROC_KILL",
"title_zh": "拦截 PROC_KILL",
"description": "USC prompt for syscall PROC_KILL.",
"description_zh": "USC 对 PROC_KILL syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SHUTDOWN",
"title": "Intercept SHUTDOWN",
"title_zh": "拦截 SHUTDOWN",
"description": "USC prompt for syscall SHUTDOWN.",
"description_zh": "USC 对 SHUTDOWN syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_USC_SC_RESTART",
"title": "Intercept RESTART",
"title_zh": "拦截 RESTART",
"description": "USC prompt for syscall RESTART.",
"description_zh": "USC 对 RESTART syscall 弹出确认。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
"group": "USC Syscall Policy",
"group_zh": "USC 系统调用策略"
},
{
"key": "CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY",
"title": "Keyboard TTY Switch Hotkey",
"title_zh": "键盘 TTY 切换热键",
"description": "Enable ALT+F1..F4 keyboard hotkey for active TTY switching.",
"description_zh": "启用 ALT+F1..F4 热键切换当前活动 TTY。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD"
},
{
"key": "CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS",
"title": "Keyboard Ctrl Shortcuts",
"title_zh": "键盘 Ctrl 快捷键",
"description": "Enable Ctrl+A/C/V shortcuts for input selection/copy/paste.",
"description_zh": "启用 Ctrl+A/C/V 输入区全选/复制/粘贴快捷键。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD",
"imply": [
"CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY"
]
},
{
"key": "CLEONOS_CLKS_ENABLE_KBD_FORCE_STOP_HOTKEY",
"title": "Keyboard Force-Stop Hotkey",
"title_zh": "键盘强制停止热键",
"description": "Enable Ctrl+Alt+C force-stop for current running user process.",
"description_zh": "启用 Ctrl+Alt+C 强制停止当前运行的用户进程。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD && CLEONOS_CLKS_ENABLE_PROCFS"
},
{
"key": "CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE",
"title": "User Init Script Probe",
"title_zh": "用户初始化脚本探测",
"description": "Probe and log /shell/init.cmd presence during userland init.",
"description_zh": "在用户态初始化期间探测并记录 /shell/init.cmd 是否存在。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC"
},
{
"key": "CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE",
"title": "User System App Probe",
"title_zh": "用户系统应用探测",
"description": "Probe /system/elfrunner.elf and /system/memc.elf during userland init.",
"description_zh": "在用户态初始化期间探测 /system/elfrunner.elf 与 /system/memc.elf。",
"type": "bool",
"default": true,
"depends_on": "CLEONOS_CLKS_ENABLE_KELF"
},
{
"key": "CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG",
"title": "Scheduler Task Count Log",
"title_zh": "调度任务数量日志",
"description": "Print scheduler task count after scheduler initialization.",
"description_zh": "在调度器初始化后打印任务数量。",
"type": "tristate",
"default": "y",
"depends_on": "CLEONOS_CLKS_ENABLE_KLOGD_TASK || CLEONOS_CLKS_ENABLE_KWORKER_TASK || CLEONOS_CLKS_ENABLE_USRD_TASK"
},
{
"key": "CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG",
"title": "Interrupt Ready Log",
"title_zh": "中断就绪日志",
"description": "Print IDT/PIC initialized log after interrupt setup.",
"description_zh": "在完成中断初始化后打印 IDT/PIC 就绪日志。",
"type": "tristate",
"default": "y"
},
{
"key": "CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG",
"title": "Shell Mode Log",
"title_zh": "Shell 模式日志",
"description": "Print whether boot default mode is user shell or kernel shell.",
"description_zh": "打印默认启动模式是用户 Shell 还是内核 Shell。",
"type": "tristate",
"default": "y"
}
]
}

View File

@@ -21,6 +21,7 @@ set(CLEONOS_USER_APP_DOOM ON CACHE BOOL "doom.elf [shell]" FORCE)
set(CLEONOS_USER_APP_EXEC ON CACHE BOOL "exec.elf [shell]" FORCE) set(CLEONOS_USER_APP_EXEC ON CACHE BOOL "exec.elf [shell]" FORCE)
set(CLEONOS_USER_APP_EXIT ON CACHE BOOL "exit.elf [shell]" FORCE) set(CLEONOS_USER_APP_EXIT ON CACHE BOOL "exit.elf [shell]" FORCE)
set(CLEONOS_USER_APP_FASTFETCH ON CACHE BOOL "fastfetch.elf [shell]" FORCE) set(CLEONOS_USER_APP_FASTFETCH ON CACHE BOOL "fastfetch.elf [shell]" FORCE)
set(CLEONOS_USER_APP_FDTEST ON CACHE BOOL "fdtest.elf [shell]" FORCE)
set(CLEONOS_USER_APP_FG ON CACHE BOOL "fg.elf [shell]" FORCE) set(CLEONOS_USER_APP_FG ON CACHE BOOL "fg.elf [shell]" FORCE)
set(CLEONOS_USER_APP_FSSTAT ON CACHE BOOL "fsstat.elf [shell]" FORCE) set(CLEONOS_USER_APP_FSSTAT ON CACHE BOOL "fsstat.elf [shell]" FORCE)
set(CLEONOS_USER_APP_GREP ON CACHE BOOL "grep.elf [shell]" FORCE) set(CLEONOS_USER_APP_GREP ON CACHE BOOL "grep.elf [shell]" FORCE)

View File

@@ -1,58 +1,67 @@
# Auto-generated by scripts/menuconfig.py # Auto-generated by scripts/menuconfig.py
# Do not edit manually unless you know what you are doing. # Do not edit manually unless you know what you are doing.
set(CLEONOS_MENUCONFIG_CLKS_LOADED ON CACHE BOOL "CLeonOS menuconfig loaded" FORCE) set(CLEONOS_MENUCONFIG_CLKS_LOADED ON CACHE BOOL "CLeonOS menuconfig loaded" FORCE)
set(CLEONOS_CLKS_ENABLE_AUDIO ON CACHE BOOL "Audio Driver Init" FORCE) set(CLEONOS_CLKS_ENABLE_AUDIO ON CACHE BOOL "音频驱动初始化" FORCE)
set(CLEONOS_CLKS_ENABLE_MOUSE ON CACHE BOOL "PS/2 Mouse Input" FORCE) set(CLEONOS_CLKS_ENABLE_MOUSE ON CACHE BOOL "PS/2 鼠标输入" FORCE)
set(CLEONOS_CLKS_ENABLE_DESKTOP ON CACHE BOOL "TTY2 Desktop" FORCE) set(CLEONOS_CLKS_ENABLE_DESKTOP ON CACHE BOOL "TTY2 桌面" FORCE)
set(CLEONOS_CLKS_ENABLE_DRIVER_MANAGER ON CACHE BOOL "Driver Manager" FORCE) set(CLEONOS_CLKS_ENABLE_DRIVER_MANAGER ON CACHE BOOL "驱动管理器" FORCE)
set(CLEONOS_CLKS_ENABLE_KELF ON CACHE BOOL "KELF Executor" FORCE) set(CLEONOS_CLKS_ENABLE_KELF ON CACHE BOOL "KELF 执行器" FORCE)
set(CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC ON CACHE BOOL "Auto Enter User Shell" FORCE) set(CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC ON CACHE BOOL "自动进入用户 Shell" FORCE)
set(CLEONOS_CLKS_ENABLE_HEAP_SELFTEST ON CACHE BOOL "Heap Selftest" FORCE) set(CLEONOS_CLKS_ENABLE_HEAP_SELFTEST ON CACHE BOOL "堆自检" FORCE)
set(CLEONOS_CLKS_ENABLE_EXTERNAL_PSF ON CACHE BOOL "Load External PSF Font" FORCE) set(CLEONOS_CLKS_ENABLE_EXTERNAL_PSF ON CACHE BOOL "加载外部 PSF 字体" FORCE)
set(CLEONOS_CLKS_ENABLE_KEYBOARD ON CACHE BOOL "PS/2 Keyboard Input" FORCE) set(CLEONOS_CLKS_ENABLE_KEYBOARD ON CACHE BOOL "PS/2 键盘输入" FORCE)
set(CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE ON CACHE BOOL "ELFRUNNER Probe" FORCE) set(CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE ON CACHE BOOL "ELFRUNNER 探测" FORCE)
set(CLEONOS_CLKS_ENABLE_KLOGD_TASK ON CACHE BOOL "Scheduler Task: klogd" FORCE) set(CLEONOS_CLKS_ENABLE_KLOGD_TASK ON CACHE BOOL "调度任务:klogd" FORCE)
set(CLEONOS_CLKS_ENABLE_KWORKER_TASK ON CACHE BOOL "Scheduler Task: kworker" FORCE) set(CLEONOS_CLKS_ENABLE_KWORKER_TASK ON CACHE BOOL "调度任务:kworker" FORCE)
set(CLEONOS_CLKS_ENABLE_USRD_TASK ON CACHE BOOL "Scheduler Task: usrd" FORCE) set(CLEONOS_CLKS_ENABLE_USRD_TASK ON CACHE BOOL "调度任务:usrd" FORCE)
set(CLEONOS_CLKS_ENABLE_BOOT_VIDEO_LOG "M" CACHE STRING "Boot Video Geometry Logs" FORCE) set(CLEONOS_CLKS_ENABLE_BOOT_VIDEO_LOG "M" CACHE STRING "启动视频几何日志" FORCE)
set(CLEONOS_CLKS_ENABLE_BOOT_VIDEO_LOG_IS_ENABLED ON CACHE BOOL "Boot Video Geometry Logs enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_BOOT_VIDEO_LOG_IS_ENABLED ON CACHE BOOL "启动视频几何日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_PMM_STATS_LOG "M" CACHE STRING "PMM Stats Logs" FORCE) set(CLEONOS_CLKS_ENABLE_PMM_STATS_LOG "M" CACHE STRING "PMM 统计日志" FORCE)
set(CLEONOS_CLKS_ENABLE_PMM_STATS_LOG_IS_ENABLED ON CACHE BOOL "PMM Stats Logs enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_PMM_STATS_LOG_IS_ENABLED ON CACHE BOOL "PMM 统计日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_HEAP_STATS_LOG "M" CACHE STRING "Heap Stats Logs" FORCE) set(CLEONOS_CLKS_ENABLE_HEAP_STATS_LOG "M" CACHE STRING "堆统计日志" FORCE)
set(CLEONOS_CLKS_ENABLE_HEAP_STATS_LOG_IS_ENABLED ON CACHE BOOL "Heap Stats Logs enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_HEAP_STATS_LOG_IS_ENABLED ON CACHE BOOL "堆统计日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_FS_ROOT_LOG "M" CACHE STRING "FS Root Children Log" FORCE) set(CLEONOS_CLKS_ENABLE_FS_ROOT_LOG "M" CACHE STRING "FS 根目录子项日志" FORCE)
set(CLEONOS_CLKS_ENABLE_FS_ROOT_LOG_IS_ENABLED ON CACHE BOOL "FS Root Children Log enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_FS_ROOT_LOG_IS_ENABLED ON CACHE BOOL "FS 根目录子项日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK ON CACHE BOOL "FS /SYSTEM Sanity Check" FORCE) set(CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK ON CACHE BOOL "FS /SYSTEM 健全性检查" FORCE)
set(CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT ON CACHE BOOL "ELFRUNNER Init" FORCE) set(CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT ON CACHE BOOL "ELFRUNNER 初始化" FORCE)
set(CLEONOS_CLKS_ENABLE_SYSCALL_TICK_QUERY ON CACHE BOOL "SYSCALL Tick Query" FORCE) set(CLEONOS_CLKS_ENABLE_SYSCALL_TICK_QUERY ON CACHE BOOL "SYSCALL Tick 查询" FORCE)
set(CLEONOS_CLKS_ENABLE_TTY_READY_LOG "M" CACHE STRING "TTY Ready Logs" FORCE) set(CLEONOS_CLKS_ENABLE_TTY_READY_LOG "M" CACHE STRING "TTY 就绪日志" FORCE)
set(CLEONOS_CLKS_ENABLE_TTY_READY_LOG_IS_ENABLED ON CACHE BOOL "TTY Ready Logs enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_TTY_READY_LOG_IS_ENABLED ON CACHE BOOL "TTY 就绪日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG "M" CACHE STRING "Idle Loop Debug Log" FORCE) set(CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG "M" CACHE STRING "空闲循环调试日志" FORCE)
set(CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG_IS_ENABLED ON CACHE BOOL "Idle Loop Debug Log enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG_IS_ENABLED ON CACHE BOOL "空闲循环调试日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_PROCFS ON CACHE BOOL "Virtual /proc" FORCE) set(CLEONOS_CLKS_ENABLE_PROCFS ON CACHE BOOL "虚拟 /proc" FORCE)
set(CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG "M" CACHE STRING "EXEC Serial Logs" FORCE) set(CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG "M" CACHE STRING "EXEC 串口日志" FORCE)
set(CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG_IS_ENABLED ON CACHE BOOL "EXEC Serial Logs enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG_IS_ENABLED ON CACHE BOOL "EXEC 串口日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_USC ON CACHE BOOL "UserSafeController (USC)" FORCE) set(CLEONOS_CLKS_ENABLE_SYSCALL_SERIAL_LOG OFF CACHE BOOL "SYSCALL 串口日志" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_FS_MKDIR OFF CACHE BOOL "Intercept FS_MKDIR" FORCE) set(CLEONOS_CLKS_ENABLE_SYSCALL_USERID_SERIAL_LOG OFF CACHE BOOL "SYSCALL USER_ID 串口日志" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_FS_WRITE OFF CACHE BOOL "Intercept FS_WRITE" FORCE) set(CLEONOS_CLKS_ENABLE_LOG_LEVEL_DEBUG ON CACHE BOOL "内核日志级别DEBUG" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_FS_APPEND OFF CACHE BOOL "Intercept FS_APPEND" FORCE) set(CLEONOS_CLKS_ENABLE_LOG_LEVEL_INFO ON CACHE BOOL "内核日志级别INFO" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_FS_REMOVE OFF CACHE BOOL "Intercept FS_REMOVE" FORCE) set(CLEONOS_CLKS_ENABLE_LOG_LEVEL_WARN ON CACHE BOOL "内核日志级别WARN" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATH ON CACHE BOOL "Intercept EXEC_PATH" FORCE) set(CLEONOS_CLKS_ENABLE_LOG_LEVEL_ERROR ON CACHE BOOL "内核日志级别ERROR" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV ON CACHE BOOL "Intercept EXEC_PATHV" FORCE) set(CLEONOS_CLKS_ENABLE_LOG_OUTPUT_SERIAL ON CACHE BOOL "内核日志输出:串口" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV_IO OFF CACHE BOOL "Intercept EXEC_PATHV_IO" FORCE) set(CLEONOS_CLKS_ENABLE_LOG_OUTPUT_TTY ON CACHE BOOL "内核日志输出TTY" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATH ON CACHE BOOL "Intercept SPAWN_PATH" FORCE) set(CLEONOS_CLKS_ENABLE_LOG_OUTPUT_JOURNAL ON CACHE BOOL "内核日志输出:日志缓冲" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATHV ON CACHE BOOL "Intercept SPAWN_PATHV" FORCE) set(CLEONOS_CLKS_ENABLE_USC ON CACHE BOOL "用户安全控制器USC" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_PROC_KILL ON CACHE BOOL "Intercept PROC_KILL" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_FS_MKDIR OFF CACHE BOOL "拦截 FS_MKDIR" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_SHUTDOWN ON CACHE BOOL "Intercept SHUTDOWN" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_FS_WRITE OFF CACHE BOOL "拦截 FS_WRITE" FORCE)
set(CLEONOS_CLKS_ENABLE_USC_SC_RESTART ON CACHE BOOL "Intercept RESTART" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_FS_APPEND OFF CACHE BOOL "拦截 FS_APPEND" FORCE)
set(CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY ON CACHE BOOL "Keyboard TTY Switch Hotkey" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_FS_REMOVE OFF CACHE BOOL "拦截 FS_REMOVE" FORCE)
set(CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS ON CACHE BOOL "Keyboard Ctrl Shortcuts" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATH ON CACHE BOOL "拦截 EXEC_PATH" FORCE)
set(CLEONOS_CLKS_ENABLE_KBD_FORCE_STOP_HOTKEY ON CACHE BOOL "Keyboard Force-Stop Hotkey" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV ON CACHE BOOL "拦截 EXEC_PATHV" FORCE)
set(CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE ON CACHE BOOL "User Init Script Probe" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV_IO OFF CACHE BOOL "拦截 EXEC_PATHV_IO" FORCE)
set(CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE ON CACHE BOOL "User System App Probe" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATH ON CACHE BOOL "拦截 SPAWN_PATH" FORCE)
set(CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG "Y" CACHE STRING "Scheduler Task Count Log" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATHV ON CACHE BOOL "拦截 SPAWN_PATHV" FORCE)
set(CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG_IS_ENABLED ON CACHE BOOL "Scheduler Task Count Log enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_PROC_KILL ON CACHE BOOL "拦截 PROC_KILL" FORCE)
set(CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG "M" CACHE STRING "Interrupt Ready Log" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_SHUTDOWN ON CACHE BOOL "拦截 SHUTDOWN" FORCE)
set(CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG_IS_ENABLED ON CACHE BOOL "Interrupt Ready Log enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_USC_SC_RESTART ON CACHE BOOL "拦截 RESTART" FORCE)
set(CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG "M" CACHE STRING "Shell Mode Log" FORCE) set(CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY ON CACHE BOOL "键盘 TTY 切换热键" FORCE)
set(CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG_IS_ENABLED ON CACHE BOOL "Shell Mode Log enabled(y|m)" FORCE) set(CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS ON CACHE BOOL "键盘 Ctrl 快捷键" FORCE)
set(CLEONOS_CLKS_ENABLE_KBD_FORCE_STOP_HOTKEY ON CACHE BOOL "键盘强制停止热键" FORCE)
set(CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE ON CACHE BOOL "用户初始化脚本探测" FORCE)
set(CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE ON CACHE BOOL "用户系统应用探测" FORCE)
set(CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG "Y" CACHE STRING "调度任务数量日志" FORCE)
set(CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG_IS_ENABLED ON CACHE BOOL "调度任务数量日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG "M" CACHE STRING "中断就绪日志" FORCE)
set(CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG_IS_ENABLED ON CACHE BOOL "中断就绪日志 enabled(y|m)" FORCE)
set(CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG "M" CACHE STRING "Shell 模式日志" FORCE)
set(CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG_IS_ENABLED ON CACHE BOOL "Shell 模式日志 enabled(y|m)" FORCE)

View File

@@ -53,6 +53,38 @@ CONFIG_CLEONOS_JSON_PATH = MENUCONFIG_DIR / ".config.cleonos.json"
CONFIG_CLKS_CMAKE_PATH = MENUCONFIG_DIR / "config.clks.cmake" CONFIG_CLKS_CMAKE_PATH = MENUCONFIG_DIR / "config.clks.cmake"
CONFIG_CLEONOS_CMAKE_PATH = MENUCONFIG_DIR / "config.cleonos.cmake" CONFIG_CLEONOS_CMAKE_PATH = MENUCONFIG_DIR / "config.cleonos.cmake"
MENUCONFIG_LANG = "en"
def _is_zh() -> bool:
return MENUCONFIG_LANG == "zh-CN"
def _t(en: str, zh: str) -> str:
return zh if _is_zh() else en
def _resolve_language(requested: str) -> str:
token = str(requested or "auto").strip().lower()
if token in {"zh", "zh-cn", "zh_cn"}:
return "zh-CN"
if token == "en":
return "en"
if token != "auto":
return "en"
env_candidates = (
os.environ.get("LC_ALL", ""),
os.environ.get("LC_MESSAGES", ""),
os.environ.get("LANG", ""),
)
for value in env_candidates:
text = str(value).strip().lower()
if text.startswith("zh"):
return "zh-CN"
return "en"
@dataclass(frozen=True) @dataclass(frozen=True)
class OptionItem: class OptionItem:
@@ -314,14 +346,20 @@ def load_clks_options() -> List[OptionItem]:
if not isinstance(entry, dict): if not isinstance(entry, dict):
continue continue
key = str(entry.get("key", "")).strip() key = str(entry.get("key", "")).strip()
title = str(entry.get("title", key)).strip() title_key = "title_zh" if _is_zh() else "title"
description = str(entry.get("description", "")).strip() desc_key = "description_zh" if _is_zh() else "description"
group_key = "group_zh" if _is_zh() else "group"
title = str(entry.get(title_key, entry.get("title", key))).strip()
description = str(entry.get(desc_key, entry.get("description", ""))).strip()
kind = normalize_kind(entry.get("type", "bool")) kind = normalize_kind(entry.get("type", "bool"))
default = normalize_tri(entry.get("default", TRI_Y), TRI_Y, kind) default = normalize_tri(entry.get("default", TRI_Y), TRI_Y, kind)
depends_on = str(entry.get("depends_on", entry.get("depends", ""))).strip() depends_on = str(entry.get("depends_on", entry.get("depends", ""))).strip()
selects = _normalize_key_list(entry.get("select", entry.get("selects", ()))) selects = _normalize_key_list(entry.get("select", entry.get("selects", ())))
implies = _normalize_key_list(entry.get("imply", entry.get("implies", ()))) implies = _normalize_key_list(entry.get("imply", entry.get("implies", ())))
group = str(entry.get("group", entry.get("menu", "General"))).strip() or "General" group = str(entry.get(group_key, entry.get("group", entry.get("menu", _t("General", "通用"))))).strip() or _t(
"General", "通用"
)
if not key: if not key:
continue continue
options.append( options.append(
@@ -378,7 +416,10 @@ def discover_user_apps() -> List[OptionItem]:
for app, section in final_apps: for app, section in final_apps:
key = f"CLEONOS_USER_APP_{sanitize_token(app)}" key = f"CLEONOS_USER_APP_{sanitize_token(app)}"
title = f"{app}.elf [{section}]" title = f"{app}.elf [{section}]"
description = f"Build and package user app '{app}' into ramdisk/{section}." if _is_zh():
description = f"构建并打包用户应用 '{app}' 到 ramdisk/{section}"
else:
description = f"Build and package user app '{app}' into ramdisk/{section}."
options.append( options.append(
OptionItem( OptionItem(
key=key, key=key,
@@ -729,34 +770,34 @@ def _detail_lines(item: OptionItem, values: Dict[str, int], ev: EvalResult) -> L
allowed = ",".join(tri_char(v) for v in _allowed_values(item, floor_val, ceil_val)) allowed = ",".join(tri_char(v) for v in _allowed_values(item, floor_val, ceil_val))
lines = [ lines = [
f"kind: {item.kind}", f"{_t('kind', '类型')}: {item.kind}",
f"requested: {tri_char(req)}", f"{_t('requested', '请求值')}: {tri_char(req)}",
f"effective: {tri_char(eff)}", f"{_t('effective', '生效值')}: {tri_char(eff)}",
f"visible: {'yes' if visible else 'no'}", f"{_t('visible', '可见')}: {_t('yes', '') if visible else _t('no', '')}",
f"allowed: {allowed}", f"{_t('allowed', '可选')}: {allowed}",
f"depends: {item.depends_on or '<none>'}", f"{_t('depends', '依赖')}: {item.depends_on or _t('<none>', '<无>')}",
] ]
symbols = ev.depends_symbols.get(item.key, []) symbols = ev.depends_symbols.get(item.key, [])
if symbols: if symbols:
parts = [f"{sym}={tri_char(ev.effective.get(sym, TRI_N))}" for sym in symbols] parts = [f"{sym}={tri_char(ev.effective.get(sym, TRI_N))}" for sym in symbols]
lines.append("depends values: " + ", ".join(parts)) lines.append(_t("depends values: ", "依赖值: ") + ", ".join(parts))
else: else:
lines.append("depends values: <none>") lines.append(_t("depends values: <none>", "依赖值: <无>"))
sel = ev.selected_by.get(item.key, []) sel = ev.selected_by.get(item.key, [])
imp = ev.implied_by.get(item.key, []) imp = ev.implied_by.get(item.key, [])
lines.append("selected by: " + (", ".join(sel) if sel else "<none>")) lines.append(_t("selected by: ", "被选择自: ") + (", ".join(sel) if sel else _t("<none>", "<无>")))
lines.append("implied by: " + (", ".join(imp) if imp else "<none>")) lines.append(_t("implied by: ", "被蕴含自: ") + (", ".join(imp) if imp else _t("<none>", "<无>")))
return lines return lines
def _tri_word(value: int) -> str: def _tri_word(value: int) -> str:
if value >= TRI_Y: if value >= TRI_Y:
return "Enabled" return _t("Enabled", "启用")
if value >= TRI_M: if value >= TRI_M:
return "Module" return _t("Module", "模块")
return "Disabled" return _t("Disabled", "禁用")
def _detail_lines_human(item: OptionItem, values: Dict[str, int], ev: EvalResult) -> List[str]: def _detail_lines_human(item: OptionItem, values: Dict[str, int], ev: EvalResult) -> List[str]:
@@ -771,26 +812,26 @@ def _detail_lines_human(item: OptionItem, values: Dict[str, int], ev: EvalResult
if symbols: if symbols:
dep_values = ", ".join(f"{sym}={tri_char(ev.effective.get(sym, TRI_N))}" for sym in symbols) dep_values = ", ".join(f"{sym}={tri_char(ev.effective.get(sym, TRI_N))}" for sym in symbols)
else: else:
dep_values = "<none>" dep_values = _t("<none>", "<无>")
selected_chain = ", ".join(ev.selected_by.get(item.key, [])) or "<none>" selected_chain = ", ".join(ev.selected_by.get(item.key, [])) or _t("<none>", "<无>")
implied_chain = ", ".join(ev.implied_by.get(item.key, [])) or "<none>" implied_chain = ", ".join(ev.implied_by.get(item.key, [])) or _t("<none>", "<无>")
allowed_text = "/".join(f"{tri_char(v)}({_tri_word(v)})" for v in allowed_vals) allowed_text = "/".join(f"{tri_char(v)}({_tri_word(v)})" for v in allowed_vals)
return [ return [
"State:", _t("State:", "状态:"),
f" Running now : {tri_char(eff)} ({_tri_word(eff)})", f" {_t('Running now', '当前生效'):12s} : {tri_char(eff)} ({_tri_word(eff)})",
f" Your choice : {tri_char(req)} ({_tri_word(req)})", f" {_t('Your choice', '你的选择'):12s} : {tri_char(req)} ({_tri_word(req)})",
f" Type : {item.kind}", f" {_t('Type', '类型'):12s} : {item.kind}",
f" Visible : {'yes' if visible else 'no'}", f" {_t('Visible', '可见'):12s} : {_t('yes', '') if visible else _t('no', '')}",
f" Allowed now : {allowed_text}", f" {_t('Allowed now', '当前可选'):12s} : {allowed_text}",
"Why:", _t("Why:", "原因:"),
f" depends on : {item.depends_on or '<none>'}", f" {_t('depends on', '依赖于'):12s} : {item.depends_on or _t('<none>', '<无>')}",
f" depends value : {dep_values}", f" {_t('depends value', '依赖值'):12s} : {dep_values}",
f" selected by : {selected_chain}", f" {_t('selected by', '被选择自'):12s} : {selected_chain}",
f" implied by : {implied_chain}", f" {_t('implied by', '被蕴含自'):12s} : {implied_chain}",
"Notes:", _t("Notes:", "说明:"),
" [a/b] in list means [effective/requested].", _t(" [a/b] in list means [effective/requested].", " 列表中的 [a/b] 表示 [生效值/请求值]。"),
f" {item.description}", f" {item.description}",
] ]
@@ -817,15 +858,20 @@ def print_section(title: str, section_options: List[OptionItem], all_options: Li
flags.append("implied") flags.append("implied")
flag_text = f" ({', '.join(flags)})" if flags else "" flag_text = f" ({', '.join(flags)})" if flags else ""
print(f"{idx:3d}. [{tri_char(eff)}|{tri_char(req)}] {item.title}{flag_text}") print(f"{idx:3d}. [{tri_char(eff)}|{tri_char(req)}] {item.title}{flag_text}")
print("Commands: <number> cycle, a all->y, n all->n, m all->m, i <n> info, b back") print(
print("Legend: [effective|requested], states: y/m/n") _t(
"Commands: <number> cycle, a all->y, n all->n, m all->m, i <n> info, b back",
"命令: <编号> 切换, a 全部->y, n 全部->n, m 全部->m, i <n> 详情, b 返回",
)
)
print(_t("Legend: [effective|requested], states: y/m/n", "图例: [生效值|请求值], 状态: y/m/n"))
def section_loop(title: str, section_options: List[OptionItem], all_options: List[OptionItem], values: Dict[str, int]) -> None: def section_loop(title: str, section_options: List[OptionItem], all_options: List[OptionItem], values: Dict[str, int]) -> None:
while True: while True:
ev = evaluate_config(all_options, values) ev = evaluate_config(all_options, values)
print_section(title, section_options, all_options, values) print_section(title, section_options, all_options, values)
raw = input(f"{title}> ").strip() raw = input(f"{title}{_t('> ', '> ')}").strip()
if not raw: if not raw:
continue continue
lower = raw.lower() lower = raw.lower()
@@ -852,12 +898,12 @@ def section_loop(title: str, section_options: List[OptionItem], all_options: Lis
item = section_options[idx - 1] item = section_options[idx - 1]
print() print()
print(f"[{idx}] {item.title}") print(f"[{idx}] {item.title}")
print(f"key: {item.key}") print(f"{_t('key', '键名')}: {item.key}")
for line in _detail_lines(item, values, ev): for line in _detail_lines(item, values, ev):
print(line) print(line)
print(f"desc: {item.description}") print(f"{_t('desc', '描述')}: {item.description}")
continue continue
print("invalid info index") print(_t("invalid info index", "无效的详情编号"))
continue continue
if raw.isdigit(): if raw.isdigit():
@@ -866,10 +912,10 @@ def section_loop(title: str, section_options: List[OptionItem], all_options: Lis
item = section_options[idx - 1] item = section_options[idx - 1]
_cycle_option_value(values, item, ev) _cycle_option_value(values, item, ev)
else: else:
print("invalid index") print(_t("invalid index", "无效编号"))
continue continue
print("unknown command") print(_t("unknown command", "未知命令"))
def grouped_section_loop( def grouped_section_loop(
@@ -887,19 +933,22 @@ def grouped_section_loop(
while True: while True:
ev = evaluate_config(all_options, values) ev = evaluate_config(all_options, values)
print() print()
print(f"== {title} / Groups ==") print(f"== {title} / {_t('Groups', '分组')} ==")
print(f" 0. All ({_group_enabled_count(section_options, ev)}/{len(section_options)} enabled)") print(
f" 0. {_t('All', '全部')} ({_group_enabled_count(section_options, ev)}/{len(section_options)} "
f"{_t('enabled', '已启用')})"
)
for idx, (name, opts) in enumerate(groups, start=1): for idx, (name, opts) in enumerate(groups, start=1):
print(f"{idx:3d}. {name} ({_group_enabled_count(opts, ev)}/{len(opts)} enabled)") print(f"{idx:3d}. {name} ({_group_enabled_count(opts, ev)}/{len(opts)} {_t('enabled', '已启用')})")
print("Commands: <number> open, b back") print(_t("Commands: <number> open, b back", "命令: <编号> 打开, b 返回"))
raw = input(f"{title}/groups> ").strip().lower() raw = input(f"{title}/{_t('groups', 'groups')}> ").strip().lower()
if not raw: if not raw:
continue continue
if raw in {"b", "back", "q", "quit"}: if raw in {"b", "back", "q", "quit"}:
return return
if not raw.isdigit(): if not raw.isdigit():
print("invalid selection") print(_t("invalid selection", "无效选择"))
continue continue
idx = int(raw) idx = int(raw)
@@ -910,7 +959,7 @@ def grouped_section_loop(
group_name, group_items = groups[idx - 1] group_name, group_items = groups[idx - 1]
section_loop(f"{title}/{group_name}", group_items, all_options, values) section_loop(f"{title}/{group_name}", group_items, all_options, values)
continue continue
print("invalid selection") print(_t("invalid selection", "无效选择"))
def _safe_addnstr(stdscr, y: int, x: int, text: str, attr: int = 0) -> None: def _safe_addnstr(stdscr, y: int, x: int, text: str, attr: int = 0) -> None:
@@ -1122,8 +1171,14 @@ def _run_ncurses_section(
h, w = stdscr.getmaxyx() h, w = stdscr.getmaxyx()
if h < 14 or w < 70: if h < 14 or w < 70:
_safe_addnstr(stdscr, 0, 0, "Terminal too small for rich UI (need >= 70x14).", theme["status_warn"]) _safe_addnstr(
_safe_addnstr(stdscr, 2, 0, "Resize terminal then press any key, or ESC to go back.") stdscr,
0,
0,
_t("Terminal too small for rich UI (need >= 70x14).", "终端太小,无法显示完整界面(至少需要 70x14"),
theme["status_warn"],
)
_safe_addnstr(stdscr, 2, 0, _t("Resize terminal then press any key, or ESC to go back.", "请调整终端大小后按任意键,或按 ESC 返回。"))
key = stdscr.getch() key = stdscr.getch()
if key in (27,): if key in (27,):
return return
@@ -1152,12 +1207,33 @@ def _run_ncurses_section(
stdscr, stdscr,
1, 1,
0, 0,
f" on:{enabled_count} mod:{module_count} total:{len(section_options)} | Space cycle a/n/m all Enter/ESC back ", (
f" {_t('on', '')}:{enabled_count} {_t('mod', '')}:{module_count} {_t('total', '总数')}:{len(section_options)}"
f" | {_t('Space cycle', '空格切换')} a/n/m {_t('all', '全部')} Enter/ESC {_t('back', '返回')} "
),
theme["subtitle"], theme["subtitle"],
) )
_draw_box(stdscr, list_box_y, list_box_x, list_box_h, list_box_w, "Options", theme["panel_border"], theme["panel_title"]) _draw_box(
_draw_box(stdscr, detail_box_y, detail_box_x, detail_box_h, detail_box_w, "Details", theme["panel_border"], theme["panel_title"]) stdscr,
list_box_y,
list_box_x,
list_box_h,
list_box_w,
_t("Options", "选项"),
theme["panel_border"],
theme["panel_title"],
)
_draw_box(
stdscr,
detail_box_y,
detail_box_x,
detail_box_h,
detail_box_w,
_t("Details", "详情"),
theme["panel_border"],
theme["panel_title"],
)
list_inner_y = list_box_y + 1 list_inner_y = list_box_y + 1
list_inner_x = list_box_x + 1 list_inner_x = list_box_x + 1
@@ -1219,12 +1295,12 @@ def _run_ncurses_section(
_safe_addnstr(stdscr, detail_inner_y + 0, detail_inner_x, cur.title, theme["value_label"]) _safe_addnstr(stdscr, detail_inner_y + 0, detail_inner_x, cur.title, theme["value_label"])
_safe_addnstr(stdscr, detail_inner_y + 1, detail_inner_x, cur.key, theme["value_key"]) _safe_addnstr(stdscr, detail_inner_y + 1, detail_inner_x, cur.key, theme["value_key"])
_safe_addnstr(stdscr, detail_inner_y + 2, detail_inner_x, f"State: {state_text}", state_attr) _safe_addnstr(stdscr, detail_inner_y + 2, detail_inner_x, f"{_t('State', '状态')}: {state_text}", state_attr)
_safe_addnstr( _safe_addnstr(
stdscr, stdscr,
detail_inner_y + 3, detail_inner_y + 3,
detail_inner_x, detail_inner_x,
f"Item: {selected + 1}/{len(section_options)} flags: {_option_flags(cur, ev)}", f"{_t('Item', '条目')}: {selected + 1}/{len(section_options)} {_t('flags', '标记')}: {_option_flags(cur, ev)}",
theme["value_label"], theme["value_label"],
) )
_draw_progress_bar( _draw_progress_bar(
@@ -1239,7 +1315,7 @@ def _run_ncurses_section(
) )
desc_title_y = detail_inner_y + 6 desc_title_y = detail_inner_y + 6
_safe_addnstr(stdscr, desc_title_y, detail_inner_x, "Details:", theme["value_label"]) _safe_addnstr(stdscr, desc_title_y, detail_inner_x, f"{_t('Details', '详情')}:", theme["value_label"])
raw_lines = _detail_lines_human(cur, values, ev) raw_lines = _detail_lines_human(cur, values, ev)
wrapped_lines: List[str] = [] wrapped_lines: List[str] = []
wrap_width = max(12, detail_inner_w) wrap_width = max(12, detail_inner_w)
@@ -1256,7 +1332,16 @@ def _run_ncurses_section(
for i, part in enumerate(wrapped_lines[:max_desc_lines]): for i, part in enumerate(wrapped_lines[:max_desc_lines]):
_safe_addnstr(stdscr, desc_title_y + 1 + i, detail_inner_x, part, 0) _safe_addnstr(stdscr, desc_title_y + 1 + i, detail_inner_x, part, 0)
_safe_addnstr(stdscr, h - 1, 0, " Space:cycle a:all-y n:all-n m:all-m Enter/ESC:back ", theme["help"]) _safe_addnstr(
stdscr,
h - 1,
0,
_t(
" Space:cycle a:all-y n:all-n m:all-m Enter/ESC:back ",
" 空格:切换 a:全y n:全n m:全m Enter/ESC:返回 ",
),
theme["help"],
)
stdscr.refresh() stdscr.refresh()
key = stdscr.getch() key = stdscr.getch()
@@ -1319,17 +1404,23 @@ def _run_ncurses_grouped_section(
items: List[Tuple[str, List[OptionItem]]] = [("All", section_options)] + groups items: List[Tuple[str, List[OptionItem]]] = [("All", section_options)] + groups
if h < 12 or w < 56: if h < 12 or w < 56:
_safe_addnstr(stdscr, 0, 0, "Terminal too small for grouped view (need >= 56x12).", theme["status_warn"]) _safe_addnstr(
_safe_addnstr(stdscr, 2, 0, "Resize terminal then press any key, or ESC to go back.") stdscr,
0,
0,
_t("Terminal too small for grouped view (need >= 56x12).", "终端太小,无法显示分组视图(至少需要 56x12"),
theme["status_warn"],
)
_safe_addnstr(stdscr, 2, 0, _t("Resize terminal then press any key, or ESC to go back.", "请调整终端大小后按任意键,或按 ESC 返回。"))
key = stdscr.getch() key = stdscr.getch()
if key in (27,): if key in (27,):
return return
continue continue
_safe_addnstr(stdscr, 0, 0, f" CLeonOS menuconfig / {title} / Groups ", theme["header"]) _safe_addnstr(stdscr, 0, 0, f" CLeonOS menuconfig / {title} / {_t('Groups', '分组')} ", theme["header"])
_safe_addnstr(stdscr, 1, 0, " Enter: open group ESC: back ", theme["subtitle"]) _safe_addnstr(stdscr, 1, 0, _t(" Enter: open group ESC: back ", " Enter:打开分组 ESC:返回 "), theme["subtitle"])
_draw_box(stdscr, 2, 0, h - 4, w, "CLKS Groups", theme["panel_border"], theme["panel_title"]) _draw_box(stdscr, 2, 0, h - 4, w, _t("CLKS Groups", "CLKS 分组"), theme["panel_border"], theme["panel_title"])
if selected < 0: if selected < 0:
selected = 0 selected = 0
@@ -1341,11 +1432,12 @@ def _run_ncurses_grouped_section(
if row >= h - 2: if row >= h - 2:
break break
on_count = _group_enabled_count(opts, ev) on_count = _group_enabled_count(opts, ev)
line = f"{'>' if i == selected else ' '} {i:02d} {name} ({on_count}/{len(opts)} enabled)" localized_name = _t("All", "全部") if name == "All" else name
line = f"{'>' if i == selected else ' '} {i:02d} {localized_name} ({on_count}/{len(opts)} {_t('enabled', '已启用')})"
attr = theme["selected"] if i == selected else theme["value_label"] attr = theme["selected"] if i == selected else theme["value_label"]
_safe_addnstr(stdscr, row, 2, line, attr) _safe_addnstr(stdscr, row, 2, line, attr)
_safe_addnstr(stdscr, h - 1, 0, " Arrows/jk move Enter open ESC back ", theme["help"]) _safe_addnstr(stdscr, h - 1, 0, _t(" Arrows/jk move Enter open ESC back ", " 方向键/jk移动 Enter打开 ESC返回 "), theme["help"])
stdscr.refresh() stdscr.refresh()
key = stdscr.getch() key = stdscr.getch()
@@ -1387,25 +1479,37 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List
total_on = clks_on + user_on total_on = clks_on + user_on
menu_entries: List[Tuple[str, str]] = [ menu_entries: List[Tuple[str, str]] = [
("clks", f"CLKS features ({clks_on}/{len(clks_options)} enabled)"), ("clks", f"{_t('CLKS features', 'CLKS 功能')} ({clks_on}/{len(clks_options)} {_t('enabled', '已启用')})"),
] ]
if user_options: if user_options:
menu_entries.append(("user", f"User apps ({user_on}/{len(user_options)} enabled)")) menu_entries.append(("user", f"{_t('User apps', '用户应用')} ({user_on}/{len(user_options)} {_t('enabled', '已启用')})"))
else: else:
menu_entries.append(("user-disabled", "User apps (CLKS-only mode)")) menu_entries.append(("user-disabled", _t("User apps (CLKS-only mode)", "用户应用(仅 CLKS 模式)")))
menu_entries.append(("save", "Save and Exit")) menu_entries.append(("save", _t("Save and Exit", "保存并退出")))
menu_entries.append(("quit", "Quit without Saving")) menu_entries.append(("quit", _t("Quit without Saving", "不保存退出")))
if h < 12 or w < 58: if h < 12 or w < 58:
_safe_addnstr(stdscr, 0, 0, "Terminal too small for menuconfig (need >= 58x12).", theme["status_warn"]) _safe_addnstr(
_safe_addnstr(stdscr, 2, 0, "Resize terminal then press any key.") stdscr,
0,
0,
_t("Terminal too small for menuconfig (need >= 58x12).", "终端太小,无法显示 menuconfig至少需要 58x12"),
theme["status_warn"],
)
_safe_addnstr(stdscr, 2, 0, _t("Resize terminal then press any key.", "请调整终端大小后按任意键。"))
stdscr.getch() stdscr.getch()
continue continue
_safe_addnstr(stdscr, 0, 0, " CLeonOS menuconfig ", theme["header"]) _safe_addnstr(stdscr, 0, 0, " CLeonOS menuconfig ", theme["header"])
_safe_addnstr(stdscr, 1, 0, " Stylish ncurses UI | Enter: open/select s: save q: quit ", theme["subtitle"]) _safe_addnstr(
stdscr,
1,
0,
_t(" Stylish ncurses UI | Enter: open/select s: save q: quit ", " 现代 ncurses 界面 | Enter:打开/选择 s:保存 q:退出 "),
theme["subtitle"],
)
_draw_box(stdscr, 2, 0, h - 5, w, "Main", theme["panel_border"], theme["panel_title"]) _draw_box(stdscr, 2, 0, h - 5, w, _t("Main", "主菜单"), theme["panel_border"], theme["panel_title"])
base = 4 base = 4
for i, (_action, text) in enumerate(menu_entries): for i, (_action, text) in enumerate(menu_entries):
@@ -1414,7 +1518,7 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List
attr = theme["selected"] if i == selected else theme["value_label"] attr = theme["selected"] if i == selected else theme["value_label"]
_safe_addnstr(stdscr, base + i, 2, row_text, attr) _safe_addnstr(stdscr, base + i, 2, row_text, attr)
_safe_addnstr(stdscr, base + 6, 2, "Global Progress:", theme["value_label"]) _safe_addnstr(stdscr, base + 6, 2, _t("Global Progress:", "全局进度:"), theme["value_label"])
_draw_progress_bar( _draw_progress_bar(
stdscr, stdscr,
base + 7, base + 7,
@@ -1426,11 +1530,29 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List
theme["progress_off"], theme["progress_off"],
) )
_safe_addnstr(stdscr, h - 2, 0, " Arrows/jk move Enter select s save q quit ", theme["help"]) _safe_addnstr(stdscr, h - 2, 0, _t(" Arrows/jk move Enter select s save q quit ", " 方向键/jk移动 Enter选择 s保存 q退出 "), theme["help"])
if user_options: if user_options:
_safe_addnstr(stdscr, h - 1, 0, " Tip: open CLKS/USER section then use Space to toggle options. ", theme["help"]) _safe_addnstr(
stdscr,
h - 1,
0,
_t(
" Tip: open CLKS/USER section then use Space to toggle options. ",
" 提示: 进入 CLKS/USER 分区后,用空格切换选项。",
),
theme["help"],
)
else: else:
_safe_addnstr(stdscr, h - 1, 0, " Tip: CLKS-only mode, open CLKS section then use Space to toggle options. ", theme["help"]) _safe_addnstr(
stdscr,
h - 1,
0,
_t(
" Tip: CLKS-only mode, open CLKS section then use Space to toggle options. ",
" 提示: 当前是仅 CLKS 模式,进入 CLKS 分区后用空格切换选项。",
),
theme["help"],
)
stdscr.refresh() stdscr.refresh()
key = stdscr.getch() key = stdscr.getch()
@@ -1462,18 +1584,18 @@ def _run_ncurses_main(stdscr, clks_options: List[OptionItem], user_options: List
def interactive_menu_ncurses(clks_options: List[OptionItem], user_options: List[OptionItem], values: Dict[str, int]) -> bool: def interactive_menu_ncurses(clks_options: List[OptionItem], user_options: List[OptionItem], values: Dict[str, int]) -> bool:
if curses is None: if curses is None:
raise RuntimeError("python curses module unavailable (install python3-curses / ncurses)") raise RuntimeError(_t("python curses module unavailable (install python3-curses / ncurses)", "缺少 python curses 模块(请安装 python3-curses / ncurses"))
if "TERM" not in os.environ or not os.environ["TERM"]: if "TERM" not in os.environ or not os.environ["TERM"]:
raise RuntimeError("TERM is not set; cannot start ncurses UI") raise RuntimeError(_t("TERM is not set; cannot start ncurses UI", "TERM 未设置,无法启动 ncurses 界面"))
return bool(curses.wrapper(lambda stdscr: _run_ncurses_main(stdscr, clks_options, user_options, values))) return bool(curses.wrapper(lambda stdscr: _run_ncurses_main(stdscr, clks_options, user_options, values)))
def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[OptionItem], values: Dict[str, int]) -> bool: def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[OptionItem], values: Dict[str, int]) -> bool:
if QtWidgets is None or QtCore is None: if QtWidgets is None or QtCore is None:
raise RuntimeError("python PySide unavailable (install PySide6, or use --plain)") raise RuntimeError(_t("python PySide unavailable (install PySide6, or use --plain)", "缺少 PySide请安装 PySide6或使用 --plain"))
if os.name != "nt" and not os.environ.get("DISPLAY") and not os.environ.get("WAYLAND_DISPLAY"): if os.name != "nt" and not os.environ.get("DISPLAY") and not os.environ.get("WAYLAND_DISPLAY"):
raise RuntimeError("GUI mode requires a desktop display (DISPLAY/WAYLAND_DISPLAY)") raise RuntimeError(_t("GUI mode requires a desktop display (DISPLAY/WAYLAND_DISPLAY)", "GUI 模式需要桌面显示环境DISPLAY/WAYLAND_DISPLAY"))
app = QtWidgets.QApplication.instance() app = QtWidgets.QApplication.instance()
owns_app = False owns_app = False
@@ -1510,7 +1632,7 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
result = {"save": False} result = {"save": False}
dialog = QtWidgets.QDialog() dialog = QtWidgets.QDialog()
dialog.setWindowTitle("CLeonOS menuconfig (PySide)") dialog.setWindowTitle(_t("CLeonOS menuconfig (PySide)", "CLeonOS menuconfigPySide"))
dialog.resize(1180, 760) dialog.resize(1180, 760)
dialog.setMinimumSize(920, 560) dialog.setMinimumSize(920, 560)
@@ -1521,7 +1643,7 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
root_layout.setContentsMargins(12, 10, 12, 12) root_layout.setContentsMargins(12, 10, 12, 12)
root_layout.setSpacing(8) root_layout.setSpacing(8)
header_title = QtWidgets.QLabel("CLeonOS menuconfig") header_title = QtWidgets.QLabel(_t("CLeonOS menuconfig", "CLeonOS 配置菜单"))
header_font = header_title.font() header_font = header_title.font()
header_font.setPointSize(header_font.pointSize() + 4) header_font.setPointSize(header_font.pointSize() + 4)
header_font.setBold(True) header_font.setBold(True)
@@ -1529,9 +1651,13 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
root_layout.addWidget(header_title) root_layout.addWidget(header_title)
if user_options: if user_options:
root_layout.addWidget(QtWidgets.QLabel("Window mode (PySide): configure CLKS features and user apps, then save.")) root_layout.addWidget(
QtWidgets.QLabel(_t("Window mode (PySide): configure CLKS features and user apps, then save.", "窗口模式PySide配置 CLKS 功能和用户应用后保存。"))
)
else: else:
root_layout.addWidget(QtWidgets.QLabel("Window mode (PySide): CLKS-only mode (user app options unavailable).")) root_layout.addWidget(
QtWidgets.QLabel(_t("Window mode (PySide): CLKS-only mode (user app options unavailable).", "窗口模式PySide仅 CLKS 模式(用户应用选项不可用)。"))
)
summary_label = QtWidgets.QLabel("") summary_label = QtWidgets.QLabel("")
root_layout.addWidget(summary_label) root_layout.addWidget(summary_label)
@@ -1546,9 +1672,11 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
user_on = sum(1 for item in user_options if ev.effective.get(item.key, item.default) > TRI_N) user_on = sum(1 for item in user_options if ev.effective.get(item.key, item.default) > TRI_N)
total = len(clks_options) + len(user_options) total = len(clks_options) + len(user_options)
summary_label.setText( summary_label.setText(
f"CLKS: {clks_on}/{len(clks_options)} on " (
f"User: {user_on}/{len(user_options)} on " f"CLKS: {clks_on}/{len(clks_options)} {_t('on', '')} "
f"Total: {clks_on + user_on}/{total}" f"{_t('User', '用户')}: {user_on}/{len(user_options)} {_t('on', '')} "
f"{_t('Total', '总计')}: {clks_on + user_on}/{total}"
)
) )
class _SectionPanel(QtWidgets.QWidget): class _SectionPanel(QtWidgets.QWidget):
@@ -1569,12 +1697,12 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
toolbar.addWidget(title_label) toolbar.addWidget(title_label)
toolbar.addStretch(1) toolbar.addStretch(1)
toggle_btn = QtWidgets.QPushButton("Cycle Selected") toggle_btn = QtWidgets.QPushButton(_t("Cycle Selected", "切换选中项"))
set_y_btn = QtWidgets.QPushButton("Set Y") set_y_btn = QtWidgets.QPushButton(_t("Set Y", "设为 Y"))
set_m_btn = QtWidgets.QPushButton("Set M") set_m_btn = QtWidgets.QPushButton(_t("Set M", "设为 M"))
set_n_btn = QtWidgets.QPushButton("Set N") set_n_btn = QtWidgets.QPushButton(_t("Set N", "设为 N"))
enable_all_btn = QtWidgets.QPushButton("All Y") enable_all_btn = QtWidgets.QPushButton(_t("All Y", "全部 Y"))
disable_all_btn = QtWidgets.QPushButton("All N") disable_all_btn = QtWidgets.QPushButton(_t("All N", "全部 N"))
toolbar.addWidget(enable_all_btn) toolbar.addWidget(enable_all_btn)
toolbar.addWidget(disable_all_btn) toolbar.addWidget(disable_all_btn)
toolbar.addWidget(set_m_btn) toolbar.addWidget(set_m_btn)
@@ -1590,7 +1718,7 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
left_layout = QtWidgets.QVBoxLayout(left) left_layout = QtWidgets.QVBoxLayout(left)
left_layout.setContentsMargins(0, 0, 0, 0) left_layout.setContentsMargins(0, 0, 0, 0)
self.table = QtWidgets.QTableWidget(len(options), 3) self.table = QtWidgets.QTableWidget(len(options), 3)
self.table.setHorizontalHeaderLabels(["Value", "Option", "Status"]) self.table.setHorizontalHeaderLabels([_t("Value", ""), _t("Option", "选项"), _t("Status", "状态")])
self.table.verticalHeader().setVisible(False) self.table.verticalHeader().setVisible(False)
self.table.horizontalHeader().setSectionResizeMode(0, resize_to_contents) self.table.horizontalHeader().setSectionResizeMode(0, resize_to_contents)
self.table.horizontalHeader().setSectionResizeMode(1, stretch_mode) self.table.horizontalHeader().setSectionResizeMode(1, stretch_mode)
@@ -1604,8 +1732,8 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
right = QtWidgets.QWidget() right = QtWidgets.QWidget()
right_layout = QtWidgets.QVBoxLayout(right) right_layout = QtWidgets.QVBoxLayout(right)
right_layout.setContentsMargins(0, 0, 0, 0) right_layout.setContentsMargins(0, 0, 0, 0)
self.state_label = QtWidgets.QLabel("State: -") self.state_label = QtWidgets.QLabel(f"{_t('State', '状态')}: -")
self.key_label = QtWidgets.QLabel("Key: -") self.key_label = QtWidgets.QLabel(f"{_t('Key', '键名')}: -")
self.detail_text = QtWidgets.QPlainTextEdit() self.detail_text = QtWidgets.QPlainTextEdit()
self.detail_text.setReadOnly(True) self.detail_text.setReadOnly(True)
right_layout.addWidget(self.state_label) right_layout.addWidget(self.state_label)
@@ -1646,8 +1774,8 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
def _show_detail(self, row: int) -> None: def _show_detail(self, row: int) -> None:
if row < 0 or row >= len(self.options): if row < 0 or row >= len(self.options):
self.state_label.setText("State: -") self.state_label.setText(f"{_t('State', '状态')}: -")
self.key_label.setText("Key: -") self.key_label.setText(f"{_t('Key', '键名')}: -")
self.detail_text.setPlainText("") self.detail_text.setPlainText("")
return return
@@ -1656,9 +1784,9 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
eff = ev.effective.get(item.key, item.default) eff = ev.effective.get(item.key, item.default)
req = normalize_tri(values.get(item.key, item.default), item.default, item.kind) req = normalize_tri(values.get(item.key, item.default), item.default, item.kind)
self.state_label.setText( self.state_label.setText(
f"State: eff={tri_char(eff)} req={tri_char(req)} kind={item.kind} flags={_option_flags(item, ev)}" f"{_t('State', '状态')}: eff={tri_char(eff)} req={tri_char(req)} kind={item.kind} flags={_option_flags(item, ev)}"
) )
self.key_label.setText(f"Key: {item.key}") self.key_label.setText(f"{_t('Key', '键名')}: {item.key}")
self.detail_text.setPlainText("\n".join([item.title, ""] + _detail_lines(item, values, ev) + ["", item.description])) self.detail_text.setPlainText("\n".join([item.title, ""] + _detail_lines(item, values, ev) + ["", item.description]))
def _on_selection_changed(self) -> None: def _on_selection_changed(self) -> None:
@@ -1669,9 +1797,14 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
return return
if len(rows) > 1: if len(rows) > 1:
self.state_label.setText(f"State: {len(rows)} items selected") self.state_label.setText(f"{_t('State', '状态')}: {len(rows)} {_t('items selected', '项已选中')}")
self.key_label.setText("Key: <multiple>") self.key_label.setText(f"{_t('Key', '键名')}: {_t('<multiple>', '<多项>')}")
self.detail_text.setPlainText("Multiple options selected.\nUse Cycle/Set buttons to update selected entries.") self.detail_text.setPlainText(
_t(
"Multiple options selected.\nUse Cycle/Set buttons to update selected entries.",
"已选中多个选项。\n使用 Cycle/Set 按钮批量修改。",
)
)
return return
self._show_detail(-1) self._show_detail(-1)
@@ -1761,7 +1894,7 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
clks_groups = _grouped_options(clks_options) clks_groups = _grouped_options(clks_options)
if len(clks_groups) <= 1: if len(clks_groups) <= 1:
clks_panel = _SectionPanel("CLKS Features", clks_options) clks_panel = _SectionPanel(_t("CLKS Features", "CLKS 功能"), clks_options)
else: else:
clks_panel = QtWidgets.QWidget() clks_panel = QtWidgets.QWidget()
clks_layout = QtWidgets.QVBoxLayout(clks_panel) clks_layout = QtWidgets.QVBoxLayout(clks_panel)
@@ -1769,22 +1902,22 @@ def interactive_menu_gui(clks_options: List[OptionItem], user_options: List[Opti
clks_layout.setSpacing(6) clks_layout.setSpacing(6)
clks_tabs = QtWidgets.QTabWidget() clks_tabs = QtWidgets.QTabWidget()
clks_layout.addWidget(clks_tabs, 1) clks_layout.addWidget(clks_tabs, 1)
clks_tabs.addTab(_SectionPanel("CLKS Features / All", clks_options), "All") clks_tabs.addTab(_SectionPanel(_t("CLKS Features / All", "CLKS 功能 / 全部"), clks_options), _t("All", "全部"))
for group_name, group_items in clks_groups: for group_name, group_items in clks_groups:
clks_tabs.addTab(_SectionPanel(f"CLKS Features / {group_name}", group_items), group_name) clks_tabs.addTab(_SectionPanel(f"{_t('CLKS Features', 'CLKS 功能')} / {group_name}", group_items), group_name)
tabs.addTab(clks_panel, "CLKS") tabs.addTab(clks_panel, "CLKS")
if user_options: if user_options:
user_panel = _SectionPanel("User Apps", user_options) user_panel = _SectionPanel(_t("User Apps", "用户应用"), user_options)
tabs.addTab(user_panel, "USER") tabs.addTab(user_panel, _t("USER", "用户"))
update_summary() update_summary()
footer = QtWidgets.QHBoxLayout() footer = QtWidgets.QHBoxLayout()
footer.addWidget(QtWidgets.QLabel("Tip: double-click a row to cycle, or use Set/Cycle buttons.")) footer.addWidget(QtWidgets.QLabel(_t("Tip: double-click a row to cycle, or use Set/Cycle buttons.", "提示:双击一行可切换,或使用 Set/Cycle 按钮。")))
footer.addStretch(1) footer.addStretch(1)
save_btn = QtWidgets.QPushButton("Save and Exit") save_btn = QtWidgets.QPushButton(_t("Save and Exit", "保存并退出"))
quit_btn = QtWidgets.QPushButton("Quit without Saving") quit_btn = QtWidgets.QPushButton(_t("Quit without Saving", "不保存退出"))
footer.addWidget(save_btn) footer.addWidget(save_btn)
footer.addWidget(quit_btn) footer.addWidget(quit_btn)
root_layout.addLayout(footer) root_layout.addLayout(footer)
@@ -1888,14 +2021,20 @@ def show_summary(clks_options: List[OptionItem], user_options: List[OptionItem],
clks_m = sum(1 for item in clks_options if ev.effective.get(item.key, item.default) == TRI_M) clks_m = sum(1 for item in clks_options if ev.effective.get(item.key, item.default) == TRI_M)
user_m = sum(1 for item in user_options if ev.effective.get(item.key, item.default) == TRI_M) user_m = sum(1 for item in user_options if ev.effective.get(item.key, item.default) == TRI_M)
print() print()
print("========== CLeonOS menuconfig ==========") print(_t("========== CLeonOS menuconfig ==========", "========== CLeonOS 配置菜单 =========="))
print(f"1) CLKS features : on={clks_on} m={clks_m} total={len(clks_options)}") print(
f"1) {_t('CLKS features', 'CLKS 功能')} : "
f"{_t('on', '')}={clks_on} m={clks_m} {_t('total', '总数')}={len(clks_options)}"
)
if user_options: if user_options:
print(f"2) User features : on={user_on} m={user_m} total={len(user_options)}") print(
f"2) {_t('User features', '用户功能')} : "
f"{_t('on', '')}={user_on} m={user_m} {_t('total', '总数')}={len(user_options)}"
)
else: else:
print("2) User features : unavailable (CLKS-only mode)") print(_t("2) User features : unavailable (CLKS-only mode)", "2) 用户功能 : 不可用(仅 CLKS 模式)"))
print("s) Save and exit") print(_t("s) Save and exit", "s) 保存并退出"))
print("q) Quit without saving") print(_t("q) Quit without saving", "q) 不保存退出"))
def interactive_menu(clks_options: List[OptionItem], user_options: List[OptionItem], values: Dict[str, int]) -> bool: def interactive_menu(clks_options: List[OptionItem], user_options: List[OptionItem], values: Dict[str, int]) -> bool:
@@ -1903,7 +2042,7 @@ def interactive_menu(clks_options: List[OptionItem], user_options: List[OptionIt
has_user = len(user_options) > 0 has_user = len(user_options) > 0
while True: while True:
show_summary(clks_options, user_options, values) show_summary(clks_options, user_options, values)
choice = input("Select> ").strip().lower() choice = input(_t("Select> ", "选择> ")).strip().lower()
if choice == "1": if choice == "1":
grouped_section_loop("CLKS", clks_options, all_options, values) grouped_section_loop("CLKS", clks_options, all_options, values)
continue continue
@@ -1911,13 +2050,13 @@ def interactive_menu(clks_options: List[OptionItem], user_options: List[OptionIt
section_loop("USER", user_options, all_options, values) section_loop("USER", user_options, all_options, values)
continue continue
if choice == "2" and not has_user: if choice == "2" and not has_user:
print("user features unavailable in CLKS-only mode") print(_t("user features unavailable in CLKS-only mode", "仅 CLKS 模式下,用户功能不可用"))
continue continue
if choice in {"s", "save"}: if choice in {"s", "save"}:
return True return True
if choice in {"q", "quit"}: if choice in {"q", "quit"}:
return False return False
print("unknown selection") print(_t("unknown selection", "未知选择"))
def parse_set_overrides(values: Dict[str, int], option_index: Dict[str, OptionItem], kv_pairs: List[str]) -> None: def parse_set_overrides(values: Dict[str, int], option_index: Dict[str, OptionItem], kv_pairs: List[str]) -> None:
@@ -1942,6 +2081,12 @@ def parse_args() -> argparse.Namespace:
parser.add_argument("--plain", action="store_true", help="use legacy plain-text menu instead of ncurses") 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("--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("--clks-only", action="store_true", help="only expose CLKS options and emit CLKS-only config")
parser.add_argument(
"--lang",
choices=["auto", "en", "zh", "zh-CN", "zh-cn", "zh_CN", "zh_cn"],
default="auto",
help="menu language: auto|en|zh-CN",
)
parser.add_argument( parser.add_argument(
"--preset", "--preset",
choices=["full", "minimal", "dev"], choices=["full", "minimal", "dev"],
@@ -1958,15 +2103,23 @@ def parse_args() -> argparse.Namespace:
def main() -> int: def main() -> int:
global MENUCONFIG_LANG
args = parse_args() args = parse_args()
MENUCONFIG_LANG = _resolve_language(args.lang)
if args.gui and args.plain: if args.gui and args.plain:
raise RuntimeError("--gui and --plain cannot be used together") raise RuntimeError(_t("--gui and --plain cannot be used together", "--gui 和 --plain 不能同时使用"))
clks_options = load_clks_options() clks_options = load_clks_options()
clks_only_mode = args.clks_only or not APPS_DIR.exists() clks_only_mode = args.clks_only or not APPS_DIR.exists()
if clks_only_mode and not args.clks_only: if clks_only_mode and not args.clks_only:
print(f"menuconfig: cleonos app directory not found, switching to CLKS-only mode ({APPS_DIR})") print(
_t(
f"menuconfig: cleonos app directory not found, switching to CLKS-only mode ({APPS_DIR})",
f"menuconfig: 未找到 cleonos 应用目录,切换到仅 CLKS 模式({APPS_DIR}",
)
)
user_options = [] if clks_only_mode else discover_user_apps() user_options = [] if clks_only_mode else discover_user_apps()
all_options = clks_options + user_options all_options = clks_options + user_options
@@ -1985,27 +2138,27 @@ def main() -> int:
should_save = interactive_menu_gui(clks_options, user_options, values) should_save = interactive_menu_gui(clks_options, user_options, values)
else: else:
if not sys.stdin.isatty(): if not sys.stdin.isatty():
raise RuntimeError("menuconfig requires interactive tty (or use --non-interactive or --gui)") raise RuntimeError(_t("menuconfig requires interactive tty (or use --non-interactive or --gui)", "menuconfig 需要交互式终端(或使用 --non-interactive / --gui"))
if args.plain: if args.plain:
should_save = interactive_menu(clks_options, user_options, values) should_save = interactive_menu(clks_options, user_options, values)
else: else:
should_save = interactive_menu_ncurses(clks_options, user_options, values) should_save = interactive_menu_ncurses(clks_options, user_options, values)
if not should_save: if not should_save:
print("menuconfig: no changes saved") print(_t("menuconfig: no changes saved", "menuconfig: 未保存任何更改"))
return 0 return 0
final_eval = evaluate_config(all_options, values) final_eval = evaluate_config(all_options, values)
write_outputs(final_eval.effective, clks_options, user_options) write_outputs(final_eval.effective, clks_options, user_options)
print(f"menuconfig: wrote {CONFIG_JSON_PATH}") print(_t(f"menuconfig: wrote {CONFIG_JSON_PATH}", f"menuconfig: 已写入 {CONFIG_JSON_PATH}"))
print(f"menuconfig: wrote {CONFIG_CMAKE_PATH}") print(_t(f"menuconfig: wrote {CONFIG_CMAKE_PATH}", f"menuconfig: 已写入 {CONFIG_CMAKE_PATH}"))
print(f"menuconfig: wrote {CONFIG_CLKS_JSON_PATH}") print(_t(f"menuconfig: wrote {CONFIG_CLKS_JSON_PATH}", f"menuconfig: 已写入 {CONFIG_CLKS_JSON_PATH}"))
print(f"menuconfig: wrote {CONFIG_CLKS_CMAKE_PATH}") print(_t(f"menuconfig: wrote {CONFIG_CLKS_CMAKE_PATH}", f"menuconfig: 已写入 {CONFIG_CLKS_CMAKE_PATH}"))
if user_options: if user_options:
print(f"menuconfig: wrote {CONFIG_CLEONOS_JSON_PATH}") print(_t(f"menuconfig: wrote {CONFIG_CLEONOS_JSON_PATH}", f"menuconfig: 已写入 {CONFIG_CLEONOS_JSON_PATH}"))
print(f"menuconfig: wrote {CONFIG_CLEONOS_CMAKE_PATH}") print(_t(f"menuconfig: wrote {CONFIG_CLEONOS_CMAKE_PATH}", f"menuconfig: 已写入 {CONFIG_CLEONOS_CMAKE_PATH}"))
else: else:
print("menuconfig: CLeonOS app config skipped (CLKS-only mode)") print(_t("menuconfig: CLeonOS app config skipped (CLKS-only mode)", "menuconfig: 已跳过 CLeonOS 应用配置(仅 CLKS 模式)"))
return 0 return 0
@@ -2013,5 +2166,5 @@ if __name__ == "__main__":
try: try:
raise SystemExit(main()) raise SystemExit(main())
except RuntimeError as exc: except RuntimeError as exc:
print(f"menuconfig error: {exc}", file=sys.stderr) print(_t(f"menuconfig error: {exc}", f"menuconfig 错误: {exc}"), file=sys.stderr)
raise SystemExit(1) raise SystemExit(1)