Esta pagina se ve mejor con JavaScript habilitado

MercuryOS Wildcards gmake

 ·  ūüéÉ kr0m

Conforme vaya creciendo nuestro SO cada vez resultar√° mas inmanegable tener todos los ficheros en un √ļnico directorio, debemos definir una estructura, una froma sencilla de organizar el c√≥digo ser√≠a esta, boot -> Cualquier c√≥digo relacionado con el bootloader o subrutinas utilizadas por este, kernel -> Cualquier c√≥digo relacionado con el kernel, drivers -> C√≥digo de drivers espec√≠ficos.

Antes de comenzar es recomendable que leas estos artículos anteriores:


Creamos la estructura de directorios:

mkdir -p Project/boot/
mkdir -p Project/kernel/
mkdir -p Project/drivers/

Copiamos o movemos los ficheros necesarios:

cp kernel_entry.asm boot_sect.asm boot_sect_print.asm boot_sect_print_hex.asm boot_sect_disk.asm 32bit-gdt.asm 32bit-print.asm 32bit-switch.asm Project/boot
cp kernel.c kernel_entry.asm Project/kernel

Make permite la utilización de wildcards, de este modo los scripts de compilación serán mas cortos y fáciles de mantener.

Podemos expandir los nombres de los ficheros que macheen un patrón:

C_SOURCES = $(wildcard kernel /*.c drivers /*.c)

Podemos crear una lista a partir de ciertos ficheros origen:

OBJ = $ {C_SOURCES : .c = .o}

Para utilizar la lista basta con hacer referencia a ella ${OBJ}:

kernel .bin : kernel/kernel_entry.o ${OBJ}
    ld -o $@ -Ttext 0x1000 $^ --oformat binary

Ahora que hemos movido los ficheros hay que modificar los includes de boot_sect.asm

vi boot/boot_sect.asm

%include "boot/boot_sect_print.asm"
%include "boot/boot_sect_print_hex.asm"
%include "boot/boot_sect_disk.asm"
%include "boot/32bit-gdt.asm"
%include "boot/32bit-print.asm"
%include "boot/32bit-switch.asm"

El Makefile final quedaría del siguiente modo:

vi Makefile

# Automatically generate lists of sources using wildcards.
C_SOURCES = $(wildcard kernel/*.c drivers/*.c)
HEADERS = $(wildcard kernel/*.h drivers/*.h)

# TODO : Make sources dep on all header files .
# Convert the *.c filenames to *.o to give a list of object files to build
OBJ = ${C_SOURCES:.c=.o}

# Run Qemu to simulate booting of our code.
run : all
	qemu-system-x86_64 os-image

# Run Qemu to simulate booting of our code with debugging session.
# gdb -ex "set architecture i386:x86-64" -ex "set disassembly-flavor intel" -ex "target remote localhost:1234" -ex "symbol-file kernel/kernel.elf"
debug : all kernel/kernel.elf
	qemu-system-x86_64 os-image -s -S &

# Used for debugging purposes
kernel/kernel.elf: boot/kernel_entry.o ${OBJ}
	ld -o $@ -Ttext 0x1000 $^

# Defaul build target
all: os-image

# This is the actual disk image that the computer loads
# which is the combination of our compiled bootsector and kernel
os-image : boot/boot_sect.bin kernel/kernel.bin
	cat $^ > os-image

# This builds the binary of our kernel from two object files :
# - the kernel_entry, which jumps to main () in our kernel
# - the compiled C kernel
kernel/kernel.bin : kernel/kernel_entry.o ${OBJ}
	ld -o $@ -Ttext 0x1000 $^ --oformat binary

# Generic rule for compiling C code to an object file
# For simplicity , we C files depend on all header files.
%.o : %.c ${HEADERS}
	cc -g -m32 -ffreestanding -c $< -o $@

# Assemble the kernel_entry.
%.o : %.asm
	nasm -f elf $< -o $@

%.bin : %.asm
	nasm -f bin $< -o $@

clean :
	rm -fr *.bin *.dis *.o *.core os-image
	rm -fr kernel/*.o boot/*.bin drivers/*.o

NOTA: Una vez mas remarcar la importancia de utilizar tabulaciones reales y no espacios en los ficheros Makefile.

Comprobamos que todo el proceso funcione:

gmake clean
gmake run

Si te ha gustado el artículo puedes invitarme a un RedBull aquí