From fdfdd03e3341d3b7d5e6a22a11a755a2c56eda1b Mon Sep 17 00:00:00 2001 From: Kimplul Date: Mon, 24 Jul 2023 19:23:50 +0300 Subject: split makefile into two parts + First part generates deps.mk, second part reads it. Allows us to use both bmake and gmake with the same makefiles. Only drawback seems to be that the first makefile considers all individual files as 'finished' targets, meaning that it's more difficult to do something like make kernel.elf though I haven't found this to be an issue. --- Makefile | 148 +++++++++++-------------------------------------------- scripts/gen-deps | 81 +++++++++++------------------- scripts/makefile | 126 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 171 deletions(-) create mode 100644 scripts/makefile diff --git a/Makefile b/Makefile index 200cc41..13fd1b5 100644 --- a/Makefile +++ b/Makefile @@ -1,138 +1,49 @@ -DO != echo -n > deps.mk +.PHONY: all +all: setup + $(MAKE) -f scripts/makefile + +# this kicks all unrecognised targets to the client script. +# note that trying to compile individual files, e.g. +# +# make kernel.elf +# +# will not work, you would need +# +# make -f scripts/makefile kernel.elf +# +# instead +.DEFAULT: setup + $(MAKE) -f scripts/makefile $< -# this could be done better -RELEASE ?= 0 -OPTFLAGS != [ "$(RELEASE)" != "0" ] \ - && echo "-O3 -flto" \ - || echo "-O0" - -DEBUG ?= 1 -DEBUGFLAGS != [ "$(DEBUG)" != "0" ] \ - && echo "-DDEBUG=1" \ - || echo "-DNDEBUG=1" - -GENERIC_UBOOT ?= 0 -UBOOTFLAGS != [ "$(GENERIC_UBOOT)" != "0" ] \ - && echo "-DGENERIC_UBOOT=1" - -ASSERT ?= 1 -ASSERTFLAGS != [ "$(ASSERT)" != "0" ] \ - && echo "-DASSERT=1" - -DEPFLAGS = -MT $@ -MMD -MP -MF $@.d -LINTFLAGS = -fsyntax-only -PREPROCESS = -E - -LLVM ?= 0 -LDFLAGS != [ "$(LLVM)" = "0" ] \ - && echo -static-libgcc -lgcc - -BUILD = build -ARCH_KERN_BUILD = $(BUILD)/kernel/arch/$(ARCH) -ARCH_INIT_BUILD = $(BUILD)/init/arch/$(ARCH) -ARCH_SOURCE = arch/$(ARCH) - -all: kmi.bin -# bmake requires us to run make depend to genereate deps.mk beforehand, -# so create an empty rule that lets the rest of the script do its job -depend: +.PHONY: +setup: + @echo -n > deps.mk + @./scripts/gen-deps -p KERNEL -c COMPILE_KERNEL -b kernel "${KERNEL_SOURCES}" + @./scripts/gen-deps -p INIT -c COMPILE_INIT -b init "${INIT_SOURCES}" # default values, overwrite if/when needed ARCH ?= riscv64 -CROSS_COMPILE ?= $(ARCH)-unknown-elf- - -OBJCOPY != [ "$(LLVM)" != "0" ] \ - && echo llvm-objcopy \ - || echo $(CROSS_COMPILE)objcopy - -COMPILER != [ "$(LLVM)" != "0" ] \ - && echo clang --target="$(CROSS_COMPILE)" \ - || echo $(CROSS_COMPILE)gcc - +ARCH_SOURCE = arch/$(ARCH) -KERNEL_SOURCES != echo common/*.c common/uapi/*.c lib/*.c # might consider renaming common, currently it refers to stuff common # to all arches but clearly there are bits that are common to init and kernel +KERNEL_SOURCES != echo common/*.c common/uapi/*.c lib/*.c INIT_SOURCES != echo lib/fdt*.c common/fdt.c common/string.c + CLEANUP := build deps.mk kernel.* init.* kmi.bin CLEANUP_CMD := -OBFLAGS := -ffreestanding -nostdlib -static -fno-pie -std=c17 -g -WARNFLAGS := -Wall -Wextra -Wvla -ARCH_CFLAGS := -D$(ARCH) - include arch/$(ARCH)/source.mk -COMPILE_FLAGS := $(CFLAGS) $(WARNFLAGS) $(OPTFLAGS) $(OBFLAGS) $(ASSERTFLAGS) \ - $(DEBUGFLAGS) $(UBOOTFLAGS) $(ARCH_CFLAGS) - -LINK_FLAGS := $(LDFLAGS) $(ARCH_LDFLAGS) - -INCLUDE_FLAGS := -I include -include config.h -include arch/$(ARCH)/config.h - -# This makes sure .bss is loaded into the binary -OBJCOPY_FLAGS ?= -Obinary -R .garbage \ - --set-section-flags .bss=alloc,load,contents - -COMPILE = $(COMPILER) \ - $(COMPILE_FLAGS) $(DEPFLAGS) $(INCLUDE_FLAGS) - -LINT = $(COMPILER) \ - $(COMPILE_FLAGS) $(LINTFLAGS) $(INCLUDE_FLAGS) - -GENELF = $(COMPILER) \ - $(COMPILE_FLAGS) $(INCLUDE_FLAGS) - -GENLINK = $(COMPILER) $(COMPILE_FLAGS) $(PREPROCESS) $(DEPFLAGS) $(INCLUDE_FLAGS) -STRIPLINK = sed -n '/^[^\#]/p' -KERN_SIZE = wc -c kernel.bin | awk '{print $$1}' -KERN_INFO = sed "s//$$($(KERN_SIZE))/" - -KERNEL_LINK := arch/$(ARCH)/conf/kernel-link -INIT_LINK := arch/$(ARCH)/conf/init-link - -UBSAN ?= 0 -KERN_FLAGS != [ "$(UBSAN)" != "0" ] \ - && echo -fsanitize=undefined - -INIT_FLAGS := -fpic - -KERNEL_OBJECTS != ./scripts/gen-deps --kernel --compile "$(KERNEL_SOURCES)" -INIT_OBJECTS != ./scripts/gen-deps --init --compile "$(INIT_SOURCES)" -KERNEL_LD != ./scripts/gen-deps --kernel --link "$(KERNEL_LINK).S" -INIT_LD != ./scripts/gen-deps --init --link "$(INIT_LINK).S" - --include deps.mk - -$(INIT_LD): kernel.bin - -init.elf: $(INIT_OBJECTS) $(INIT_LD) - $(GENELF) $(INIT_FLAGS) -T $(INIT_LD) $(INIT_OBJECTS) -o init.elf $(LINK_FLAGS) - -kernel.elf: $(KERNEL_OBJECTS) $(KERNEL_LD) - $(GENELF) $(KERNEL_FLAGS) -T $(KERNEL_LD) $(KERNEL_OBJECTS) -o kernel.elf $(LINK_FLAGS) - -init.bin: init.elf - $(OBJCOPY) $(OBJCOPY_FLAGS) init.elf init.bin - -kernel.bin: kernel.elf - $(OBJCOPY) $(OBJCOPY_FLAGS) kernel.elf kernel.bin - -kmi.bin: init.bin kernel.bin - cat init.bin kernel.bin > kmi.bin - -.PHONY: -lint: $(INIT_OBJECTS:.o=.o.l) $(KERNEL_OBJECTS:.o=.o.l) - .PHONY: format format: find arch lib common include -iname '*.[ch]' |\ - xargs -n 10 -P 0 uncrustify -c uncrustify.conf --no-backup -F - + xargs uncrustify -c uncrustify.conf --no-backup -F - .PHONY: license license: find arch lib common include -iname '*.[ch]' |\ - xargs -n 10 -P 0 ./scripts/license + xargs ./scripts/license .PHONY: docs docs: @@ -140,12 +51,11 @@ docs: xargs ./scripts/warn-undocumented doxygen docs/doxygen.conf -# bmake didn't seem to have the -f flag on by default -RM ?= rm -f +RM = rm .PHONY: clean clean: - $(RM) -r $(CLEANUP) + $(RM) -rf $(CLEANUP) .PHONY: clean_run clean_run: @@ -153,7 +63,7 @@ clean_run: .PHONY: clean_docs clean_docs: - $(RM) -r docs/output + $(RM) -rf docs/output .PHONY: clean_all clean_all: clean clean_run clean_docs diff --git a/scripts/gen-deps b/scripts/gen-deps index 9a9ad6e..f45707c 100755 --- a/scripts/gen-deps +++ b/scripts/gen-deps @@ -1,60 +1,37 @@ #!/bin/sh -gencommon () { - lint="build/${path}/${s%.*}${1}.l" - dep="build/${path}/${s%.*}${1}.d" - obj="build/${path}/${s%.*}${1}" - - echo "${dep}:" >> deps.mk - echo "-include ${dep}" >> deps.mk - echo "${obj}: ${s}" >> deps.mk -} - -genlink () { - gencommon ".ld" - if [ ${kern} ]; then - echo " \$(GENLINK) ${s} | \$(STRIPLINK) > ${obj}" >> deps.mk - else - echo " \$(GENLINK) ${s} | \$(STRIPLINK) | \$(KERN_INFO) > ${obj}" >> deps.mk; - fi -} - -genrule () { - gencommon "${1}" - echo " \$(COMPILE) ${flags} -c ${s} -o ${obj}" >> deps.mk - - echo "${lint}: ${s}" >> deps.mk - echo " \$(LINT) ${flags} -c ${s} -o /dev/null" >> deps.mk -} - -case "${1}" in - --kernel) - kern=1 - path=kernel - flags='$(KERN_FLAGS)' - ;; - --init) - path=init - flags='$(INIT_FLAGS)' - ;; -esac +PREFIX= +COMPILE=COMPILE +LINT=LINT +BUILD=build/ + +while getopts "p:c:b:l:" opt; do + case "$opt" in + p) PREFIX="$OPTARG"_;; + c) COMPILE="$OPTARG";; + l) LINT="$OPTARG";; + b) BUILD=build/"$OPTARG";; + *) echo "unrecognised option -$OPTARG" >&2; exit 1;; + esac +done -case "${2}" in - --compile) - suffix=.o - func=genrule - ;; - --link) - suffix=.ld - func=genlink -esac +shift $((OPTIND - 1)) # create all subdirectories -mkdir -p $(echo "${3}" | xargs -n 1 dirname | uniq | sed 's|^|build/init/|g') -mkdir -p $(echo "${3}" | xargs -n 1 dirname | uniq | sed 's|^|build/kernel/|g') +mkdir -p $(echo "${@}" | tr ' ' '\n' | sed "s|[^/]*$||;s|^|${BUILD}/|" | uniq) -for s in ${3} +for s in ${@} do - ${func} ${suffix} - echo ${obj} + obj="${BUILD}/${s%.*}.o" + lint="${obj}.l" + dep="${obj}.d" + + echo "${PREFIX}OBJS += ${obj}" >> deps.mk + echo "${PREFIX}LINTS += ${lint}" >> deps.mk + echo "${dep}:" >> deps.mk + echo "-include ${dep}" >> deps.mk + echo "${obj}: ${s}" >> deps.mk + echo " \$(${COMPILE}) -c ${s} -o ${obj}" >> deps.mk + echo "${lint}: ${s}" >> deps.mk + echo " \$(${LINT}) -c ${s} -o /dev/null" >> deps.mk done diff --git a/scripts/makefile b/scripts/makefile new file mode 100644 index 0000000..762c5c9 --- /dev/null +++ b/scripts/makefile @@ -0,0 +1,126 @@ +# this could be done better +RELEASE ?= 0 +OPTFLAGS != [ "$(RELEASE)" != "0" ] \ + && echo "-O3 -flto" \ + || echo "-O0" + +DEBUG ?= 1 +DEBUGFLAGS != [ "$(DEBUG)" != "0" ] \ + && echo "-DDEBUG=1" \ + || echo "-DNDEBUG=1" + +GENERIC_UBOOT ?= 0 +UBOOTFLAGS != [ "$(GENERIC_UBOOT)" != "0" ] \ + && echo "-DGENERIC_UBOOT=1" \ + || echo + +ASSERT ?= 1 +ASSERTFLAGS != [ "$(ASSERT)" != "0" ] \ + && echo "-DASSERT=1" \ + || echo + +DEPFLAGS = -MT $@ -MMD -MP -MF $@.d +LINTFLAGS = -fsyntax-only +PREPROCESS = -E + +LLVM ?= 0 +LDFLAGS != [ "$(LLVM)" = "0" ] \ + && echo -static-libgcc -lgcc \ + || echo + +BUILD = build +ARCH_KERN_BUILD = $(BUILD)/kernel/arch/$(ARCH) +ARCH_INIT_BUILD = $(BUILD)/init/arch/$(ARCH) +ARCH_SOURCE = arch/$(ARCH) + +all: kmi.bin + +# default values, overwrite if/when needed +ARCH ?= riscv64 +CROSS_COMPILE ?= $(ARCH)-unknown-elf- + +OBJCOPY != [ "$(LLVM)" != "0" ] \ + && echo llvm-objcopy \ + || echo $(CROSS_COMPILE)objcopy + +COMPILER != [ "$(LLVM)" != "0" ] \ + && echo clang --target="$(CROSS_COMPILE)" \ + || echo $(CROSS_COMPILE)gcc + + +OBFLAGS = -ffreestanding -nostdlib -static -fno-pie -std=c17 -g +WARNFLAGS = -Wall -Wextra -Wvla +ARCH_CFLAGS = -D$(ARCH) + +include arch/$(ARCH)/source.mk + +COMPILE_FLAGS = $(CFLAGS) $(WARNFLAGS) $(OPTFLAGS) $(OBFLAGS) $(ASSERTFLAGS) \ + $(DEBUGFLAGS) $(UBOOTFLAGS) $(ARCH_CFLAGS) + +LINK_FLAGS = $(LDFLAGS) $(ARCH_LDFLAGS) + +INCLUDE_FLAGS = -I include -include config.h -include arch/$(ARCH)/config.h + +# This makes sure .bss is loaded into the binary +OBJCOPY_FLAGS ?= -Obinary -R .garbage \ + --set-section-flags .bss=alloc,load,contents + +COMPILE = $(COMPILER) \ + $(COMPILE_FLAGS) $(DEPFLAGS) $(INCLUDE_FLAGS) + +LINT = $(COMPILER) \ + $(COMPILE_FLAGS) $(LINTFLAGS) $(INCLUDE_FLAGS) + +GENELF = $(COMPILER) \ + $(COMPILE_FLAGS) $(INCLUDE_FLAGS) + +GENLINK = $(COMPILER) $(COMPILE_FLAGS) $(PREPROCESS) $(DEPFLAGS) $(INCLUDE_FLAGS) +STRIPLINK = sed -n '/^[^\#]/p' +KERN_SIZE = wc -c kernel.bin | awk '{print $$1}' +KERN_INFO = sed "s//$$($(KERN_SIZE))/" + +KERNEL_LINK = arch/$(ARCH)/conf/kernel-link.S +INIT_LINK = arch/$(ARCH)/conf/init-link.S + +KERNEL_LD = build/kernel-link.ld +INIT_LD = build/init-link.ld + +UBSAN ?= 0 +KERN_FLAGS != [ "$(UBSAN)" != "0" ] \ + && echo -fsanitize=undefined \ + || echo + +INIT_FLAGS := -fpic + +COMPILE_KERNEL = $(COMPILE) $(KERN_FLAGS) +COMPILE_INIT = $(COMPILE) $(INIT_FLAGS) + +-include deps.mk + +-include $(KERNEL_LD).d +$(INIT_LD): kernel.bin +$(INIT_LD): $(INIT_LINK) + $(GENLINK) $(INIT_LINK) | $(STRIPLINK) | $(KERN_INFO) > $(INIT_LD) + +-include $(KERNEL_LD).d +$(KERNEL_LD): $(KERNEL_LINK) + $(GENLINK) $(KERNEL_LINK) | $(STRIPLINK) > $(KERNEL_LD) + +init.elf: $(INIT_OBJS) $(INIT_LD) + $(GENELF) $(INIT_FLAGS) -T $(INIT_LD) $(INIT_OBJS) -o init.elf $(LINK_FLAGS) + +kernel.elf: $(KERNEL_OBJS) $(KERNEL_LD) + $(GENELF) $(KERNEL_FLAGS) -T $(KERNEL_LD) $(KERNEL_OBJS) -o kernel.elf $(LINK_FLAGS) + +init.bin: init.elf + $(OBJCOPY) $(OBJCOPY_FLAGS) init.elf init.bin + +kernel.bin: kernel.elf + $(OBJCOPY) $(OBJCOPY_FLAGS) kernel.elf kernel.bin + +kmi.bin: init.bin kernel.bin + cat init.bin kernel.bin > kmi.bin + +# might lint some common things twice +.PHONY: +lint: $(INIT_LINTS) $(KERNEL_LINTS) -- cgit v1.3