mirror of
https://github.com/johndoe6345789/MetalOS.git
synced 2026-04-24 13:45:02 +00:00
Merge pull request #16 from johndoe6345789/copilot/remove-makefile-support
Migrate to pure CMake build system by removing all Makefiles
This commit is contained in:
42
.github/workflows/qemu-test.yml
vendored
42
.github/workflows/qemu-test.yml
vendored
@@ -25,6 +25,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
nasm \
|
||||
qemu-system-x86 \
|
||||
ovmf \
|
||||
@@ -32,19 +33,21 @@ jobs:
|
||||
xorriso \
|
||||
imagemagick
|
||||
|
||||
- name: Build bootloader
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
cd bootloader
|
||||
make
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
|
||||
- name: Build kernel
|
||||
- name: Build bootloader and kernel
|
||||
run: |
|
||||
cd kernel
|
||||
make
|
||||
cd build
|
||||
cmake --build .
|
||||
|
||||
- name: Create bootable image
|
||||
run: |
|
||||
make image
|
||||
cd build
|
||||
cmake --build . --target image
|
||||
|
||||
- name: Start QEMU and capture screenshot
|
||||
run: |
|
||||
@@ -56,19 +59,22 @@ jobs:
|
||||
XVFB_PID=$!
|
||||
sleep 2
|
||||
|
||||
# Verify disk image exists (created by 'make image')
|
||||
if [ ! -f build/metalos.img ]; then
|
||||
echo "Error: build/metalos.img not found!"
|
||||
# Verify disk image exists (created by cmake build)
|
||||
if [ ! -f build/build/metalos.img ]; then
|
||||
echo "Error: build/build/metalos.img not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create directory for logs
|
||||
mkdir -p build/logs
|
||||
|
||||
# Start QEMU in the background with a timeout
|
||||
timeout 30s qemu-system-x86_64 \
|
||||
-bios /usr/share/OVMF/OVMF_CODE.fd \
|
||||
-drive format=raw,file=build/metalos.img \
|
||||
-drive format=raw,file=build/build/metalos.img \
|
||||
-m 512M \
|
||||
-display gtk \
|
||||
-serial file:build/serial.log \
|
||||
-serial file:build/logs/serial.log \
|
||||
-no-reboot &
|
||||
QEMU_PID=$!
|
||||
|
||||
@@ -77,7 +83,7 @@ jobs:
|
||||
|
||||
# Take screenshot using ImageMagick (optional - don't fail if this doesn't work)
|
||||
# Using subshell to prevent 'set -e' from affecting this optional step
|
||||
{ import -window root build/qemu-screenshot.png; } || echo "Screenshot capture failed (non-fatal)"
|
||||
{ import -window root build/logs/qemu-screenshot.png; } || echo "Screenshot capture failed (non-fatal)"
|
||||
|
||||
# Gracefully stop QEMU (don't fail if already stopped)
|
||||
kill $QEMU_PID 2>/dev/null || true
|
||||
@@ -91,9 +97,9 @@ jobs:
|
||||
- name: Show serial output
|
||||
if: always()
|
||||
run: |
|
||||
if [ -f build/serial.log ]; then
|
||||
if [ -f build/logs/serial.log ]; then
|
||||
echo "=== QEMU Serial Output ==="
|
||||
cat build/serial.log
|
||||
cat build/logs/serial.log
|
||||
else
|
||||
echo "No serial output captured"
|
||||
fi
|
||||
@@ -103,7 +109,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: qemu-screenshot
|
||||
path: build/qemu-screenshot.png
|
||||
path: build/logs/qemu-screenshot.png
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Upload serial log
|
||||
@@ -111,7 +117,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: serial-log
|
||||
path: build/serial.log
|
||||
path: build/logs/serial.log
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Upload built disk image
|
||||
@@ -119,5 +125,5 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: metalos-disk-image
|
||||
path: build/metalos.img
|
||||
path: build/build/metalos.img
|
||||
if-no-files-found: warn
|
||||
|
||||
35
.github/workflows/release.yml
vendored
35
.github/workflows/release.yml
vendored
@@ -24,25 +24,28 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
nasm \
|
||||
qemu-system-x86 \
|
||||
ovmf \
|
||||
mtools \
|
||||
xorriso
|
||||
|
||||
- name: Build bootloader
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
cd bootloader
|
||||
make
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
|
||||
- name: Build kernel
|
||||
- name: Build bootloader and kernel
|
||||
run: |
|
||||
cd kernel
|
||||
make
|
||||
cd build
|
||||
cmake --build .
|
||||
|
||||
- name: Create bootable image
|
||||
run: |
|
||||
make image
|
||||
cd build
|
||||
cmake --build . --target image
|
||||
|
||||
- name: Prepare release directory
|
||||
run: |
|
||||
@@ -51,29 +54,29 @@ jobs:
|
||||
mkdir -p release
|
||||
|
||||
# Copy the bootable disk image (required)
|
||||
if [ -f build/metalos.img ]; then
|
||||
cp build/metalos.img release/
|
||||
if [ -f build/build/metalos.img ]; then
|
||||
cp build/build/metalos.img release/
|
||||
echo "✓ Copied metalos.img"
|
||||
else
|
||||
echo "Error: build/metalos.img not found!"
|
||||
echo "Error: build/build/metalos.img not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy bootloader if it exists (required)
|
||||
if [ -f bootloader/bootx64.efi ]; then
|
||||
cp bootloader/bootx64.efi release/
|
||||
if [ -f build/bootloader/bootx64.efi ]; then
|
||||
cp build/bootloader/bootx64.efi release/
|
||||
echo "✓ Copied bootx64.efi"
|
||||
else
|
||||
echo "Error: bootloader/bootx64.efi not found!"
|
||||
echo "Error: build/bootloader/bootx64.efi not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy kernel if it exists (required)
|
||||
if [ -f kernel/metalos.bin ]; then
|
||||
cp kernel/metalos.bin release/
|
||||
if [ -f build/kernel/metalos.bin ]; then
|
||||
cp build/kernel/metalos.bin release/
|
||||
echo "✓ Copied metalos.bin"
|
||||
else
|
||||
echo "Error: kernel/metalos.bin not found!"
|
||||
echo "Error: build/kernel/metalos.bin not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
16
.github/workflows/unit-tests.yml
vendored
16
.github/workflows/unit-tests.yml
vendored
@@ -22,17 +22,23 @@ jobs:
|
||||
set -e # Exit on any error
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential
|
||||
sudo apt-get install -y build-essential cmake
|
||||
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
|
||||
- name: Build unit tests
|
||||
run: |
|
||||
cd tests
|
||||
make all
|
||||
cd build
|
||||
cmake --build .
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
cd tests
|
||||
make test
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: Test summary
|
||||
if: always()
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -18,6 +18,8 @@
|
||||
# Build directories
|
||||
build/
|
||||
build-*/
|
||||
cmake-build/
|
||||
cmake-build-*/
|
||||
bootloader/build/
|
||||
kernel/build/
|
||||
_codeql_build_dir/
|
||||
|
||||
@@ -53,9 +53,9 @@ endif()
|
||||
# Custom target to create bootable image
|
||||
find_program(MFORMAT mformat)
|
||||
find_program(MCOPY mcopy)
|
||||
find_program(MDD mdd)
|
||||
find_program(MMD mmd)
|
||||
|
||||
if(MFORMAT AND MCOPY)
|
||||
if(MFORMAT AND MCOPY AND MMD)
|
||||
add_custom_target(image
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/build/iso/EFI/BOOT
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
@@ -65,10 +65,10 @@ if(MFORMAT AND MCOPY)
|
||||
${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 dd if=/dev/zero of=${CMAKE_BINARY_DIR}/build/metalos.img bs=1M count=64
|
||||
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 ${MMD} -i ${CMAKE_BINARY_DIR}/build/metalos.img ::/EFI
|
||||
COMMAND ${MMD} -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
|
||||
@@ -143,6 +143,20 @@ if(QEMU)
|
||||
COMMENT "Running MetalOS in QEMU with GDB server (port 1234)"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(qemu-uefi-test
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Testing QEMU UEFI boot (no OS image)..."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Using OVMF firmware: ${OVMF_FIRMWARE}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "This will boot to UEFI shell in nographic mode."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "You should see UEFI boot messages. Press Ctrl-A then X to exit QEMU."
|
||||
COMMAND ${QEMU}
|
||||
-drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE}
|
||||
-m 512M
|
||||
-nographic
|
||||
-net none
|
||||
COMMENT "Testing QEMU UEFI setup without OS image"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
message(WARNING "OVMF firmware not found - QEMU targets will not be available")
|
||||
endif()
|
||||
|
||||
@@ -152,9 +152,19 @@ Closes #42
|
||||
Every PR should be tested in QEMU:
|
||||
|
||||
```bash
|
||||
make clean
|
||||
make all
|
||||
make qemu
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
cmake --build . --target qemu
|
||||
```
|
||||
|
||||
Or if you already have a build directory:
|
||||
|
||||
```bash
|
||||
cd build
|
||||
cmake --build . --target clean
|
||||
cmake --build .
|
||||
cmake --build . --target qemu
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
144
Makefile
144
Makefile
@@ -1,144 +0,0 @@
|
||||
# MetalOS Main Makefile
|
||||
# Builds bootloader, kernel, and creates bootable image
|
||||
|
||||
.PHONY: all bootloader kernel image qemu qemu-debug qemu-gdb qemu-uefi-test test clean distclean
|
||||
|
||||
all: bootloader kernel
|
||||
|
||||
# Run unit tests
|
||||
test:
|
||||
@echo "Running unit tests..."
|
||||
@cd tests && $(MAKE) test
|
||||
|
||||
bootloader:
|
||||
@echo "Building bootloader..."
|
||||
@cd bootloader && $(MAKE) || echo "Warning: Bootloader build failed (expected during Phase 1 development)"
|
||||
|
||||
kernel:
|
||||
@echo "Building kernel..."
|
||||
@cd kernel && $(MAKE) || echo "Warning: Kernel build failed (expected during Phase 1 development)"
|
||||
|
||||
# Create bootable disk image for UEFI/QEMU
|
||||
image: bootloader kernel
|
||||
@chmod +x scripts/create_image.sh
|
||||
@./scripts/create_image.sh
|
||||
|
||||
# Run in QEMU with UEFI firmware (OVMF)
|
||||
# Automatically detects OVMF path and display mode
|
||||
# Set QEMU_DISPLAY=gtk or QEMU_DISPLAY=sdl to use graphical mode
|
||||
QEMU_DISPLAY ?= none
|
||||
|
||||
qemu: image
|
||||
@echo "Starting QEMU with UEFI firmware..."
|
||||
@bash -c ' \
|
||||
if [ -f /usr/share/OVMF/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/OVMF/OVMF_CODE.fd"; \
|
||||
elif [ -f /usr/share/ovmf/OVMF.fd ]; then \
|
||||
OVMF="/usr/share/ovmf/OVMF.fd"; \
|
||||
elif [ -f /usr/share/edk2-ovmf/x64/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/edk2-ovmf/x64/OVMF_CODE.fd"; \
|
||||
elif [ -f /usr/share/qemu/ovmf-x86_64.bin ]; then \
|
||||
OVMF="/usr/share/qemu/ovmf-x86_64.bin"; \
|
||||
else \
|
||||
echo "Error: OVMF UEFI firmware not found!"; \
|
||||
echo "Install with:"; \
|
||||
echo " Ubuntu/Debian: sudo apt-get install ovmf"; \
|
||||
echo " Arch Linux: sudo pacman -S edk2-ovmf"; \
|
||||
echo " Fedora: sudo dnf install edk2-ovmf"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "Using OVMF firmware: $$OVMF"; \
|
||||
echo "Display mode: $(QEMU_DISPLAY) (set QEMU_DISPLAY=gtk for graphical)"; \
|
||||
qemu-system-x86_64 \
|
||||
-drive if=pflash,format=raw,readonly=on,file=$$OVMF \
|
||||
-drive format=raw,file=build/metalos.img \
|
||||
-m 512M \
|
||||
-serial stdio \
|
||||
-display $(QEMU_DISPLAY) \
|
||||
-net none \
|
||||
'
|
||||
|
||||
qemu-debug: image
|
||||
@echo "Starting QEMU with debug output..."
|
||||
@bash -c ' \
|
||||
if [ -f /usr/share/OVMF/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/OVMF/OVMF_CODE.fd"; \
|
||||
elif [ -f /usr/share/ovmf/OVMF.fd ]; then \
|
||||
OVMF="/usr/share/ovmf/OVMF.fd"; \
|
||||
elif [ -f /usr/share/edk2-ovmf/x64/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/edk2-ovmf/x64/OVMF_CODE.fd"; \
|
||||
else \
|
||||
echo "Error: OVMF UEFI firmware not found!"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
qemu-system-x86_64 \
|
||||
-drive if=pflash,format=raw,readonly=on,file=$$OVMF \
|
||||
-drive format=raw,file=build/metalos.img \
|
||||
-m 512M \
|
||||
-serial stdio \
|
||||
-display $(QEMU_DISPLAY) \
|
||||
-net none \
|
||||
-d int,cpu_reset \
|
||||
'
|
||||
|
||||
qemu-gdb: image
|
||||
@echo "Starting QEMU with GDB server on port 1234..."
|
||||
@bash -c ' \
|
||||
if [ -f /usr/share/OVMF/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/OVMF/OVMF_CODE.fd"; \
|
||||
elif [ -f /usr/share/ovmf/OVMF.fd ]; then \
|
||||
OVMF="/usr/share/ovmf/OVMF.fd"; \
|
||||
elif [ -f /usr/share/edk2-ovmf/x64/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/edk2-ovmf/x64/OVMF_CODE.fd"; \
|
||||
else \
|
||||
echo "Error: OVMF UEFI firmware not found!"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "QEMU will wait for GDB connection on localhost:1234"; \
|
||||
echo "In another terminal, run: gdb kernel/metalos.bin"; \
|
||||
echo "Then in GDB: target remote localhost:1234"; \
|
||||
qemu-system-x86_64 \
|
||||
-drive if=pflash,format=raw,readonly=on,file=$$OVMF \
|
||||
-drive format=raw,file=build/metalos.img \
|
||||
-m 512M \
|
||||
-serial stdio \
|
||||
-display $(QEMU_DISPLAY) \
|
||||
-net none \
|
||||
-s -S \
|
||||
'
|
||||
|
||||
# Quick UEFI test - boots to UEFI shell without OS (for verifying QEMU+OVMF setup)
|
||||
qemu-uefi-test:
|
||||
@echo "Testing QEMU UEFI boot (no OS image)..."
|
||||
@bash -c ' \
|
||||
if [ -f /usr/share/OVMF/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/OVMF/OVMF_CODE.fd"; \
|
||||
elif [ -f /usr/share/ovmf/OVMF.fd ]; then \
|
||||
OVMF="/usr/share/ovmf/OVMF.fd"; \
|
||||
elif [ -f /usr/share/edk2-ovmf/x64/OVMF_CODE.fd ]; then \
|
||||
OVMF="/usr/share/edk2-ovmf/x64/OVMF_CODE.fd"; \
|
||||
else \
|
||||
echo "Error: OVMF UEFI firmware not found!"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
echo "Using OVMF firmware: $$OVMF"; \
|
||||
echo "This will boot to UEFI shell in nographic mode."; \
|
||||
echo "You should see UEFI boot messages. Press Ctrl-A then X to exit QEMU."; \
|
||||
qemu-system-x86_64 \
|
||||
-drive if=pflash,format=raw,readonly=on,file=$$OVMF \
|
||||
-m 512M \
|
||||
-nographic \
|
||||
-net none \
|
||||
'
|
||||
|
||||
clean:
|
||||
@echo "Cleaning build artifacts..."
|
||||
@cd bootloader && $(MAKE) clean
|
||||
@cd kernel && $(MAKE) clean
|
||||
@cd tests && $(MAKE) clean
|
||||
@rm -rf build
|
||||
|
||||
distclean: clean
|
||||
@echo "Deep clean..."
|
||||
@find . -name "*.o" -delete
|
||||
@find . -name "*.d" -delete
|
||||
28
README.md
28
README.md
@@ -67,18 +67,18 @@ See [docs/ROADMAP.md](docs/ROADMAP.md) for detailed phase breakdown.
|
||||
|
||||
## Building
|
||||
|
||||
MetalOS supports **multiple build systems** - choose what works best for you!
|
||||
MetalOS uses **CMake** as its build system for a modern, cross-platform build experience.
|
||||
|
||||
### Quick Start (Make - Traditional)
|
||||
### Quick Start (CMake)
|
||||
|
||||
```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
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
cmake --build . --target qemu
|
||||
```
|
||||
|
||||
### CMake + Ninja (Fast Modern Build)
|
||||
### Using Ninja (Faster Builds)
|
||||
|
||||
```bash
|
||||
mkdir build && cd build
|
||||
@@ -103,19 +103,15 @@ The easiest way to build MetalOS with all dependencies:
|
||||
```bash
|
||||
./scripts/docker-build.sh # Build Docker image
|
||||
./scripts/docker-run.sh scripts/setup-deps.sh # Setup dependencies
|
||||
./scripts/docker-run.sh make all # Build everything
|
||||
./scripts/docker-run.sh make qemu # Test in QEMU
|
||||
./scripts/docker-run.sh cmake --build build # Build everything
|
||||
```
|
||||
|
||||
**See [docs/BUILD_SYSTEMS.md](docs/BUILD_SYSTEMS.md) for detailed comparison and usage of all build systems.**
|
||||
|
||||
**QEMU UEFI Testing**:
|
||||
```bash
|
||||
make qemu # Boot in QEMU with UEFI (headless)
|
||||
make qemu QEMU_DISPLAY=gtk # Boot with graphical display
|
||||
make qemu-debug # Boot with debug output
|
||||
make qemu-gdb # Boot with GDB debugging
|
||||
make qemu-uefi-test # Test UEFI firmware setup
|
||||
cmake --build . --target qemu # Boot in QEMU with UEFI (headless)
|
||||
cmake --build . --target qemu-debug # Boot with debug output
|
||||
cmake --build . --target qemu-gdb # Boot with GDB debugging
|
||||
cmake --build . --target qemu-uefi-test # Test UEFI firmware setup
|
||||
```
|
||||
|
||||
See [docs/BUILD.md](docs/BUILD.md) for detailed build instructions and [docs/TESTING.md](docs/TESTING.md) for testing guide.
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
# MetalOS Bootloader Makefile
|
||||
# Builds UEFI bootloader (bootx64.efi)
|
||||
|
||||
# Cross-compiler setup
|
||||
CC = gcc
|
||||
LD = ld
|
||||
OBJCOPY = objcopy
|
||||
|
||||
# Directories
|
||||
SRC_DIR = src
|
||||
INC_DIR = include
|
||||
BUILD_DIR = build
|
||||
|
||||
# Compiler flags for UEFI
|
||||
CFLAGS = -Wall -Wextra -Werror \
|
||||
-ffreestanding -fno-stack-protector -fno-stack-check \
|
||||
-fshort-wchar -mno-red-zone \
|
||||
-I$(INC_DIR) \
|
||||
-DEFI_FUNCTION_WRAPPER
|
||||
|
||||
# Linker flags for UEFI
|
||||
LDFLAGS = -shared -Bsymbolic -nostdlib \
|
||||
-znocombreloc -T uefi.lds
|
||||
|
||||
# Source files
|
||||
SOURCES = $(wildcard $(SRC_DIR)/*.c)
|
||||
OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SOURCES))
|
||||
|
||||
# Output
|
||||
TARGET = bootx64.efi
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BUILD_DIR) $(TARGET)
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
# Compile C files
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# Link and create EFI binary
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(LD) $(LDFLAGS) $(OBJECTS) -o $(BUILD_DIR)/bootx64.so
|
||||
$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \
|
||||
-j .dynsym -j .rel -j .rela -j .reloc \
|
||||
--target=efi-app-x86_64 \
|
||||
$(BUILD_DIR)/bootx64.so $@
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) $(TARGET)
|
||||
|
||||
# Note: This is a simplified Makefile
|
||||
# A real implementation would use gnu-efi or proper UEFI SDK
|
||||
@@ -21,10 +21,12 @@ The easiest way to build MetalOS is using Docker, which provides a pre-configure
|
||||
./scripts/docker-run.sh scripts/setup-deps.sh
|
||||
|
||||
# 3. Build MetalOS
|
||||
./scripts/docker-run.sh make all
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
|
||||
# 4. Test in QEMU (headless mode)
|
||||
./scripts/docker-run.sh make qemu
|
||||
cmake --build . --target qemu
|
||||
|
||||
# 5. Optional: Interactive shell in container
|
||||
./scripts/docker-run.sh /bin/bash
|
||||
@@ -33,7 +35,7 @@ The easiest way to build MetalOS is using Docker, which provides a pre-configure
|
||||
### What's Included in Docker
|
||||
|
||||
The Docker image includes:
|
||||
- **Build tools**: GCC, NASM, Make, CMake, Meson
|
||||
- **Build tools**: GCC, NASM, CMake, Meson
|
||||
- **QEMU**: For testing with UEFI firmware
|
||||
- **OVMF**: UEFI firmware for QEMU
|
||||
- **Dependency management**: Scripts to download AMD firmware, Mesa RADV, QT6
|
||||
@@ -127,11 +129,15 @@ This produces `kernel/metalos.bin` - the kernel binary.
|
||||
## Creating Bootable Image
|
||||
|
||||
```bash
|
||||
# From repository root
|
||||
make image
|
||||
# From repository root, if you haven't already
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
|
||||
# Create the bootable image
|
||||
cmake --build . --target image
|
||||
```
|
||||
|
||||
This creates `build/metalos.img` - a bootable disk image containing:
|
||||
This creates the bootable disk image at `<build-directory>/build/metalos.img` (e.g., `build/build/metalos.img` if your build directory is named `build/`). The image contains:
|
||||
- EFI System Partition with bootloader
|
||||
- Kernel binary
|
||||
- Any required data files
|
||||
@@ -146,41 +152,33 @@ Ensure QEMU and OVMF are installed:
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt-get install qemu-system-x86 ovmf mtools
|
||||
sudo apt-get install qemu-system-x86 ovmf mtools cmake
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -S qemu-full edk2-ovmf mtools
|
||||
sudo pacman -S qemu-full edk2-ovmf mtools cmake
|
||||
|
||||
# Fedora
|
||||
sudo dnf install qemu-system-x86 edk2-ovmf mtools
|
||||
sudo dnf install qemu-system-x86 edk2-ovmf mtools cmake
|
||||
```
|
||||
|
||||
### Boot MetalOS in QEMU
|
||||
|
||||
```bash
|
||||
make qemu
|
||||
cd build
|
||||
cmake --build . --target qemu
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Build bootloader and kernel (or use placeholders if build fails)
|
||||
1. Build bootloader and kernel
|
||||
2. Create a bootable FAT32 disk image with UEFI boot structure
|
||||
3. Launch QEMU with OVMF UEFI firmware in headless mode
|
||||
4. Boot the system (will drop to UEFI shell until bootloader is complete)
|
||||
|
||||
**Display Options**: By default, QEMU runs in headless mode (no graphics). To use graphical display:
|
||||
|
||||
```bash
|
||||
# Use GTK display (if available)
|
||||
make qemu QEMU_DISPLAY=gtk
|
||||
|
||||
# Use SDL display (if available)
|
||||
make qemu QEMU_DISPLAY=sdl
|
||||
```
|
||||
4. Boot the system
|
||||
|
||||
### Boot with Debug Output
|
||||
|
||||
```bash
|
||||
make qemu-debug
|
||||
cd build
|
||||
cmake --build . --target qemu-debug
|
||||
```
|
||||
|
||||
This includes CPU interrupt and reset debugging output.
|
||||
@@ -191,7 +189,8 @@ For debugging with GDB:
|
||||
|
||||
```bash
|
||||
# Terminal 1 - Start QEMU with GDB server
|
||||
make qemu-gdb
|
||||
cd build
|
||||
cmake --build . --target qemu-gdb
|
||||
|
||||
# Terminal 2 - Connect GDB
|
||||
gdb kernel/metalos.bin
|
||||
@@ -206,7 +205,8 @@ QEMU will wait for GDB connection before starting execution.
|
||||
To verify QEMU and OVMF are properly installed without needing a bootable OS image:
|
||||
|
||||
```bash
|
||||
make qemu-uefi-test
|
||||
cd build
|
||||
cmake --build . --target qemu-uefi-test
|
||||
```
|
||||
|
||||
This boots directly to the UEFI shell, confirming your QEMU+OVMF setup works correctly.
|
||||
@@ -292,10 +292,14 @@ ENABLE_SERIAL ?= 1
|
||||
|
||||
```bash
|
||||
# Clean all build artifacts
|
||||
make clean
|
||||
cd build
|
||||
cmake --build . --target clean
|
||||
|
||||
# Clean everything including dependencies
|
||||
make distclean
|
||||
# Or remove the build directory entirely
|
||||
cd ..
|
||||
rm -rf build
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
# MetalOS Build Systems Guide
|
||||
|
||||
MetalOS supports multiple build systems to accommodate different developer preferences and workflows.
|
||||
MetalOS uses **CMake** as its primary build system, which can be used with different build backends for different workflows.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Make (Traditional)
|
||||
```bash
|
||||
make all # Build everything
|
||||
make qemu # Test in QEMU
|
||||
make clean # Clean build artifacts
|
||||
```
|
||||
|
||||
### Using CMake + Make
|
||||
### Using CMake (Default)
|
||||
```bash
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
cmake --build . --target qemu # Test in QEMU
|
||||
```
|
||||
|
||||
### Using CMake + Ninja (Fastest)
|
||||
@@ -23,6 +17,7 @@ cmake --build .
|
||||
mkdir build && cd build
|
||||
cmake -G Ninja ..
|
||||
ninja
|
||||
ninja qemu # Test in QEMU
|
||||
```
|
||||
|
||||
### Using Conan + CMake
|
||||
@@ -35,89 +30,38 @@ 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 |
|
||||
| Build Backend | Speed | Features | Best For |
|
||||
|---------------|-------|----------|----------|
|
||||
| **Make** (default) | Medium | Cross-platform, standard | General use, CI/CD |
|
||||
| **Ninja** | Fast | Parallel builds | Development, large projects |
|
||||
| **Conan** | Medium | Dependency management | Projects with external deps |
|
||||
|
||||
## Detailed Usage
|
||||
|
||||
### 1. Make (Traditional Build System)
|
||||
### 1. CMake (Primary Build System)
|
||||
|
||||
The original build system using GNU Make.
|
||||
CMake is the primary build system for MetalOS, providing cross-platform support and modern features.
|
||||
|
||||
#### 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)
|
||||
# Configure and build
|
||||
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
|
||||
# Create bootable image
|
||||
cmake --build . --target image
|
||||
|
||||
# Run in QEMU
|
||||
cmake --build . --target qemu # Headless mode
|
||||
cmake --build . --target qemu-debug # With debug output
|
||||
cmake --build . --target qemu-gdb # With GDB server
|
||||
cmake --build . --target qemu-uefi-test # Test UEFI setup
|
||||
|
||||
# Test
|
||||
ctest
|
||||
@@ -133,6 +77,23 @@ cmake --build . --target clean
|
||||
rm -rf build # Complete clean
|
||||
```
|
||||
|
||||
#### Advantages
|
||||
- ✅ Cross-platform (Windows, Linux, macOS)
|
||||
- ✅ IDE integration (CLion, VSCode, Visual Studio)
|
||||
- ✅ Modern dependency management
|
||||
- ✅ Better parallel build support
|
||||
- ✅ Generates compile_commands.json for IDEs
|
||||
|
||||
#### Disadvantages
|
||||
- ❌ Requires cmake installation
|
||||
- ❌ Slightly more complex setup
|
||||
|
||||
---
|
||||
|
||||
### 2. Ninja (Fast Build Backend)
|
||||
|
||||
Ninja is a fast build backend that can be used with CMake for faster incremental builds.
|
||||
|
||||
#### Advantages
|
||||
- ✅ Cross-platform (Windows, Linux, macOS)
|
||||
- ✅ IDE integration (CLion, Visual Studio, VS Code)
|
||||
|
||||
@@ -63,9 +63,11 @@ add_executable(kernel_elf $<TARGET_OBJECTS:kernel_obj> ${KERNEL_ASM_OBJECTS})
|
||||
set_target_properties(kernel_elf PROPERTIES
|
||||
OUTPUT_NAME metalos.elf
|
||||
LINKER_LANGUAGE C
|
||||
POSITION_INDEPENDENT_CODE OFF
|
||||
)
|
||||
target_link_options(kernel_elf PRIVATE
|
||||
-nostdlib
|
||||
-no-pie
|
||||
-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld
|
||||
)
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
# MetalOS Kernel Makefile
|
||||
|
||||
# Cross-compiler (x86_64 bare metal)
|
||||
CC = x86_64-elf-gcc
|
||||
AS = nasm
|
||||
LD = x86_64-elf-ld
|
||||
OBJCOPY = x86_64-elf-objcopy
|
||||
|
||||
# Check if cross-compiler exists, fallback to regular gcc
|
||||
ifeq ($(shell which $(CC) 2>/dev/null),)
|
||||
CC = gcc
|
||||
LD = ld
|
||||
OBJCOPY = objcopy
|
||||
endif
|
||||
|
||||
# Directories
|
||||
SRC_DIR = src
|
||||
INC_DIR = include
|
||||
BUILD_DIR = build
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS = -Wall -Wextra -Werror \
|
||||
-ffreestanding -fno-stack-protector \
|
||||
-mno-red-zone -mcmodel=large \
|
||||
-I$(INC_DIR) \
|
||||
-O2
|
||||
|
||||
# Assembler flags
|
||||
ASFLAGS = -f elf64
|
||||
|
||||
# Linker flags
|
||||
LDFLAGS = -nostdlib -T linker.ld
|
||||
|
||||
# Source files
|
||||
C_SOURCES = $(shell find $(SRC_DIR) -name '*.c')
|
||||
ASM_SOURCES = $(shell find $(SRC_DIR) -name '*.asm')
|
||||
|
||||
# Object files
|
||||
C_OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(C_SOURCES))
|
||||
ASM_OBJECTS = $(patsubst $(SRC_DIR)/%.asm,$(BUILD_DIR)/%.o,$(ASM_SOURCES))
|
||||
OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS)
|
||||
|
||||
# Output
|
||||
TARGET = metalos.bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BUILD_DIR) $(TARGET)
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
mkdir -p $(BUILD_DIR)/core
|
||||
mkdir -p $(BUILD_DIR)/hal
|
||||
mkdir -p $(BUILD_DIR)/drivers
|
||||
mkdir -p $(BUILD_DIR)/syscall
|
||||
|
||||
# Compile C files
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# Assemble ASM files
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.asm
|
||||
@mkdir -p $(dir $@)
|
||||
$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
# Link kernel
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(LD) $(LDFLAGS) $(OBJECTS) -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) $(TARGET)
|
||||
|
||||
# Print variables for debugging
|
||||
info:
|
||||
@echo "C Sources: $(C_SOURCES)"
|
||||
@echo "ASM Sources: $(ASM_SOURCES)"
|
||||
@echo "Objects: $(OBJECTS)"
|
||||
@echo "Compiler: $(CC)"
|
||||
@@ -1,64 +0,0 @@
|
||||
# MetalOS Test Suite Makefile
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra -std=c11 -I../tests/include -I../kernel/include -I../bootloader/include
|
||||
LDFLAGS =
|
||||
|
||||
# Test source files
|
||||
TEST_SOURCES = $(wildcard unit/*.c)
|
||||
TEST_BINARIES = $(TEST_SOURCES:.c=)
|
||||
|
||||
# Default target
|
||||
.PHONY: all
|
||||
all: $(TEST_BINARIES)
|
||||
|
||||
# Build each test binary
|
||||
unit/%: unit/%.c include/test_framework.h
|
||||
@echo "Building test: $@"
|
||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
|
||||
# Run all tests
|
||||
.PHONY: test
|
||||
test: all
|
||||
@echo ""
|
||||
@echo "╔════════════════════════════════════════════╗"
|
||||
@echo "║ Running MetalOS Test Suite ║"
|
||||
@echo "╚════════════════════════════════════════════╝"
|
||||
@echo ""
|
||||
@for test in $(TEST_BINARIES); do \
|
||||
./$$test || exit 1; \
|
||||
done
|
||||
@echo ""
|
||||
@echo "╔════════════════════════════════════════════╗"
|
||||
@echo "║ All Test Suites Passed ✓ ║"
|
||||
@echo "╚════════════════════════════════════════════╝"
|
||||
@echo ""
|
||||
|
||||
# Run tests with verbose output
|
||||
.PHONY: test-verbose
|
||||
test-verbose: all
|
||||
@for test in $(TEST_BINARIES); do \
|
||||
echo "Running $$test..."; \
|
||||
./$$test -v; \
|
||||
echo ""; \
|
||||
done
|
||||
|
||||
# Clean test binaries
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@echo "Cleaning test binaries..."
|
||||
@rm -f $(TEST_BINARIES)
|
||||
@rm -f unit/*.o
|
||||
@echo "Clean complete"
|
||||
|
||||
# Help target
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "MetalOS Test Suite Makefile"
|
||||
@echo ""
|
||||
@echo "Targets:"
|
||||
@echo " all - Build all test binaries"
|
||||
@echo " test - Build and run all tests"
|
||||
@echo " test-verbose - Run tests with verbose output"
|
||||
@echo " clean - Remove test binaries"
|
||||
@echo " help - Show this help message"
|
||||
Reference in New Issue
Block a user