wip: bare bones for C in kernel
This commit is contained in:
+30
-169
@@ -1,182 +1,43 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(ksOSKernel LANGUAGES ASM C)
|
||||
set(KERNEL_MODULE_NAME "Kernel")
|
||||
|
||||
# Where to emit compile_commands.json for SourceKit-LSP. Empty: Kernel/
|
||||
# (ancestor of SWIFT_SOURCES). Override: -DKERNEL_COMPILE_COMMANDS_DIR=/path
|
||||
# or env KERNEL_COMPILE_COMMANDS_DIR.
|
||||
set(KERNEL_COMPILE_COMMANDS_DIR "" CACHE PATH
|
||||
"Directory for Swift compile_commands.json (SourceKit-LSP)")
|
||||
file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/KernelMain.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/entry.S
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/**/*.c
|
||||
)
|
||||
|
||||
# --- Locate Swift toolchain with Embedded Swift stdlib ---
|
||||
# Priority: cmake var > env var > auto-detect
|
||||
if(NOT SWIFT_TOOLCHAIN AND DEFINED ENV{SWIFT_TOOLCHAIN})
|
||||
set(SWIFT_TOOLCHAIN "$ENV{SWIFT_TOOLCHAIN}")
|
||||
endif()
|
||||
add_executable(Kernel ${KERNEL_SOURCES})
|
||||
target_include_directories(Kernel PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Include/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../Common
|
||||
)
|
||||
|
||||
if(SWIFT_TOOLCHAIN)
|
||||
set(SWIFTC "${SWIFT_TOOLCHAIN}/usr/bin/swiftc")
|
||||
set(SWIFT_RESOURCE_DIR "${SWIFT_TOOLCHAIN}/usr/lib/swift")
|
||||
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||
# Scan for a swift.org toolchain that ships the embedded stdlib.
|
||||
# APPLE is false here (target is Generic), so we check the HOST OS.
|
||||
file(GLOB _tc_candidates
|
||||
"$ENV{HOME}/Library/Developer/Toolchains/*.xctoolchain"
|
||||
"/Library/Developer/Toolchains/*.xctoolchain"
|
||||
)
|
||||
foreach(_tc ${_tc_candidates})
|
||||
if(EXISTS "${_tc}/usr/lib/swift/embedded")
|
||||
set(SWIFTC "${_tc}/usr/bin/swiftc")
|
||||
set(SWIFT_RESOURCE_DIR "${_tc}/usr/lib/swift")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
# Linux: find swiftc in PATH
|
||||
find_program(_SWIFTC_EXE swiftc)
|
||||
if(_SWIFTC_EXE)
|
||||
get_filename_component(_SWIFTC_BIN "${_SWIFTC_EXE}" DIRECTORY)
|
||||
get_filename_component(_SWIFTC_USR "${_SWIFTC_BIN}" DIRECTORY)
|
||||
|
||||
if(EXISTS "${_SWIFTC_USR}/lib/swift/embedded")
|
||||
set(SWIFTC "${_SWIFTC_EXE}")
|
||||
set(SWIFT_RESOURCE_DIR "${_SWIFTC_USR}/lib/swift")
|
||||
elseif(EXISTS "${_SWIFTC_USR}/lib/swift/lib/swift/embedded")
|
||||
set(SWIFTC "${_SWIFTC_EXE}")
|
||||
set(SWIFT_RESOURCE_DIR "${_SWIFTC_USR}/lib/swift/lib/swift")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
target_compile_options(Kernel PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C>:
|
||||
-ffreestanding
|
||||
-fno-stack-protector
|
||||
-fno-builtin
|
||||
-Wall -Wextra
|
||||
-g
|
||||
-mgeneral-regs-only
|
||||
>
|
||||
)
|
||||
|
||||
if(NOT SWIFTC OR NOT EXISTS "${SWIFT_RESOURCE_DIR}/embedded")
|
||||
message(FATAL_ERROR
|
||||
"Swift toolchain with Embedded Swift not found.\n"
|
||||
"Install a swift.org toolchain and pass -DSWIFT_TOOLCHAIN=<root> "
|
||||
"or set the SWIFT_TOOLCHAIN env var.")
|
||||
endif()
|
||||
|
||||
message(STATUS "Swift: ${SWIFTC}")
|
||||
message(STATUS "Swift resource dir: ${SWIFT_RESOURCE_DIR}")
|
||||
|
||||
# Hint for SourceKit: VSCode must use this toolchain (same as compile_commands),
|
||||
# not Xcode's default; otherwise: "Loading the standard library failed" with Embedded.
|
||||
get_filename_component(_SWIFT_IDE_PATH "${SWIFTC}" DIRECTORY)
|
||||
set(_ide_hint
|
||||
"# If SourceKit reports \"Loading the standard library failed\", set the Swift
|
||||
# extension's swift.path to the directory on the line below and restart
|
||||
# \"Swift: Restart SourceKit LSP\". (Embedded Swift — must match this toolchain, not Xcode.)
|
||||
# Regenerated on each CMake configure.
|
||||
")
|
||||
string(APPEND _ide_hint "${_SWIFT_IDE_PATH}\n")
|
||||
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/../ide-swift-toolchain.txt" "${_ide_hint}")
|
||||
|
||||
# --- Build ---
|
||||
add_compile_options(-ffreestanding -nostdlib -O0 -g)
|
||||
|
||||
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
||||
add_link_options(
|
||||
-fuse-ld=lld
|
||||
target_link_options(Kernel PRIVATE
|
||||
-nostdlib
|
||||
-static
|
||||
-Wl,-T,${LINKER_SCRIPT}
|
||||
-no-pie
|
||||
-T "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld"
|
||||
-z max-page-size=0x1000
|
||||
)
|
||||
|
||||
set(SWIFT_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/Kernel.swift
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/DTB.swift
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/IO/UART.swift
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/Arch/ExceptionContext.swift
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/OS/panic.swift # idfk why but sourcekit-lsp dont see Panic.swift but see panic.swift perfectly
|
||||
)
|
||||
set(SWIFT_OBJ ${CMAKE_CURRENT_BINARY_DIR}/kernel_swift.o)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${SWIFT_OBJ}
|
||||
COMMAND ${SWIFTC}
|
||||
-target aarch64-none-none-elf
|
||||
-enable-experimental-feature Embedded
|
||||
-parse-as-library
|
||||
-wmo
|
||||
-O
|
||||
-Xcc -fno-stack-protector
|
||||
-Xcc -I${CMAKE_CURRENT_SOURCE_DIR}/../Common
|
||||
-import-bridging-header ${CMAKE_CURRENT_SOURCE_DIR}/Source/Support/BridgingHeader.h
|
||||
-resource-dir ${SWIFT_RESOURCE_DIR}
|
||||
-c ${SWIFT_SOURCES}
|
||||
-o ${SWIFT_OBJ}
|
||||
COMMAND ${LLVM_OBJCOPY} --remove-section=.swift_modhash ${SWIFT_OBJ}
|
||||
DEPENDS ${SWIFT_SOURCES}
|
||||
COMMENT "Compiling Swift kernel"
|
||||
set_target_properties(Kernel PROPERTIES
|
||||
OUTPUT_NAME "Kernel.elf"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
)
|
||||
|
||||
set_source_files_properties(${SWIFT_OBJ} PROPERTIES
|
||||
EXTERNAL_OBJECT TRUE
|
||||
GENERATED TRUE
|
||||
)
|
||||
|
||||
add_executable(kernel.elf Source/Arch/entry.S Source/Support/stubs.c Source/Arch/vectors.S ${SWIFT_OBJ})
|
||||
|
||||
add_custom_command(TARGET kernel.elf POST_BUILD
|
||||
COMMAND ${LLVM_OBJCOPY} -O binary kernel.elf kernel.bin
|
||||
)
|
||||
|
||||
# --- SourceKit-LSP: generate compile_commands.json for Swift (Dynamic) ---
|
||||
set(_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Source/Support/BridgingHeader.h")
|
||||
|
||||
set(SWIFT_ARGS
|
||||
"\"${SWIFTC}\""
|
||||
"\"-target\"" "\"aarch64-none-none-elf\""
|
||||
"\"-enable-experimental-feature\"" "\"Embedded\""
|
||||
"\"-module-name\"" "\"${KERNEL_MODULE_NAME}\""
|
||||
"\"-parse-as-library\""
|
||||
"\"-wmo\""
|
||||
"\"-import-bridging-header\"" "\"${_BRIDGING_HEADER}\""
|
||||
"\"-Xcc\"" "\"-I${CMAKE_CURRENT_SOURCE_DIR}/../Common\""
|
||||
"\"-Xcc\"" "\"-fno-stack-protector\""
|
||||
"\"-resource-dir\"" "\"${SWIFT_RESOURCE_DIR}\""
|
||||
)
|
||||
foreach(_src IN LISTS SWIFT_SOURCES)
|
||||
list(APPEND SWIFT_ARGS "\"${_src}\"")
|
||||
endforeach()
|
||||
|
||||
string(JOIN ", " SWIFT_ARGS_JSON ${SWIFT_ARGS})
|
||||
|
||||
set(COMPDB_ENTRIES "")
|
||||
list(LENGTH SWIFT_SOURCES _src_count)
|
||||
math(EXPR _last_idx "${_src_count} - 1")
|
||||
set(_idx 0)
|
||||
|
||||
foreach(_src IN LISTS SWIFT_SOURCES)
|
||||
set(_entry " {\n \"file\": \"${_src}\",\n \"directory\": \"${CMAKE_CURRENT_BINARY_DIR}\",\n \"arguments\": [${SWIFT_ARGS_JSON}]\n }")
|
||||
|
||||
if(_idx LESS _last_idx)
|
||||
string(APPEND _entry ",\n")
|
||||
else()
|
||||
string(APPEND _entry "\n")
|
||||
endif()
|
||||
|
||||
string(APPEND COMPDB_ENTRIES "${_entry}")
|
||||
math(EXPR _idx "${_idx} + 1")
|
||||
endforeach()
|
||||
|
||||
# Precedence: CMake -D > env > Kernel/ (ancestor of all SWIFT_SOURCES).
|
||||
if(NOT KERNEL_COMPILE_COMMANDS_DIR STREQUAL "")
|
||||
set(COMPDB_OUTPUT_DIR "${KERNEL_COMPILE_COMMANDS_DIR}")
|
||||
elseif(DEFINED ENV{KERNEL_COMPILE_COMMANDS_DIR} AND NOT "$ENV{KERNEL_COMPILE_COMMANDS_DIR}" STREQUAL "")
|
||||
set(COMPDB_OUTPUT_DIR "$ENV{KERNEL_COMPILE_COMMANDS_DIR}")
|
||||
else()
|
||||
set(COMPDB_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
# Same JSON twice: (1) optional Kernel/ or KERNEL_COMPILE_COMMANDS_DIR, (2) repo
|
||||
# root. SourceKit/Cursor/VSCode Swift extension resolve compile_commands at the
|
||||
# workspace root first; a DB only under Kernel/ often yields no language service
|
||||
# and broken cross-file resolution (WMO) even though the build works.
|
||||
set(KERNEL_COMPDB_CONTENT "[\n${COMPDB_ENTRIES}]\n")
|
||||
file(GENERATE OUTPUT "${COMPDB_OUTPUT_DIR}/compile_commands.json"
|
||||
CONTENT "${KERNEL_COMPDB_CONTENT}"
|
||||
)
|
||||
set(_REPO_COMPDB "${CMAKE_CURRENT_SOURCE_DIR}/../compile_commands.json")
|
||||
file(GENERATE OUTPUT "${_REPO_COMPDB}"
|
||||
CONTENT "${KERNEL_COMPDB_CONTENT}"
|
||||
add_custom_command(TARGET Kernel POST_BUILD
|
||||
COMMAND ${LLVM_OBJCOPY} -O binary ${CMAKE_BINARY_DIR}/Kernel.elf ${CMAKE_BINARY_DIR}/Kernel.bin
|
||||
COMMENT "Generating ksOSKernel.bin from Kernel.elf"
|
||||
)
|
||||
Reference in New Issue
Block a user