Makefile: start moving to macro based Makefile target generation

- libam-riscv32-nemu is working.
- libam on platforms other than riscv32-nemu has not been worked on yet.
- klib has not been worked on yet.
This commit is contained in:
xinyangli 2024-12-10 17:45:52 +08:00
parent 1e69b23756
commit 54ee5d6c31
Signed by: xin
SSH key fingerprint: SHA256:UU5pRTl7NiLFJbWJZa+snLylZSXIz5rgHmwjzv8v4oE
5 changed files with 93 additions and 92 deletions

View file

@ -1,4 +1,5 @@
# Makefile for AbstractMachine Kernels and Libraries # Makefile for AbstractMachine Kernels and Libraries
include scripts/helpers/rules.mk
### *Get a more readable version of this Makefile* by `make html` (requires python-markdown) ### *Get a more readable version of this Makefile* by `make html` (requires python-markdown)
html: html:
@ -17,9 +18,6 @@ endif
### Override checks when `make clean/clean-all/html` ### Override checks when `make clean/clean-all/html`
ifeq ($(findstring $(MAKECMDGOALS),clean|clean-all|html),) ifeq ($(findstring $(MAKECMDGOALS),clean|clean-all|html),)
### Print build info message
$(info # Building $(NAME)-$(MAKECMDGOALS) [$(ARCH)])
### Check: environment variable `$AM_HOME` looks sane ### Check: environment variable `$AM_HOME` looks sane
ifeq ($(wildcard $(AM_HOME)/am/include/am.h),) ifeq ($(wildcard $(AM_HOME)/am/include/am.h),)
$(error $$AM_HOME must be an AbstractMachine repo) $(error $$AM_HOME must be an AbstractMachine repo)
@ -36,33 +34,16 @@ ARCH_SPLIT = $(subst -, ,$(ARCH))
ISA = $(word 1,$(ARCH_SPLIT)) ISA = $(word 1,$(ARCH_SPLIT))
PLATFORM = $(word 2,$(ARCH_SPLIT)) PLATFORM = $(word 2,$(ARCH_SPLIT))
### Check if there is something to build
ifeq ($(flavor SRCS), undefined)
$(error Nothing to build)
endif
### Checks end here ### Checks end here
endif endif
## 2. General Compilation Targets ## 2. General Compilation Targets
### Create the destination directory (`build/$ARCH`) ### Create the destination directory (`build/$ARCH`)
WORK_DIR = $(shell pwd) WORK_DIR ?= $(shell pwd)
DST_DIR = $(WORK_DIR)/build/$(ARCH) DST_DIR ?= $(WORK_DIR)/build/$(ARCH)
$(shell mkdir -p $(DST_DIR)) LIB_BUILDDIR ?= $(DST_DIR)/lib
INSTALLDIR ?= $(WORK_DIR)/build/install/$(ARCH)
### Compilation targets (a binary image or archive)
IMAGE_REL = build/$(NAME)-$(ARCH)
IMAGE = $(abspath $(IMAGE_REL))
ARCHIVE = $(WORK_DIR)/build/$(NAME)-$(ARCH).a
### Collect the files to be linked: object files (`.o`) and libraries (`.a`)
OBJS = $(addprefix $(DST_DIR)/, $(addsuffix .o, $(basename $(SRCS))))
LIBS := $(sort $(LIBS) am klib) # lazy evaluation ("=") causes infinite recursions
LINKAGE = $(OBJS) \
$(addsuffix -$(ARCH).a, $(join \
$(addsuffix /build/, $(addprefix $(AM_HOME)/, $(LIBS))), \
$(LIBS) ))
## 3. General Compilation Flags ## 3. General Compilation Flags
@ -76,27 +57,13 @@ OBJDUMP ?= $(CROSS_COMPILE)objdump
OBJCOPY ?= $(CROSS_COMPILE)objcopy OBJCOPY ?= $(CROSS_COMPILE)objcopy
READELF ?= $(CROSS_COMPILE)readelf READELF ?= $(CROSS_COMPILE)readelf
### Compilation flags
INC_PATH += $(WORK_DIR)/include $(addsuffix /include/, $(addprefix $(AM_HOME)/, $(LIBS)))
INCFLAGS += $(addprefix -I, $(INC_PATH))
ARCH_H := arch/$(ARCH).h
CFLAGS += -lm -g -O3 -MMD -Wall $(INCFLAGS) \
-D__ISA__=\"$(ISA)\" -D__ISA_$(shell echo $(ISA) | tr a-z A-Z)__ \
-D__ARCH__=$(ARCH) -D__ARCH_$(shell echo $(ARCH) | tr a-z A-Z | tr - _) \
-D__PLATFORM__=$(PLATFORM) -D__PLATFORM_$(shell echo $(PLATFORM) | tr a-z A-Z | tr - _) \
-DARCH_H=\"$(ARCH_H)\" \
-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector \
-Wno-main -U_FORTIFY_SOURCE -fvisibility=hidden
CXXFLAGS += $(CFLAGS) -ffreestanding -fno-rtti -fno-exceptions CXXFLAGS += $(CFLAGS) -ffreestanding -fno-rtti -fno-exceptions
ASFLAGS += $(INCFLAGS) ASFLAGS += $(INCFLAGS)
LDFLAGS += -z noexecstack LDFLAGS += -z noexecstack
INTERFACE_LDFLAGS += -z noexecstack
## 4. Arch-Specific Configurations ## 4. Arch-Specific Configurations
### Paste in arch-specific configurations (e.g., from `scripts/x86_64-qemu.mk`)
-include $(AM_HOME)/scripts/$(ARCH).mk
### Fall back to native gcc/binutils if there is no cross compiler ### Fall back to native gcc/binutils if there is no cross compiler
ifeq ($(wildcard $(shell which $(CC))),) ifeq ($(wildcard $(shell which $(CC))),)
$(info # $(CC) not found; fall back to default gcc and binutils) $(info # $(CC) not found; fall back to default gcc and binutils)
@ -105,43 +72,31 @@ endif
## 5. Compilation Rules ## 5. Compilation Rules
### Rule (compile): a single `.c` -> `.o` (gcc) ### Build libam
$(DST_DIR)/%.o: %.c
@mkdir -p $(dir $@) && echo + CC $<
@$(CC) -std=gnu11 $(CFLAGS) -c -o $@ $(realpath $<)
### Rule (compile): a single `.cc` -> `.o` (g++) #### Include archetecture specific build flags
$(DST_DIR)/%.o: %.cc include $(AM_HOME)/scripts/$(ARCH).mk
@mkdir -p $(dir $@) && echo + CXX $<
@$(CXX) -std=c++17 $(CXXFLAGS) -c -o $@ $(realpath $<)
### Rule (compile): a single `.cpp` -> `.o` (g++) #### Generating build rules with ADD_LIBRARY call. Target specific build flags can be tuned via changing prefixed variables (AM_ here)
$(DST_DIR)/%.o: %.cpp AM_INCPATH += $(AM_HOME)/am/include $(AM_HOME)/am/src $(AM_HOME)/klib/include
@mkdir -p $(dir $@) && echo + CXX $< AM_CFLAGS += -lm -g -O3 -MMD -Wall $(addprefix -I, $(AM_INCPATH)) \
@$(CXX) -std=c++17 $(CXXFLAGS) -c -o $@ $(realpath $<) -D__ISA__=\"$(ISA)\" -D__ISA_$(shell echo $(ISA) | tr a-z A-Z)__ \
-D__ARCH__=$(ARCH) -D__ARCH_$(shell echo $(ARCH) | tr a-z A-Z | tr - _) \
-D__PLATFORM__=$(PLATFORM) -D__PLATFORM_$(shell echo $(PLATFORM) | tr a-z A-Z | tr - _) \
-DARCH_H=\"$(ARCH_H)\" \
-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector \
-Wno-main -U_FORTIFY_SOURCE -fvisibility=hidden
### Rule (compile): a single `.S` -> `.o` (gcc, which preprocesses and calls as) $(eval $(call ADD_LIBRARY,$(LIB_BUILDDIR)/libam-$(ARCH).a,AM_))
$(DST_DIR)/%.o: %.S
@mkdir -p $(dir $@) && echo + AS $<
@$(AS) $(ASFLAGS) -c -o $@ $(realpath $<)
### Rule (recursive make): build a dependent library (am, klib, ...) ALL := am
$(LIBS): %: all: $(addsuffix -$(ARCH).a, $(addprefix $(LIB_BUILDDIR)/lib, $(ALL)))
@$(MAKE) -s -C $(AM_HOME)/$* archive
### Rule (link): objects (`*.o`) and libraries (`*.a`) -> `IMAGE.elf`, the final ELF binary to be packed into image (ld) ### Rule (link): objects (`*.o`) and libraries (`*.a`) -> `IMAGE.elf`, the final ELF binary to be packed into image (ld)
$(IMAGE).elf: $(OBJS) $(LIBS) $(IMAGE).elf: $(OBJS) $(LIBS)
@echo + LD "->" $(IMAGE_REL).elf @echo + LD "->" $(IMAGE_REL).elf
@$(LD) $(LDFLAGS) -o $(IMAGE).elf --start-group $(LINKAGE) --end-group @$(LD) $(LDFLAGS) -o $(IMAGE).elf --start-group $(LINKAGE) --end-group
### Rule (archive): objects (`*.o`) -> `ARCHIVE.a` (ar)
$(ARCHIVE): $(OBJS)
@echo + AR "->" $(shell realpath $@ --relative-to .)
@$(AR) rcs $(ARCHIVE) $(OBJS)
### Rule (`#include` dependencies): paste in `.d` files generated by gcc on `-MMD`
-include $(addprefix $(DST_DIR)/, $(addsuffix .d, $(basename $(SRCS))))
## 6. Miscellaneous ## 6. Miscellaneous
### Build order control ### Build order control

47
scripts/helpers/rules.mk Normal file
View file

@ -0,0 +1,47 @@
# Usage:
# $(1): Target prefix
#
# Generate build rules for files in variable <PREFIX>_SRCS. Use <PREFIX>_CFLAGS,
# <PREFIX>_CXXFLAGS, <PREFIX>_ASFLAGS to control build flags.
# E.g:
# $(eval $(call COMPILE_RULES,AM_))
define COMPILE_RULES
AM_OBJS := $(addprefix $(DST_DIR)/, $(addsuffix .o, $(AM_SRCS)))
### Rule (compile): a single `.c` -> `.c.o` (gcc)
$$(filter %.c.o, $$($(1)OBJS)): $$(DST_DIR)/%.c.o: %.c
@mkdir -p $$(dir $$@) && echo + CC $$<
@$$(CC) $$($(1)CFLAGS) -c -o $$@ $$(realpath $$<)
### Rule (compile): a single `.cc` -> `.cc.o` (g++)
$$(filter %.cc.o, $$($(1)OBJS)): $$(DST_DIR)/%.cc.o: %.cc
@mkdir -p $$(dir $$@) && echo + CXX $$<
@$$(CXX) $$($(1)CXXFLAGS) -c -o $$@ $$(realpath $$<)
### Rule (compile): a single `.cpp` -> `.cpp.o` (g++)
$$(filter %.cpp.o, $$($(1)OBJS)): $$(DST_DIR)/%.cpp.o: %.cpp
@mkdir -p $$(dir $$@) && echo + CXX $$<
@$$(CXX) $$($(1)CXXFLAGS) -c -o $$@ $$(realpath $$<)
### Rule (compile): a single `.S` -> `.S.o` (gcc, which preprocesses and calls as)
$$(filter %.S.o, $$($(1)OBJS)): $$(DST_DIR)/%.S.o: %.S
@mkdir -p $$(dir $$@) && echo + AS $$<
@$$(AS) $$($(1)ASFLAGS) -c -o $$@ $$(realpath $$<)
### Rule (`#include` dependencies): paste in `.d` files generated by gcc on `-MMD`
-include $$(addprefix $$(DST_DIR)/, $$(addsuffix .d, $$(filter %.c %.cc, $$(AM_SRCS))))
endef
# Usage:
# $(1): Library name
# $(2): Library variable prefix
# E.g:
# $(eval $(call ADD_LIBRARY,am-riscv,AM_))
define ADD_LIBRARY
$(eval $(call COMPILE_RULES,$(2)))
$(1): $$($(2)OBJS)
@mkdir -p $$(dir $$@)
@echo + AR "->" $$(patsubst $$(CURDIR)/%,%,$(1))
@$$(AR) rcs $$@ $$($(2)OBJS)
endef

View file

@ -1,8 +1,7 @@
CROSS_COMPILE := riscv64-linux-gnu- CROSS_COMPILE := riscv64-linux-gnu-
COMMON_CFLAGS := -fno-pic -march=rv64g -mcmodel=medany -mstrict-align AM_CFLAGS += -static -fno-pic -march=rv64g -mcmodel=medany -mstrict-align
CFLAGS += $(COMMON_CFLAGS) -static AM_ASFLAGS += -static -fno-pic -march=rv32g_zicsr -mcmodel=medany -O0
ASFLAGS += $(COMMON_CFLAGS) -O0 AM_LDFLAGS += -melf64lriscv -O2
LDFLAGS += -melf64lriscv -O2
# overwrite ARCH_H defined in $(AM_HOME)/Makefile # overwrite ARCH_H defined in $(AM_HOME)/Makefile
ARCH_H := arch/riscv.h ARCH_H := arch/riscv.h

View file

@ -1,21 +1,19 @@
AM_SRCS := platform/nemu/trm.c \ AM_SRCS := am/src/platform/nemu/trm.c \
platform/nemu/ioe/ioe.c \ am/src/platform/nemu/ioe/ioe.c \
platform/nemu/ioe/timer.c \ am/src/platform/nemu/ioe/timer.c \
platform/nemu/ioe/input.c \ am/src/platform/nemu/ioe/input.c \
platform/nemu/ioe/gpu.c \ am/src/platform/nemu/ioe/gpu.c \
platform/nemu/ioe/audio.c \ am/src/platform/nemu/ioe/audio.c \
platform/nemu/ioe/disk.c \ am/src/platform/nemu/ioe/disk.c \
platform/nemu/mpe.c am/src/platform/nemu/mpe.c
CFLAGS += -fdata-sections -ffunction-sections AM_CFLAGS += -fdata-sections -ffunction-sections
LDFLAGS += -T $(AM_HOME)/scripts/linker.ld \ AM_LDFLAGS += -T $(AM_HOME)/scripts/linker.ld \
--defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0 --defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
LDFLAGS += --gc-sections -e _start AM_LDFLAGS += --gc-sections -e _start
NEMUFLAGS += -b
#-l $(shell dirname $(IMAGE).elf)/nemu-log.txt
CFLAGS += -DMAINARGS=\"$(mainargs)\" AM_CFLAGS += -DMAINARGS=\"$(mainargs)\"
CFLAGS += -I$(AM_HOME)/am/src/platform/nemu/include AM_INCPATH += $(AM_HOME)/am/src/platform/nemu/include
.PHONY: $(AM_HOME)/am/src/platform/nemu/trm.c .PHONY: $(AM_HOME)/am/src/platform/nemu/trm.c
image: $(IMAGE).elf image: $(IMAGE).elf
@ -23,6 +21,9 @@ image: $(IMAGE).elf
@echo + OBJCOPY "->" $(IMAGE_REL).bin @echo + OBJCOPY "->" $(IMAGE_REL).bin
@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin @$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin
NEMUFLAGS += -b
#-l $(shell dirname $(IMAGE).elf)/nemu-log.txt
run: image run: image
$(MAKE) -C $(NEMU_HOME) ISA=$(ISA) run ARGS="$(NEMUFLAGS)" IMG=$(IMAGE).bin $(MAKE) -C $(NEMU_HOME) ISA=$(ISA) run ARGS="$(NEMUFLAGS)" IMG=$(IMAGE).bin

View file

@ -1,10 +1,9 @@
include $(AM_HOME)/scripts/isa/riscv.mk include $(AM_HOME)/scripts/isa/riscv.mk
include $(AM_HOME)/scripts/platform/nemu.mk include $(AM_HOME)/scripts/platform/nemu.mk
CFLAGS += -DISA_H=\"riscv/riscv.h\" AM_CFLAGS += -DISA_H=\"riscv/riscv.h\" -march=rv32im_zicsr -mabi=ilp32 # overwrite
COMMON_CFLAGS += -march=rv32im_zicsr -mabi=ilp32 # overwrite AM_LDFLAGS += -melf32lriscv # overwrite
LDFLAGS += -melf32lriscv # overwrite
AM_SRCS += riscv/nemu/start.S \ AM_SRCS += am/src/riscv/nemu/start.S \
riscv/nemu/cte.c \ am/src/riscv/nemu/cte.c \
riscv/nemu/trap.S \ am/src/riscv/nemu/trap.S \
riscv/nemu/vme.c am/src/riscv/nemu/vme.c