178 lines
5.8 KiB
Python
Executable File
178 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from glob import glob
|
|
import os
|
|
|
|
file = open('Makefile', 'w', encoding='utf-8')
|
|
def raw(s):
|
|
print(s, file=file)
|
|
|
|
def srcobj(path):
|
|
srcs = None
|
|
if os.path.isfile(path):
|
|
srcs = [path]
|
|
else:
|
|
srcs = glob(path + '/**/*.[csS]', recursive=True)
|
|
objs = ['out/obj/' + src.removeprefix('src/') + '.o' for src in srcs]
|
|
return ' ' + ' '.join(objs) + ' '
|
|
|
|
def t(out, deps='', cmds=[], phony=False, verbose=False):
|
|
if phony:
|
|
raw(f".PHONY: {out}")
|
|
else:
|
|
cmds = ["mkdir -p $(@D)"] + cmds
|
|
raw(f"{out}: {deps}")
|
|
v = '' if verbose else '$(V)'
|
|
for cmd in cmds:
|
|
raw(f"\t{v}{cmd}")
|
|
|
|
|
|
raw("""
|
|
# automatically generated by ./configure
|
|
|
|
PATH := $(shell pwd)/toolchain/prefix/bin/:$(PATH)
|
|
|
|
AR = x86_64-camellia-ar
|
|
AS = x86_64-camellia-as
|
|
CC = x86_64-camellia-gcc
|
|
|
|
V=@
|
|
|
|
CFLAGS = -g -std=gnu99 -Os -fPIC -ftrack-macro-expansion=0 \
|
|
-Wall -Wextra -Wold-style-definition -Wno-address-of-packed-member \
|
|
-Werror=incompatible-pointer-types -Werror=implicit-function-declaration
|
|
|
|
CFLAGS_KERNEL = $(CFLAGS) \
|
|
-ffreestanding -mno-sse -mgeneral-regs-only \
|
|
--sysroot=out/sysrootk/ -Isrc/
|
|
CFLAGS_LIBC = $(CFLAGS) -ffreestanding -Isrc/
|
|
|
|
SPARSEFLAGS = $(CFLAGS_KERNEL) -Wno-non-pointer-null -Iout/sysrootk/usr/include/ -D__SPARSE
|
|
|
|
LIB = out/sysrootu/lib/libc.a out/sysrootu/lib/libm.a out/sysrootu/lib/crt0.o
|
|
""")
|
|
|
|
t('all', 'out/boot.iso out/fs.e2 check', phony=True)
|
|
t('portdeps', 'out/sysrootu/usr/include/ $(LIB)', phony=True)
|
|
|
|
# TODO check userland sources too
|
|
t('check', '', [
|
|
'find src/kernel/ -type f -name *.c | xargs -n 1 sparse $(SPARSEFLAGS)'
|
|
], phony=True)
|
|
|
|
t('clean', '', [
|
|
'rm -rf out/'
|
|
], phony=True, verbose=True)
|
|
|
|
raw("""
|
|
PORTS=
|
|
.PHONY: ports
|
|
# portdeps is phony, so ports/% is automatically "phony" too
|
|
ports: $(patsubst %,ports/%,$(PORTS))
|
|
ports/%: portdeps
|
|
+$@/port install
|
|
""")
|
|
|
|
t('out/boot.iso', 'out/fs/boot/kernel out/fs/boot/grub/grub.cfg out/fs/boot/init.gz', [
|
|
'grub-mkrescue -o $@ out/fs/ >/dev/null 2>&1'
|
|
])
|
|
|
|
t('out/fs/boot/kernel', 'src/kernel/arch/amd64/linker.ld' + srcobj('src/kernel/') + srcobj('src/libk/'), [
|
|
'$(CC) -nostdlib -Wl,-zmax-page-size=4096 -Wl,--no-warn-mismatch -Wl,-no-pie -T $^ -o $@ -lgcc',
|
|
'grub-file --is-x86-multiboot2 $@ || echo "$@ has an invalid multiboot2 header"',
|
|
'grub-file --is-x86-multiboot2 $@ || rm $@; test -e $@'
|
|
])
|
|
|
|
t('out/sysrootu/lib/libc.a', srcobj('src/libc/') + srcobj('src/libk/'), [
|
|
'$(AR) rcs $@ $^'
|
|
])
|
|
t('out/sysrootu/lib/libm.a', '', [
|
|
'$(AR) rcs $@ $^'
|
|
])
|
|
|
|
t('out/bootstrap', 'out/bootstrap.elf', ['objcopy -O binary $^ $@'])
|
|
t('out/bootstrap.elf', 'src/bootstrap/linker.ld' + srcobj('src/bootstrap/') + 'out/sysrootu/lib/libc.a', [
|
|
'$(CC) -nostdlib -Wl,-no-pie -T $^ -o $@'
|
|
])
|
|
|
|
t('out/fs/boot/init.gz', 'out/bootstrap out/initrd.tar', ['cat $^ | gzip > $@'])
|
|
|
|
t('out/fs/boot/grub/grub.cfg', 'src/kernel/arch/amd64/grub.cfg', ['cp $< $@'])
|
|
|
|
t('out/fs.e2', '', ['mkfs.ext2 $@ 1024 >/dev/null'])
|
|
|
|
userbins = []
|
|
for src in glob('*', root_dir='src/cmd/'):
|
|
cmd = src.removesuffix('.c')
|
|
t(f'out/initrd/bin/amd64/{cmd}', '$(LIB) ' + srcobj(f'src/cmd/{src}'), [
|
|
'$(CC) $^ -o $@'
|
|
])
|
|
userbins.append(cmd)
|
|
|
|
raw("USERBINS = " + " ".join(userbins))
|
|
|
|
# don't build the example implementation from libext2
|
|
t('out/obj/cmd/ext2fs/ext2/example.c.o', '', ['touch $@'])
|
|
|
|
t('out/initrd/%', 'sysroot/%', ['cp $< $@'])
|
|
|
|
t('out/initrd.tar',
|
|
'$(patsubst sysroot/%,out/initrd/%,$(shell find sysroot/ -type f)) '
|
|
'$(patsubst %,out/initrd/bin/amd64/%,$(USERBINS)) '
|
|
'$(shell find out/initrd/) '
|
|
'ports ',
|
|
['cd out/initrd; tar chf ../initrd.tar *'])
|
|
|
|
t('src/libc/include/__errno.h',
|
|
'src/libc/include/__errno.h.awk src/libk/include/camellia/errno.h',
|
|
['awk -f $^ > $@'])
|
|
|
|
t('src/libc/syscall.c',
|
|
'src/libc/syscall.c.awk src/libk/include/camellia/syscalls.h',
|
|
['awk -f $^ > $@'])
|
|
|
|
def includes(target, modules, deps='', cmds=[]):
|
|
dirs = " ".join([f"src/{mod}/include/" for mod in modules])
|
|
t(target, deps, [
|
|
"set -eu;"
|
|
f"for file in $$(find {dirs} -type f,l -name '*.h'); do "
|
|
" out=$@$${file#src/*/include/};"
|
|
" mkdir -p $$(dirname $$out);"
|
|
" ln -rfs $$file $$out;"
|
|
"done"
|
|
] + cmds, phony=True)
|
|
|
|
includes("out/sysrootk/usr/include/", ["libk"])
|
|
# this must work without a toolchain available, as it's required to build
|
|
# the toolchain
|
|
includes("out/sysrootu/usr/include/", ["libc", "libk"], 'src/libc/include/__errno.h', [
|
|
'ln -rfs src/libc/include/__errno.h $@',
|
|
])
|
|
t('out/sysrootu/lib/crt0.o', 'out/obj/libc/_start.s.o', ['cp $^ $@'])
|
|
|
|
def cc(rule, args, deps):
|
|
# The | marks an order-only dependency. This means that sysroot will be
|
|
# built every time the rule is ran, but without forcing a rebuild if the
|
|
# rule is fresh.
|
|
# https://www.gnu.org/software/make/manual/make.html#index-order_002donly-prerequisites
|
|
t(f'out/obj/{rule}.o', f'src/{rule} | {deps}', [
|
|
f'$(CC) {args} -c $< -o $@'
|
|
])
|
|
|
|
cc("%.c", "$(CFLAGS)", "out/sysrootu/usr/include/")
|
|
cc("%.s", "$(CFLAGS)", "out/sysrootu/usr/include/")
|
|
cc("%.S", "$(CFLAGS)", "out/sysrootu/usr/include/")
|
|
cc("bootstrap/%.c", "$(CFLAGS) -fno-pie", "out/sysrootu/usr/include/")
|
|
cc("libc/%.c", "$(CFLAGS_LIBC)", "out/sysrootu/usr/include/")
|
|
|
|
cc("libc/vendor/dlmalloc/%.c", "$(CFLAGS_LIBC) -DMAP_ANONYMOUS -DHAVE_MORECORE=0 -DNO_MALLOC_H -Wno-expansion-to-defined -Wno-old-style-definition", "out/sysrootu/usr/include/")
|
|
|
|
cc("kernel/%.c", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/")
|
|
cc("kernel/%.s", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/")
|
|
cc("kernel/%.S", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/")
|
|
cc("libk/%.c", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/")
|
|
cc("libk/%.s", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/")
|
|
cc("libk/%.S", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/")
|
|
|
|
cc("kernel/arch/amd64/32/%.c", "$(CFLAGS_KERNEL) -fno-pic -m32", "out/sysrootk/usr/include/")
|
|
cc("kernel/arch/amd64/32/%.s", "$(CFLAGS_KERNEL) -fno-pic -m32", "out/sysrootk/usr/include/")
|