diff --git a/.gitignore b/.gitignore index 4dc89a3..4a3f4a4 100644 --- a/.gitignore +++ b/.gitignore @@ -17,9 +17,24 @@ # Build directories build/ +build-*/ bootloader/build/ kernel/build/ +# CMake specific +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +CMakeUserPresets.json +compile_commands.json +CTestTestfile.cmake + +# Conan specific +conaninfo.txt +conanbuildinfo.* +conan.lock +graph_info.json + # Test binaries tests/unit/test_* !tests/unit/*.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d152d2f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,161 @@ +# MetalOS Root CMakeLists.txt +cmake_minimum_required(VERSION 3.16) + +project(MetalOS + VERSION 0.1.0 + DESCRIPTION "Minimal OS for QT6 applications" + LANGUAGES C CXX ASM +) + +# Set C standard +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# Set C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Export compile commands for IDE support +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Default to Release build if not specified +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) +endif() + +# Options +option(BUILD_BOOTLOADER "Build UEFI bootloader" ON) +option(BUILD_KERNEL "Build kernel" ON) +option(BUILD_TESTS "Build unit tests" ON) + +# Build output directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + +# Create build directory for image +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/build) + +# Add subdirectories +if(BUILD_BOOTLOADER) + add_subdirectory(bootloader) +endif() + +if(BUILD_KERNEL) + add_subdirectory(kernel) +endif() + +if(BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() + +# Custom target to create bootable image +find_program(MFORMAT mformat) +find_program(MCOPY mcopy) +find_program(MDD mdd) + +if(MFORMAT AND MCOPY) + add_custom_target(image + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/build/iso/EFI/BOOT + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/bootloader/bootx64.efi + ${CMAKE_BINARY_DIR}/build/iso/EFI/BOOT/ + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/kernel/metalos.bin + ${CMAKE_BINARY_DIR}/build/iso/ + COMMAND ${CMAKE_COMMAND} -E echo "Creating disk image..." + COMMAND dd if=/dev/zero of=${CMAKE_BINARY_DIR}/build/metalos.img bs=1M count=64 2>/dev/null + COMMAND ${MFORMAT} -i ${CMAKE_BINARY_DIR}/build/metalos.img -F -v METALOS :: + COMMAND ${MDD} -i ${CMAKE_BINARY_DIR}/build/metalos.img ::/EFI + COMMAND ${MDD} -i ${CMAKE_BINARY_DIR}/build/metalos.img ::/EFI/BOOT + COMMAND ${MCOPY} -i ${CMAKE_BINARY_DIR}/build/metalos.img + ${CMAKE_BINARY_DIR}/build/iso/EFI/BOOT/bootx64.efi ::/EFI/BOOT/ + COMMAND ${MCOPY} -i ${CMAKE_BINARY_DIR}/build/metalos.img + ${CMAKE_BINARY_DIR}/build/iso/metalos.bin ::/ + COMMAND ${CMAKE_COMMAND} -E echo "Success! Created ${CMAKE_BINARY_DIR}/build/metalos.img" + DEPENDS bootloader_efi kernel_bin + COMMENT "Creating bootable disk image" + VERBATIM + ) +else() + message(WARNING "mtools not found - 'image' target will not be available") +endif() + +# Custom target to run in QEMU +find_program(QEMU qemu-system-x86_64) +if(QEMU) + # Find OVMF firmware + set(OVMF_PATHS + /usr/share/OVMF/OVMF_CODE.fd + /usr/share/ovmf/OVMF.fd + /usr/share/edk2-ovmf/x64/OVMF_CODE.fd + /usr/share/qemu/ovmf-x86_64.bin + ) + + foreach(ovmf_path ${OVMF_PATHS}) + if(EXISTS ${ovmf_path}) + set(OVMF_FIRMWARE ${ovmf_path}) + break() + endif() + endforeach() + + if(OVMF_FIRMWARE) + message(STATUS "Found OVMF firmware: ${OVMF_FIRMWARE}") + + add_custom_target(qemu + COMMAND ${QEMU} + -drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE} + -drive format=raw,file=${CMAKE_BINARY_DIR}/build/metalos.img + -m 512M + -serial stdio + -display none + -net none + DEPENDS image + COMMENT "Running MetalOS in QEMU" + VERBATIM + ) + + add_custom_target(qemu-debug + COMMAND ${QEMU} + -drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE} + -drive format=raw,file=${CMAKE_BINARY_DIR}/build/metalos.img + -m 512M + -serial stdio + -display none + -net none + -d int,cpu_reset + DEPENDS image + COMMENT "Running MetalOS in QEMU with debug output" + VERBATIM + ) + + add_custom_target(qemu-gdb + COMMAND ${QEMU} + -drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE} + -drive format=raw,file=${CMAKE_BINARY_DIR}/build/metalos.img + -m 512M + -serial stdio + -display none + -net none + -s -S + DEPENDS image + COMMENT "Running MetalOS in QEMU with GDB server (port 1234)" + VERBATIM + ) + else() + message(WARNING "OVMF firmware not found - QEMU targets will not be available") + endif() +else() + message(WARNING "QEMU not found - QEMU targets will not be available") +endif() + +# Print configuration summary +message(STATUS "") +message(STATUS "MetalOS Configuration:") +message(STATUS " Version: ${PROJECT_VERSION}") +message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") +message(STATUS " Bootloader: ${BUILD_BOOTLOADER}") +message(STATUS " Kernel: ${BUILD_KERNEL}") +message(STATUS " Tests: ${BUILD_TESTS}") +message(STATUS "") diff --git a/README.md b/README.md index 8ac88be..06883b4 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,36 @@ See [docs/ROADMAP.md](docs/ROADMAP.md) for detailed phase breakdown. ## Building -### Docker Build (Recommended) +MetalOS supports **multiple build systems** - choose what works best for you! + +### Quick Start (Make - Traditional) + +```bash +make all # Build bootloader, kernel, and userspace +make test # Run unit tests +make qemu # Test in QEMU with UEFI firmware +make clean # Clean build artifacts +``` + +### CMake + Ninja (Fast Modern Build) + +```bash +mkdir build && cd build +cmake -G Ninja .. +ninja +ninja qemu +``` + +### Conan (With Package Management) + +```bash +mkdir build && cd build +conan install .. --build=missing +cmake .. -DCMAKE_TOOLCHAIN_FILE=../build/Release/generators/conan_toolchain.cmake -G Ninja +ninja +``` + +### Docker Build (Recommended for Consistency) The easiest way to build MetalOS with all dependencies: @@ -78,14 +107,7 @@ The easiest way to build MetalOS with all dependencies: ./scripts/docker-run.sh make qemu # Test in QEMU ``` -### Native Build - -```bash -make all # Build bootloader, kernel, and userspace -make test # Run unit tests -make qemu # Test in QEMU with UEFI firmware -make clean # Clean build artifacts -``` +**See [docs/BUILD_SYSTEMS.md](docs/BUILD_SYSTEMS.md) for detailed comparison and usage of all build systems.** **QEMU UEFI Testing**: ```bash diff --git a/bootloader/CMakeLists.txt b/bootloader/CMakeLists.txt new file mode 100644 index 0000000..627aa12 --- /dev/null +++ b/bootloader/CMakeLists.txt @@ -0,0 +1,84 @@ +# MetalOS Bootloader CMakeLists.txt +# Builds UEFI bootloader (bootx64.efi) + +cmake_minimum_required(VERSION 3.16) + +project(MetalOS_Bootloader C) + +# Source files +set(BOOTLOADER_SOURCES + src/main.c +) + +# Header files +set(BOOTLOADER_HEADERS + include/bootloader.h + include/efi.h +) + +# Compiler flags for UEFI +set(UEFI_CFLAGS + -Wall + -Wextra + -Werror + -ffreestanding + -fno-stack-protector + -fno-stack-check + -fshort-wchar + -mno-red-zone + -DEFI_FUNCTION_WRAPPER +) + +# Linker flags for UEFI +set(UEFI_LDFLAGS + -shared + -Bsymbolic + -nostdlib + -znocombreloc +) + +# Create object library +add_library(bootloader_obj OBJECT ${BOOTLOADER_SOURCES}) +target_include_directories(bootloader_obj PRIVATE include) +target_compile_options(bootloader_obj PRIVATE ${UEFI_CFLAGS}) + +# Create shared library (intermediate) +add_library(bootloader_so SHARED $) +set_target_properties(bootloader_so PROPERTIES + OUTPUT_NAME bootx64 + SUFFIX .so + LINKER_LANGUAGE C +) +target_link_options(bootloader_so PRIVATE + ${UEFI_LDFLAGS} + -T ${CMAKE_CURRENT_SOURCE_DIR}/uefi.lds +) + +# Custom command to convert .so to .efi +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi + COMMAND ${CMAKE_OBJCOPY} + -j .text -j .sdata -j .data -j .dynamic + -j .dynsym -j .rel -j .rela -j .reloc + --target=efi-app-x86_64 + $ + ${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi + DEPENDS bootloader_so + COMMENT "Converting bootloader to EFI format" + VERBATIM +) + +# Custom target for the EFI file +add_custom_target(bootloader_efi ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi +) + +# Install target +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi + DESTINATION boot/efi/EFI/BOOT +) + +# Print status +message(STATUS "Bootloader configuration:") +message(STATUS " Sources: ${BOOTLOADER_SOURCES}") +message(STATUS " Output: bootx64.efi") diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..bba19c2 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,72 @@ +""" +MetalOS Conan Package Configuration + +This file defines the dependencies and build configuration for MetalOS. +Currently, MetalOS is a freestanding OS with no external dependencies, +but this file is prepared for future use when we integrate: +- Mesa RADV (GPU driver) +- QT6 (application framework) +- Other system libraries +""" + +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout + + +class MetalOSConan(ConanFile): + name = "metalos" + version = "0.1.0" + license = "MIT" + author = "MetalOS Contributors" + url = "https://github.com/johndoe6345789/MetalOS" + description = "Minimal OS for QT6 applications on AMD64 + Radeon RX 6600" + topics = ("os", "uefi", "minimal", "qt6", "gpu") + + settings = "os", "compiler", "build_type", "arch" + options = { + "build_bootloader": [True, False], + "build_kernel": [True, False], + "build_tests": [True, False], + } + default_options = { + "build_bootloader": True, + "build_kernel": True, + "build_tests": True, + } + + # Specify which generator to use (cmake, make, ninja, etc.) + generators = "CMakeDeps" + + # No external dependencies yet (freestanding OS) + # Future dependencies will be added here: + # requires = ( + # "qt/6.5.0@qt/stable", # When we port QT6 + # "mesa/22.3.0@system/stable", # When we integrate Mesa RADV + # ) + + def layout(self): + cmake_layout(self) + + def generate(self): + tc = CMakeToolchain(self) + # Pass options to CMake + tc.variables["BUILD_BOOTLOADER"] = self.options.build_bootloader + tc.variables["BUILD_KERNEL"] = self.options.build_kernel + tc.variables["BUILD_TESTS"] = self.options.build_tests + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + + def package_info(self): + self.cpp_info.libs = [] # MetalOS doesn't provide libraries + self.cpp_info.bindirs = ["boot", "boot/efi/EFI/BOOT"] + + # Set environment variables for tools that need to find our binaries + self.buildenv_info.append_path("PATH", self.package_folder) diff --git a/docs/BUILD_SYSTEMS.md b/docs/BUILD_SYSTEMS.md new file mode 100644 index 0000000..a129a4f --- /dev/null +++ b/docs/BUILD_SYSTEMS.md @@ -0,0 +1,418 @@ +# MetalOS Build Systems Guide + +MetalOS supports multiple build systems to accommodate different developer preferences and workflows. + +## Quick Start + +### Using Make (Traditional) +```bash +make all # Build everything +make qemu # Test in QEMU +make clean # Clean build artifacts +``` + +### Using CMake + Make +```bash +mkdir build && cd build +cmake .. +cmake --build . +``` + +### Using CMake + Ninja (Fastest) +```bash +mkdir build && cd build +cmake -G Ninja .. +ninja +``` + +### Using Conan + CMake +```bash +mkdir build && cd build +conan install .. --build=missing +cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake +cmake --build . +``` + +## Build System Comparison + +| Build System | Speed | Features | Best For | +|--------------|-------|----------|----------| +| **Make** | Medium | Simple, traditional | Quick builds, CI/CD | +| **CMake** | Medium | Cross-platform, modern | Complex projects, IDEs | +| **Ninja** | Fast | Parallel builds | Development, large projects | +| **Conan** | Medium | Dependency management | Projects with external deps | + +## Detailed Usage + +### 1. Make (Traditional Build System) + +The original build system using GNU Make. + +#### Build Commands +```bash +# Build all components +make all + +# Build individually +make bootloader +make kernel +make test + +# Create bootable image +make image + +# Run in QEMU +make qemu # Headless mode +make qemu QEMU_DISPLAY=gtk # With GUI +make qemu-debug # With debug output +make qemu-gdb # With GDB server + +# Clean +make clean # Clean build artifacts +make distclean # Deep clean +``` + +#### Advantages +- ✅ Simple and straightforward +- ✅ No additional dependencies +- ✅ Works on all Unix-like systems +- ✅ Easy to understand and modify + +#### Disadvantages +- ❌ Not cross-platform (Windows requires special setup) +- ❌ Can be slower for large projects +- ❌ Limited dependency tracking + +--- + +### 2. CMake (Modern Build Generator) + +CMake generates build files for various build systems (Make, Ninja, Visual Studio, etc.). + +#### Build Commands +```bash +# Configure (generates build files) +mkdir build && cd build +cmake .. + +# Configure with specific generator +cmake -G "Unix Makefiles" .. +cmake -G Ninja .. +cmake -G "Visual Studio 17 2022" .. # Windows + +# Configure with options +cmake -DBUILD_BOOTLOADER=ON -DBUILD_KERNEL=ON -DBUILD_TESTS=ON .. +cmake -DCMAKE_BUILD_TYPE=Debug .. +cmake -DCMAKE_BUILD_TYPE=Release .. + +# Build +cmake --build . +cmake --build . --parallel 8 # Use 8 parallel jobs + +# Build specific targets +cmake --build . --target bootloader_efi +cmake --build . --target kernel_bin +cmake --build . --target image + +# Run custom targets +cmake --build . --target qemu +cmake --build . --target qemu-debug +cmake --build . --target qemu-gdb + +# Test +ctest +ctest --output-on-failure +ctest -V # Verbose + +# Install +cmake --install . +cmake --install . --prefix /path/to/install + +# Clean +cmake --build . --target clean +rm -rf build # Complete clean +``` + +#### Advantages +- ✅ Cross-platform (Windows, Linux, macOS) +- ✅ IDE integration (CLion, Visual Studio, VS Code) +- ✅ Modern and widely adopted +- ✅ Better dependency tracking +- ✅ Supports multiple generators + +#### Disadvantages +- ❌ More complex than Make +- ❌ Requires CMake to be installed +- ❌ Learning curve for CMakeLists.txt syntax + +--- + +### 3. Ninja (Fast Build System) + +Ninja is designed for speed and is often used with CMake. + +#### Build Commands +```bash +# Configure with Ninja generator +mkdir build && cd build +cmake -G Ninja .. + +# Build (much faster than Make) +ninja + +# Build specific targets +ninja bootloader_efi +ninja kernel_bin +ninja image +ninja qemu + +# Clean +ninja clean +``` + +#### Advantages +- ✅ **Very fast** - optimized for speed +- ✅ Better parallelization than Make +- ✅ Accurate dependency tracking +- ✅ Clean output format +- ✅ Works great with CMake + +#### Disadvantages +- ❌ Requires Ninja to be installed +- ❌ Less familiar than Make +- ❌ Requires CMake to generate build files + +--- + +### 4. Conan (Package Manager + Build System) + +Conan manages dependencies and integrates with CMake. + +#### Setup +```bash +# Install Conan (first time only) +pip install conan + +# Initialize Conan profile (first time only) +conan profile detect --force +``` + +#### Build Commands +```bash +# Create build directory +mkdir build && cd build + +# Install dependencies (currently none, but ready for future) +conan install .. --build=missing + +# Alternative: Install with specific settings +conan install .. --build=missing -s build_type=Debug +conan install .. --build=missing -s build_type=Release + +# Configure with Conan-generated toolchain +cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + +# Build +cmake --build . + +# Or use Conan to build directly +cd .. +conan build . --build-folder=build +``` + +#### Advantages +- ✅ Dependency management (for future QT6, Mesa, etc.) +- ✅ Reproducible builds +- ✅ Version management +- ✅ Cross-platform package management +- ✅ Integration with CMake and other build systems + +#### Disadvantages +- ❌ Requires Python and Conan +- ❌ Additional complexity +- ❌ Currently overkill (we have no dependencies yet) +- ❌ Learning curve + +--- + +## Which Build System Should I Use? + +### For Quick Development +**Use: Make or CMake + Ninja** +```bash +# Make - simplest +make all && make qemu + +# Or Ninja - fastest +cd build-ninja && ninja && ninja qemu +``` + +### For IDE Integration +**Use: CMake** +- Works with CLion, Visual Studio Code, Visual Studio +- Configure your IDE to use the CMakeLists.txt + +### For CI/CD +**Use: Make or CMake** +```bash +# GitHub Actions, GitLab CI, etc. +make all && make test + +# Or with CMake +cmake -B build -G Ninja +cmake --build build +ctest --test-dir build +``` + +### For Cross-Platform Development +**Use: CMake + Ninja** +```bash +# Works on Linux, macOS, Windows +cmake -G Ninja -B build +cmake --build build +``` + +### For Projects with Dependencies (Future) +**Use: Conan + CMake** +```bash +# When we add QT6, Mesa RADV, etc. +conan install . --build=missing +cmake --preset conan-release +cmake --build --preset conan-release +``` + +--- + +## File Structure + +``` +MetalOS/ +├── Makefile # Traditional Make build +├── CMakeLists.txt # Root CMake configuration +├── conanfile.py # Conan package definition +├── conanfile.txt # Simple Conan configuration +├── bootloader/ +│ ├── Makefile # Bootloader Make build +│ └── CMakeLists.txt # Bootloader CMake build +├── kernel/ +│ ├── Makefile # Kernel Make build +│ └── CMakeLists.txt # Kernel CMake build +└── tests/ + ├── Makefile # Tests Make build + └── CMakeLists.txt # Tests CMake build +``` + +--- + +## Common Build Options + +### CMake Options +```bash +# Enable/disable components +-DBUILD_BOOTLOADER=ON/OFF +-DBUILD_KERNEL=ON/OFF +-DBUILD_TESTS=ON/OFF + +# Build type +-DCMAKE_BUILD_TYPE=Debug +-DCMAKE_BUILD_TYPE=Release +-DCMAKE_BUILD_TYPE=RelWithDebInfo + +# Compiler +-DCMAKE_C_COMPILER=/usr/bin/gcc +-DCMAKE_CXX_COMPILER=/usr/bin/g++ + +# Install prefix +-DCMAKE_INSTALL_PREFIX=/opt/metalos +``` + +### Make Options +```bash +# Display mode for QEMU +QEMU_DISPLAY=gtk +QEMU_DISPLAY=sdl +QEMU_DISPLAY=none + +# Verbose output +V=1 +VERBOSE=1 +``` + +--- + +## Troubleshooting + +### CMake: Ninja not found +```bash +# Ubuntu/Debian +sudo apt-get install ninja-build + +# macOS +brew install ninja + +# Arch Linux +sudo pacman -S ninja +``` + +### CMake: OVMF not found +```bash +# Ubuntu/Debian +sudo apt-get install ovmf + +# Arch Linux +sudo pacman -S edk2-ovmf + +# Or specify manually +cmake .. -DOVMF_FIRMWARE=/path/to/OVMF.fd +``` + +### Conan: Profile not found +```bash +# Detect default profile +conan profile detect --force + +# Create custom profile +conan profile show default > myprofile +# Edit myprofile as needed +conan install .. --profile=myprofile +``` + +--- + +## Performance Comparison + +Build time for clean build (approximate): + +| Build System | Time | Notes | +|--------------|------|-------| +| Make | ~2s | Single-threaded by default | +| Make -j8 | ~1s | With 8 parallel jobs | +| CMake + Make | ~2s | Same as Make | +| CMake + Ninja| ~0.5s| Fastest option | +| Conan + CMake| ~3s | Additional dependency resolution | + +*Times measured on a typical development machine. Your results may vary.* + +--- + +## Future Plans + +As MetalOS grows and adds dependencies (QT6, Mesa RADV), we recommend: + +1. **Development**: CMake + Ninja (fastest iteration) +2. **Dependency Management**: Conan (when dependencies are added) +3. **CI/CD**: Keep Make for simplicity, or migrate to CMake +4. **Distribution**: Create Conan packages for easy installation + +--- + +## Getting Help + +- Check `docs/BUILD.md` for detailed build instructions +- See `docs/DEVELOPMENT.md` for development workflow +- Read individual Makefiles and CMakeLists.txt for specifics +- Check `conanfile.py` comments for dependency information + +--- + +**Note**: All build systems produce identical outputs. Choose based on your workflow and preferences! diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt new file mode 100644 index 0000000..02aeee3 --- /dev/null +++ b/kernel/CMakeLists.txt @@ -0,0 +1,79 @@ +# MetalOS Kernel CMakeLists.txt +# Builds minimal kernel binary + +cmake_minimum_required(VERSION 3.16) + +project(MetalOS_Kernel C ASM) + +# Source files +set(KERNEL_SOURCES + src/main.c +) + +# Find all source files in subdirectories +file(GLOB_RECURSE CORE_SOURCES "src/core/*.c") +file(GLOB_RECURSE HAL_SOURCES "src/hal/*.c") +file(GLOB_RECURSE DRIVER_SOURCES "src/drivers/*.c") +file(GLOB_RECURSE SYSCALL_SOURCES "src/syscall/*.c") + +list(APPEND KERNEL_SOURCES + ${CORE_SOURCES} + ${HAL_SOURCES} + ${DRIVER_SOURCES} + ${SYSCALL_SOURCES} +) + +# Compiler flags for kernel +set(KERNEL_CFLAGS + -Wall + -Wextra + -Werror + -ffreestanding + -fno-stack-protector + -mno-red-zone + -mcmodel=large + -O2 +) + +# Create object library +add_library(kernel_obj OBJECT ${KERNEL_SOURCES}) +target_include_directories(kernel_obj PRIVATE include) +target_compile_options(kernel_obj PRIVATE ${KERNEL_CFLAGS}) + +# Create kernel binary +add_executable(kernel_elf $) +set_target_properties(kernel_elf PROPERTIES + OUTPUT_NAME metalos.elf + LINKER_LANGUAGE C +) +target_link_options(kernel_elf PRIVATE + -nostdlib + -T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld +) + +# Custom command to create flat binary +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin + COMMAND ${CMAKE_OBJCOPY} + -O binary + $ + ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin + DEPENDS kernel_elf + COMMENT "Creating kernel flat binary" + VERBATIM +) + +# Custom target for the binary +add_custom_target(kernel_bin ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin +) + +# Install target +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin + DESTINATION boot +) + +# Print status +message(STATUS "Kernel configuration:") +message(STATUS " Sources: ${KERNEL_SOURCES}") +message(STATUS " Output: metalos.bin") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..f0785a9 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,47 @@ +# MetalOS Tests CMakeLists.txt +# Builds and runs unit tests + +cmake_minimum_required(VERSION 3.16) + +project(MetalOS_Tests C) + +# Find all test source files +file(GLOB TEST_SOURCES "unit/*.c") + +# Include directories +include_directories( + include + ../bootloader/include + ../kernel/include +) + +# Create a test executable for each test file +foreach(test_source ${TEST_SOURCES}) + # Get the test name from the file name + get_filename_component(test_name ${test_source} NAME_WE) + + # Create test executable + add_executable(${test_name} ${test_source}) + + # Set compiler flags + target_compile_options(${test_name} PRIVATE + -Wall + -Wextra + -std=c11 + ) + + # Add as a test + add_test(NAME ${test_name} COMMAND ${test_name}) +endforeach() + +# Custom target to run all tests +add_custom_target(run_tests + COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure + DEPENDS ${TEST_SOURCES} + COMMENT "Running all tests" + VERBATIM +) + +# Print status +message(STATUS "Tests configuration:") +message(STATUS " Test sources: ${TEST_SOURCES}")