Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ae9ce33
refactor: Move compile options to target.properties interface library
kryczkal Aug 5, 2025
18aca3f
refactor: Remove post-arch action and consolidate target properties l…
kryczkal Aug 5, 2025
a0c6862
refactor: Update 32-bit loader CMake configuration to use target prop…
kryczkal Aug 5, 2025
196a7ad
refactor: Simplify source file handling in CMakeLists.txt for x86_64 …
kryczkal Aug 5, 2025
8d6ada8
refactor: Simplify CMakeLists.txt by removing redundant source file h…
kryczkal Aug 5, 2025
0a37833
refactor: Simplify third-party library linking in kernel build system
kryczkal Aug 5, 2025
3858125
chore: Move third-party library status messages to appropriate CMakeL…
kryczkal Aug 5, 2025
faf0d38
refactor: Use target properties for kernel configuration and CRT objects
kryczkal Aug 6, 2025
3044200
refactor: Split CXX global constructors into separate object librarie…
kryczkal Aug 6, 2025
d61fd2c
refactor: Use target properties for kernel configuration and simplify…
kryczkal Aug 6, 2025
fc698e8
fix: Remove PRIVATE keyword from add_dependencies call
kryczkal Aug 6, 2025
7e87790
Fix message
kryczkal Aug 6, 2025
771f77a
Apply suggestion from @Copilot
kryczkal Aug 6, 2025
5c9ab80
chore: Update toolchain versions to binutils 2.44 and gcc 15.1.0
kryczkal Aug 6, 2025
e64ce05
chore: Add error handling and debug output for crtbegin/crtend object…
kryczkal Aug 6, 2025
1bf5395
refactor: Reorder and enhance toolchain setup in prepare_env action
kryczkal Aug 6, 2025
e120be2
refactor: Remove unnecessary step dependencies in prepare_env action
kryczkal Aug 6, 2025
32e57f7
refactor: Reorganize kernel CMakeLists.txt to improve dependency mana…
kryczkal Aug 6, 2025
069a693
docs: Add note about linking objects to interface libraries in CMakeL…
kryczkal Aug 6, 2025
7113a04
refactor: Improve kernel build configuration and linking order
kryczkal Aug 6, 2025
0feb2da
refactor: Simplify kernel build configuration and remove debug messages
kryczkal Aug 6, 2025
ce589c2
refactor: Simplify CRT object linking in kernel build configuration
kryczkal Aug 6, 2025
b86a749
refactor: Improve kernel linking order and CRT object handling
kryczkal Aug 6, 2025
70b331b
refactor: Reorganize CMakeLists.txt linking and remove redundant targ…
kryczkal Aug 6, 2025
616435c
Apply suggestion from @Copilot
kryczkal Aug 6, 2025
1b10194
chore: Fix CMakeLists.txt syntax errors and add compile definitions f…
kryczkal Aug 6, 2025
2843e70
refactor: Reorganize CMakeLists.txt to improve dependency linking and…
kryczkal Aug 6, 2025
0ec692b
Merge branch 'dev' into kryczkal/cmake-modularization-03
kryczkal Aug 9, 2025
721656a
Quickfix
kryczkal Aug 9, 2025
f442572
Merge branch 'dev' into kryczkal/cmake-modularization-03
kryczkal Aug 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions .github/actions/prepare_env/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,14 @@ runs:
shell: bash
run: sudo "$GITHUB_WORKSPACE/scripts/env/install_deps_ubuntu.bash" --install -v

- name: Configure environment
env:
ARCH: ${{ inputs.arch }}
shell: bash
run: sudo "$GITHUB_WORKSPACE/scripts/config/configure.bash" "$ARCH" debug -v -p test_mode

- name: Cache toolchain
uses: actions/cache@v4
id: cache-build-tools
with:
key: tools-${{ inputs.arch }}-${{ hashFiles('scripts/env/toolchain_versions.txt') }}
key: tools-${{ inputs.arch }}-${{ hashFiles('scripts/env/toolchain_versions.txt', 'scripts/env/build_cross_compile.bash') }}
path: tools

- name: Build toolchain
- name: Build toolchain and Setup PATH
env:
TOOLCHAIN_PATH: ${{ github.workspace }}/tools
BUILD_PATH: ${{ github.workspace }}/build
Expand All @@ -35,16 +29,23 @@ runs:
shell: bash
run: |
if [[ $BUILD_TOOLS_CACHE_HIT == 'true' ]]; then
echo "Toolchain is cached, skipping build"
if [[ $ARCH == 'x86_64' ]]; then
echo "Adding x86 toolchain paths to the PATH"
echo "$TOOLCHAIN_PATH/i386-elf/bin" >> $GITHUB_PATH
echo "$TOOLCHAIN_PATH/x86_64-elf/bin" >> $GITHUB_PATH
else
echo "Unsupported arch"
exit 1
fi
echo "Toolchain is cached, skipping build"
else
echo "Building toolchain"
sudo "$GITHUB_WORKSPACE/scripts/env/install_toolchain.bash" "$TOOLCHAIN_PATH" "$BUILD_PATH" "$ARCH" -v
fi

echo "Adding toolchain to PATH for subsequent steps"
if [[ $ARCH == 'x86_64' ]]; then
echo "$TOOLCHAIN_PATH/i386-elf/bin" >> $GITHUB_PATH
echo "$TOOLCHAIN_PATH/x86_64-elf/bin" >> $GITHUB_PATH
else
echo "Unsupported arch"
exit 1
fi

- name: Configure environment
env:
ARCH: ${{ inputs.arch }}
shell: bash
run: sudo "$GITHUB_WORKSPACE/scripts/config/configure.bash" "$ARCH" debug -v -p test_mode
16 changes: 14 additions & 2 deletions alkos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,21 @@ add_subdirectory(libc)
add_subdirectory(generated)
add_subdirectory(kernel)

get_property(BOOTABLE_KERNEL_EXECUTABLE TARGET alkos.kernel.config PROPERTY BOOTABLE_KERNEL_EXECUTABLE)
get_property(KERNEL_MODULES TARGET alkos.kernel.config PROPERTY KERNEL_MODULES)
get_property(KERNEL_COMMANDS TARGET alkos.kernel.config PROPERTY KERNEL_COMMANDS)
get_property(ARCH_QEMU_COMMAND TARGET alkos.kernel.config PROPERTY ARCH_QEMU_COMMAND)
get_property(ARCH_QEMU_NORMAL_FLAGS TARGET alkos.kernel.config PROPERTY ARCH_QEMU_NORMAL_FLAGS)
get_property(ARCH_QEMU_TEST_FLAGS TARGET alkos.kernel.config PROPERTY ARCH_QEMU_TEST_FLAGS)

alkos_ensure_defined(
VARS BOOTABLE_KERNEL_EXECUTABLE
MESSAGE "No primary kernel executable defined by the end of the configuration."
VARS
BOOTABLE_KERNEL_EXECUTABLE
KERNEL_MODULES
KERNEL_COMMANDS
ARCH_QEMU_COMMAND
ARCH_QEMU_NORMAL_FLAGS
ARCH_QEMU_TEST_FLAGS
)

################################################################################
Expand Down
66 changes: 63 additions & 3 deletions alkos/cmake/ValidationHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# alkos_ensure_defined
#===============================================================================
#
# Checks if one or more variables are defined and halts with a fatal error,
# listing all undefined variables at once.
# Checks if one or more variables are defined (and nonempty) and halts with a
# fatal error, listing all undefined variables at once.
#
# Parameters:
# VARS <var>... A list of variable names to check.
Expand Down Expand Up @@ -42,7 +42,7 @@ function(alkos_ensure_defined)

set(undefined_vars "")
foreach(var_name ${ARG_VARS})
if(NOT DEFINED ${var_name})
if(NOT ${var_name})
Comment thread
Jlisowskyy marked this conversation as resolved.
Comment thread
Jlisowskyy marked this conversation as resolved.
list(APPEND undefined_vars "${var_name}")
endif()
endforeach()
Expand All @@ -59,3 +59,63 @@ function(alkos_ensure_defined)
message(FATAL_ERROR "${error_message}")
endif()
endfunction()

#===============================================================================
# alkos_ensure_property_defined
#===============================================================================
#
# Checks if a property is defined for a target and halts with a fatal error,
# listing all undefined properties at once.
#
# Parameters:
# TARGET <target> The target to check the properties for.
# PROPS <prop>... A list of property names to check.
# MESSAGE <message> (Optional) A supplementary message to append to the
# standard error output. This is useful for providing
# additional context or instructions to the user.
#
# Example:
# # Assume alkos.kernel.config is a target and BOOTABLE_KERNEL_EXECUTABLE
# # is not defined.
# alkos_ensure_property_defined(
# TARGET alkos.kernel.config
# PROPS BOOTABLE_KERNEL_EXECUTABLE KERNEL_MODULES
# MESSAGE "The BOOTABLE_KERNEL_EXECUTABLE property must be set for the KERNEL_MODULES target."
# )
#
function(alkos_ensure_property_defined)
set(options)
set(oneValueArgs TARGET MESSAGE)
set(multiValueArgs PROPS)

cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

if(NOT ARG_TARGET)
message(FATAL_ERROR "alkos_ensure_property_defined() called without a TARGET to check.")
endif()

if(NOT ARG_PROPS)
message(FATAL_ERROR "alkos_ensure_property_defined() called without any PROPS to check.")
endif()

set(undefined_props "")
foreach(prop_name ${ARG_PROPS})
get_property(is_defined TARGET ${ARG_TARGET} PROPERTY ${prop_name} DEFINED)
if(NOT is_defined)
list(APPEND undefined_props "${prop_name}")
endif()
endforeach()

if(undefined_props)
string(JOIN ", " undefined_props_str "${undefined_props}")

set(error_message "The following required properties are not defined for target '${ARG_TARGET}': ${undefined_props_str}")

if(ARG_MESSAGE)
string(APPEND error_message "\n${ARG_MESSAGE}")
endif()

message(FATAL_ERROR "${error_message}")
endif()
endfunction()

150 changes: 79 additions & 71 deletions alkos/kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
message(STATUS "Configuring kernel...")

# This target acts as a central hub for configuration data (e.g., kernel modules)
# that needs to be communicated to the top-level CMakeLists.txt.
add_library(alkos.kernel.config INTERFACE)
add_library(alkos.kernel.headers INTERFACE) # Kernel headers for exporting
add_library(alkos.kernel.deps INTERFACE) # Target to link all dependencies to
#------------------------------------------------------------------------------#
# Notes: alkos.kernel.deps #
#------------------------------------------------------------------------------#
# Note: Caveat - linking objects to this target also requires
# using target_sources $<TARGET_OBJECTS:{some lib name}> syntax because
# interface libraries are only carriers for headers and properties
#
#------------------------------------------------------------------------------#
# Note: This target is used to ensure proper linking order
# Idea was that this is the linking "api" of the kernel
# So that arch etc, doesn't have to care about the linking order
# This is current unused in the intended way, but may be useful in the future
#
#------------------------------------------------------------------------------#

############################### Error Checking ###############################

alkos_ensure_defined(
Expand All @@ -11,19 +31,6 @@ alkos_ensure_defined(
add_compile_definitions(__ALKOS_KERNEL__=1)
add_compile_definitions(__ALKOS_LIBK__=1) # For LIBK headers

############################# Arch Dependent Vars ############################

# ----------------------------------------------------------------------------
# Arch can optionally create other executables (for chainloading, etc)
# They need to place themselves in sysroot/boot
# This is the list of executables that will be loaded by the bootloader as
# modules
set(KERNEL_MODULES "")
# ----------------------------------------------------------------------------
# This is the executable that the bootloader will give control to
set(BOOTABLE_KERNEL_EXECUTABLE alkos.kernel)
# ----------------------------------------------------------------------------

########################### Setting Sysroot Boot #############################

file(MAKE_DIRECTORY ${SYSROOT}/boot)
Expand All @@ -49,91 +56,92 @@ if (CMAKE_FEATURE_FLAG_RUN_TEST_MODE)
list(APPEND KERNEL_SOURCES ${KERNEL_TEST_SOURCES})
endif ()


#################################### Exec ####################################

add_executable(alkos.kernel
${KERNEL_SOURCES}
)
add_executable(alkos.kernel ${KERNEL_SOURCES})

############################### Adding Headers ###############################

add_library(alkos.kernel.headers INTERFACE)
target_include_directories(alkos.kernel.headers INTERFACE
include
test
abi
)

target_link_libraries(alkos.kernel PRIVATE
alkos.kernel.headers
)

########################## Configure for given Arch ##########################

add_subdirectory(arch/${ARCH})

############################### Error Checking ###############################

alkos_ensure_defined(
VARS
BOOTABLE_KERNEL_EXECUTABLE
KERNEL_MODULES
KERNEL_COMMANDS
ARCH_QEMU_COMMAND
ARCH_QEMU_NORMAL_FLAGS
ARCH_QEMU_TEST_FLAGS
CRTI_OBJ
CRTN_OBJ
)

message(STATUS "Bootable kernel executable: ${BOOTABLE_KERNEL_EXECUTABLE}")
message(STATUS "Kernel modules: ${KERNEL_MODULES}")
message(STATUS "Kernel commands: ${KERNEL_COMMANDS}")

list(LENGTH KERNEL_MODULES KERNEL_MODULES_LENGTH)
list(LENGTH KERNEL_COMMANDS KERNEL_COMMANDS_LENGTH)

# Check if the two lists are the same size
if(NOT KERNEL_MODULES_LENGTH EQUAL KERNEL_COMMANDS_LENGTH)
message(FATAL_ERROR "KERNEL_MODULES and KERNEL_COMMANDS have different sizes: ${KERNEL_MODULES_LENGTH} vs ${KERNEL_COMMANDS_LENGTH}")
endif()
# TODO: Immediately here, error checking should happen
# But the error checking itself fails!!! and for some reason
# alkos_ensure_property_defined() says the property is not defined
Comment on lines +76 to +78

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create issue?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems important


################################# ThirdParty #################################

message(STATUS "Adding third-party libraries...")
add_subdirectory(thirdparty)

################################## Linking ###################################
target_link_libraries(alkos.kernel.deps INTERFACE
alkos.kernel.thirdparty
libk
AutoGenLib
)

target_link_libraries(alkos.kernel PRIVATE libk gcc ${THIRD_PARTY_LIBRARIES} AutoGenLib)
################################ Linking Kernel ################################

target_link_libraries(alkos.kernel PRIVATE
target.properties
alkos.kernel.config
alkos.kernel.headers
alkos.kernel.deps
)

############## Linker Configuration for CXX Global Constructors ##############
# Set the linker to link objects in the correct order
# NOTE: ARCH cmake is expected to provide variables for global constructors
# according to the compiler needs
# NOTE: This linking must be done at this level as global constructors
# should be supported on each architecture
if (NOT DEFINED CRTI_OBJ OR NOT DEFINED CRTN_OBJ)
message(FATAL_ERROR "One of: crti.o, crtn.o is not defined. Those should be defined in the ARCH CMakeLists.txt file")
endif ()

set(CMAKE_CXX_LINKER_LAUNCHER "/bin/bash -c")
set(CMAKE_CXX_LINK_EXECUTABLE
"/bin/bash -c \"${CMAKE_CXX_COMPILER} <CMAKE_CXX_LINK_FLAGS> <FLAGS> <LINK_FLAGS> \
${CRTI_OBJ} \
\$\(${CMAKE_C_COMPILER} -print-file-name=crtbegin.o\) \
<OBJECTS> \
\$\(${CMAKE_C_COMPILER} -print-file-name=crtend.o\) \
${CRTN_OBJ} \
-o <TARGET> <LINK_LIBRARIES>\""
# Retrieve our custom CRT object paths from the arch-specific configuration.
get_property(CRTI_OBJ_PATH TARGET alkos.kernel.config PROPERTY CRTI_OBJ)
get_property(CRTN_OBJ_PATH TARGET alkos.kernel.config PROPERTY CRTN_OBJ)
alkos_ensure_defined(
VARS CRTI_OBJ_PATH CRTN_OBJ_PATH
MESSAGE "CRTI_OBJ/CRTN_OBJ properties were not set by the architecture-specific CMake file."
)

# Find the compiler's CRT object files at configure-time.
execute_process(
COMMAND ${CMAKE_C_COMPILER} -print-file-name=crtbegin.o
OUTPUT_VARIABLE CRTBEGIN_OBJ_PATH
ERROR_VARIABLE CRTBEGIN_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${CMAKE_C_COMPILER} -print-file-name=crtend.o
OUTPUT_VARIABLE CRTEND_OBJ_PATH
ERROR_VARIABLE CRTEND_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
)

alkos_ensure_defined(
VARS CRTBEGIN_OBJ_PATH CRTEND_OBJ_PATH
MESSAGE "Could not find compiler's crtbegin.o/crtend.o files."
)

########################## Back-Propagate Variables ##########################
message(STATUS "Found CRT Objects:")
message(STATUS " crti: ${CRTI_OBJ_PATH}")
message(STATUS " crtbegin: ${CRTBEGIN_OBJ_PATH}")
message(STATUS " crtend: ${CRTEND_OBJ_PATH}")
message(STATUS " crtn: ${CRTN_OBJ_PATH}")

# TODO:
# The below code could technically be replaced with target_link_libraries()
# it also should enforce the correct linking order.
# I have done so with success, but it introduced a bug where no tests were
# detected in the kernel and I was unable to reslove it so gave up for now.

set(BOOTABLE_KERNEL_EXECUTABLE ${BOOTABLE_KERNEL_EXECUTABLE} PARENT_SCOPE)
set(KERNEL_MODULES ${KERNEL_MODULES} PARENT_SCOPE)
set(KERNEL_COMMANDS ${KERNEL_COMMANDS} PARENT_SCOPE)
# Add all objects and libraries to the kernel target in the correct link order.
# The linker requires: crti, crtbegin, <main objects>, <libraries>, crtend, crtn
set(CMAKE_CXX_LINK_EXECUTABLE
"${CMAKE_CXX_COMPILER} <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${CRTI_OBJ_PATH} ${CRTBEGIN_OBJ_PATH} <OBJECTS> ${CRTEND_OBJ_PATH} ${CRTN_OBJ_PATH} -o <TARGET> <LINK_LIBRARIES>"
)

set(ARCH_QEMU_COMMAND ${ARCH_QEMU_COMMAND} PARENT_SCOPE)
set(ARCH_QEMU_NORMAL_FLAGS ${ARCH_QEMU_NORMAL_FLAGS} PARENT_SCOPE)
set(ARCH_QEMU_TEST_FLAGS ${ARCH_QEMU_TEST_FLAGS} PARENT_SCOPE)
Loading