endif
.PHONY: build qemu clean
+.SECONDEXPANSION:
build: # Build as default target
-CXXFLAGS ?= -O2
-CXXFLAGS := $(CXXFLAGS) -std=c++20 -fno-strict-aliasing -Wall -Wextra -Werror \
- -mgeneral-regs-only -fno-exceptions -fno-rtti -ffreestanding
-LDFLAGS ?= -O2
-LDFLAGS := $(LDFLAGS) -std=c++20 -Wall -Wextra -Werror -ffreestanding
+CXXFLAGS := -std=c++20 -fno-strict-aliasing -Wall -Wextra -Werror \
+ -mgeneral-regs-only -fno-exceptions -fno-rtti -ffreestanding -O2 $(CXXFLAGS)
+LDFLAGS := $(CXXFLAGS) $(LDFLAGS)
TO_ISO := isodir/boot/grub/grub.cfg
TO_CLEAN := isodir voyage.iso
+TO_INCLUDE :=
-include **/module.mk
+SRC_DIR = $(SUBDIR)src/
+OUT_DIR = $(SUBDIR)out/
+DEP_DIR = $(SUBDIR)dep/
+
+SRCS = $(shell find '$(SRC_DIR)' -name '*.cpp') $(shell find '$(SRC_DIR)' -name '*.S')
+PREP = $(patsubst $(SRC_DIR)%.S,$(OUT_DIR)%.s,$(SRCS:$(SRC_DIR)%.cpp=$(OUT_DIR)%.ii))
+DEPS = $(SRCS:$(SRC_DIR)%=$(DEP_DIR)%.d)
+OBJS = $(PREP:=.o)
+
+SUBDIR := kernel/
+include $(SUBDIR)module.mk
+SUBDIR := test_module/
+include $(SUBDIR)module.mk
build: voyage.iso
qemu: build
clean:
-rm -rf $(TO_CLEAN)
install:
- install -D voyage.iso -t "$(PREFIX)"
+ install -D voyage.iso -t '$(PREFIX)'
voyage.iso: $(TO_ISO)
- grub-mkrescue -o "$@" isodir
+ grub-mkrescue -o '$@' isodir
isodir/boot/grub/grub.cfg: grub.cfg
- mkdir -p "$(@D)"
- install -m 644 "$<" "$@"
+ mkdir -p '$(@D)'
+ install -m 644 '$<' '$@'
+
+PRECOND = $(patsubst $(OUT_DIR)%.s,$(SRC_DIR)%.S,$(patsubst $(OUT_DIR)%.ii,$(SRC_DIR)%.cpp,$(patsubst $(DEP_DIR)%.d,$(SRC_DIR)%,$@)))
+EXP = $(patsubst $(DEP_DIR)%.S.d,$(OUT_DIR)%.s,$(@:$(DEP_DIR)%.cpp.d=$(OUT_DIR)%.ii))
+DEP = $(patsubst $(OUT_DIR)%.s,$(DEP_DIR)%.S.d,$(@:$(OUT_DIR)%.ii=$(DEP_DIR)%.cpp.d))
+%.ii %.cpp.d &: $$(PRECOND)
+ mkdir -p '$(dir $(EXP))' '$(dir $(DEP))'
+ $(CXX) $(CXXFLAGS) -E '$<' -MMD -MT '$(EXP)' -MF '$(DEP)' -o '$(EXP)'
+%.s %.S.d &: $$(PRECOND)
+ mkdir -p '$(dir $(EXP))' '$(dir $(DEP))'
+ $(CXX) $(CXXFLAGS) -E '$<' -MMD -MT '$(EXP)' -MF '$(DEP)' -o '$(EXP)'
+
+%: %.o # Because it causes shitty useless loops with the next rule
+%.o: %
+ $(CXX) $(CXXFLAGS) -fpreprocessed -c '$<' -o '$@'
+
+ifneq ($(MAKECMDGOALS),clean)
+ include $(TO_INCLUDE)
+endif
# You should have received a copy of the CC0 Public Domain Dedication along with
# this file. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-SRC_DIR := kernel/src/
-OUT_DIR := kernel/out/
-DEP_DIR := kernel/dep/
EXEC_NAME := kernel.elf64
TO_ISO += isodir/boot/$(EXEC_NAME)
TO_CLEAN += $(OUT_DIR) $(DEP_DIR)
-
-LOCAL_CXX := g++-system
-LOCAL_CXXFLAGS := $(CXXFLAGS) -mcmodel=kernel -mno-red-zone \
- -isystem $(INCLUDES) -isystem $(INCLUDES)/c++ -isystem $(INCLUDES)/c++/x86_64-unknown-linux-gnu
- # The previous line is a dirty hack. But not that much, because it doesn't allow me to include non-freestanding headers anyways
-LOCAL_LDFLAGS := $(LDFLAGS) -T kernel/linker.ld -z max-page-size=0x1000 \
- -mno-red-zone -mcmodel=kernel
-
-CPPSRCS := $(shell find $(SRC_DIR) -name '*.cpp')
-CPPOBJS := $(CPPSRCS:$(SRC_DIR)%=$(OUT_DIR)%.o)
-ASMSRCS := $(shell find $(SRC_DIR) -name '*.S' | grep -v crt)
-ASMOBJS := $(ASMSRCS:$(SRC_DIR)%=$(OUT_DIR)%.o)
-
-CRTI_OBJ := $(OUT_DIR)/lib/crti.S.o
-CRTBEGIN_OBJ := $(shell $(LOCAL_CXX) $(LOCAL_LDFLAGS) -print-file-name=crtbegin.o)
-CRTEND_OBJ := $(shell $(LOCAL_CXX) $(LOCAL_LDFLAGS) -print-file-name=crtend.o)
-CRTN_OBJ := $(OUT_DIR)/lib/crtn.S.o
-
-OBJS := $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(CPPOBJS) $(ASMOBJS) $(CRTEND_OBJ) $(CRTN_OBJ)
+TO_INCLUDE += $(DEPS)
isodir/boot/$(EXEC_NAME): $(OUT_DIR)$(EXEC_NAME)
- mkdir -p "$(@D)"
- install -m 644 "$<" "$@"
-
-$(OUT_DIR)$(EXEC_NAME): OBJS := $(OBJS)
-$(OUT_DIR)$(EXEC_NAME): LDLIBS := -nostdlib -lgcc
-$(OUT_DIR)$(EXEC_NAME): LDFLAGS := $(LOCAL_LDFLAGS)
-$(OUT_DIR)$(EXEC_NAME): CXX := $(LOCAL_CXX)
-$(OUT_DIR)$(EXEC_NAME): $(OBJS) kernel/linker.ld
- mkdir -p "$(@D)"
- $(CXX) $(LDFLAGS) -o "$@" $(OBJS) $(LDLIBS)
-
-$(OUT_DIR)%.o: DEP_DIR := $(DEP_DIR)
-$(OUT_DIR)%.o: CXXFLAGS := $(LOCAL_CXXFLAGS)
-$(OUT_DIR)%.o: CXX := $(LOCAL_CXX)
-$(OUT_DIR)%.o: $(SRC_DIR)%
- mkdir -p $(@D)
- mkdir -p $(dir $(DEP_DIR)$*)
- $(CXX) $(CXXFLAGS) -c "$<" -MMD -MT "$@" -MF "$(DEP_DIR)$*.d" -o "$@"
-
--include $(DEP_DIR)*.d
+ mkdir -p '$(@D)'
+ install -m 644 '$<' '$@'
+
+CRTI_OBJ := $(OUT_DIR)lib/crti.s.o
+CRTBEGIN_OBJ := $$(shell $$(CXX) $$(LDFLAGS) -print-file-name=crtbegin.o)
+CRTEND_OBJ := $$(shell $$(CXX) $$(LDFLAGS) -print-file-name=crtend.o)
+CRTN_OBJ := $(OUT_DIR)lib/crtn.s.o
+
+TARGETS_TO_VAR := $(OUT_DIR)$(EXEC_NAME) $(PREP) $(DEPS) $(OBJS)
+
+$(TARGETS_TO_VAR): SUBDIR := $(SUBDIR)
+$(TARGETS_TO_VAR): CXX := g++-system
+$(TARGETS_TO_VAR): CXXFLAGS := $(CXXFLAGS) -mcmodel=kernel -mno-red-zone\
+-isystem $(INCLUDES) -isystem $(INCLUDES)/c++ -isystem $(INCLUDES)/c++/x86_64-unknown-linux-gnu
+# The previous line is a dirty hack. But not that much, because it doesn't allow me to include non-freestanding headers anyways
+$(TARGETS_TO_VAR): LDFLAGS := $(LDFLAGS) -z max-page-size=0x1000 -mno-red-zone -mcmodel=kernel
+$(TARGETS_TO_VAR): LDLIBS := -nostdlib -lgcc
+$(OUT_DIR)$(EXEC_NAME): kernel/linker.ld $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(filter-out $(CRTI_OBJ) $(CRTN_OBJ),$(OBJS)) $(CRTEND_OBJ) $(CRTN_OBJ)
+ mkdir -p '$(@D)'
+ $(CXX) $(LDFLAGS) -o '$@' -T $+ $(LDLIBS)
+
+.SECONDARY: $(PREP) $(OBJS)
# You should have received a copy of the CC0 Public Domain Dedication along with
# this file. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-SRC_DIR := test_module/src/
-OUT_DIR := test_module/out/
-DEP_DIR := test_module/dep/
EXEC_NAME := test-module.elf64
-TO_ISO += isodir/boot/$(EXEC_NAME)
+TO_ISO += isodir/boot/$(EXEC_NAME)
TO_CLEAN += $(OUT_DIR) $(DEP_DIR)
-
-LOCAL_CXX := g++-user
-LOCAL_CXXFLAGS := $(CXXFLAGS)
-LOCAL_LDFLAGS := $(LDFLAGS)
-
-CPPSRCS := $(shell find $(SRC_DIR) -name '*.cpp')
-CPPOBJS := $(CPPSRCS:$(SRC_DIR)%=$(OUT_DIR)%.o)
-ASMSRCS := $(shell find $(SRC_DIR) -name '*.S')
-ASMOBJS := $(ASMSRCS:$(SRC_DIR)%=$(OUT_DIR)%.o)
-OBJS := $(CPPOBJS) $(ASMOBJS)
+TO_INCLUDE += $(DEPS)
isodir/boot/$(EXEC_NAME): $(OUT_DIR)$(EXEC_NAME)
- mkdir -p "$(@D)"
- install -m 644 "$<" "$@"
+ mkdir -p '$(@D)'
+ install -m 644 '$<' '$@'
-$(OUT_DIR)$(EXEC_NAME): OBJS := $(OBJS)
-$(OUT_DIR)$(EXEC_NAME): LDLIBS := -nostdlib -lgcc
-$(OUT_DIR)$(EXEC_NAME): LDFLAGS := $(LOCAL_LDFLAGS)
-$(OUT_DIR)$(EXEC_NAME): CXX := $(LOCAL_CXX)
-$(OUT_DIR)$(EXEC_NAME): $(OBJS)
- mkdir -p "$(@D)"
- $(CXX) $(LDFLAGS) -o "$@" $+ $(LDLIBS)
+TARGETS_TO_VAR := $(OUT_DIR)$(EXEC_NAME) $(PREP) $(DEPS) $(OBJS)
-$(OUT_DIR)%.o: DEP_DIR := $(DEP_DIR)
-$(OUT_DIR)%.o: CXXFLAGS := $(LOCAL_CXXFLAGS)
-$(OUT_DIR)%.o: CXX := $(LOCAL_CXX)
-$(OUT_DIR)%.o: $(SRC_DIR)%
- mkdir -p $(@D)
- mkdir -p $(dir $(DEP_DIR)$*)
- $(CXX) $(CXXFLAGS) -c "$<" -MMD -MT "$@" -MF "$(DEP_DIR)$*.d" -o "$@"
+$(TARGETS_TO_VAR): SUBDIR := $(SUBDIR)
+$(TARGETS_TO_VAR): CXX := g++-user
+$(TARGETS_TO_VAR): CXXFLAGS := $(CXXFLAGS)
+$(TARGETS_TO_VAR): LDFLAGS := $(LDFLAGS)
+$(TARGETS_TO_VAR): LDLIBS := -nostdlib -lgcc
+$(OUT_DIR)$(EXEC_NAME): $(OBJS)
+ mkdir -p '$(@D)'
+ $(CXX) $(LDFLAGS) -o '$@' $+ $(LDLIBS)
--include $(DEP_DIR)*.d
+.SECONDARY: $(PREP) $(OBJS)