makefile
示例
# Common part for the Makefile.
# This file will be included by the Makefile of each project.
# Custom Macro Definition (Common part)
include ../defines.mk
DEFS +=
CROSS_COMPILE = riscv64-unknown-elf-
CFLAGS += -nostdlib -fno-builtin -g -Wall
CFLAGS += -march=rv32g -mabi=ilp32
QEMU = qemu-system-riscv32
QFLAGS = -nographic -smp 1 -machine virt -bios none
GDB = gdb-multiarch
CC = ${CROSS_COMPILE}gcc
OBJCOPY = ${CROSS_COMPILE}objcopy
OBJDUMP = ${CROSS_COMPILE}objdump
MKDIR = mkdir -p
RM = rm -rf
OUTPUT_PATH = out
# SRCS_ASM & SRCS_C are defined in the Makefile of each project.
OBJS_ASM := $(addprefix ${OUTPUT_PATH}/, $(patsubst %.S, %.o, ${SRCS_ASM}))
OBJS_C := $(addprefix $(OUTPUT_PATH)/, $(patsubst %.c, %.o, ${SRCS_C}))
OBJS = ${OBJS_ASM} ${OBJS_C}
ELF = ${OUTPUT_PATH}/os.elf
BIN = ${OUTPUT_PATH}/os.bin
USE_LINKER_SCRIPT ?= true
ifeq (${USE_LINKER_SCRIPT}, true)
LDFLAGS = -T ${OUTPUT_PATH}/os.ld.generated
else
LDFLAGS = -Ttext=0x80000000
endif
.DEFAULT_GOAL := all
all: ${OUTPUT_PATH} ${ELF}
${OUTPUT_PATH}:
@${MKDIR} $@
# start.o must be the first in dependency!
#
# For USE_LINKER_SCRIPT == true, before do link, run preprocessor manually for
# linker script.
# -E specifies GCC to only run preprocessor
# -P prevents preprocessor from generating linemarkers (#line directives)
# -x c tells GCC to treat your linker script as C source file
${ELF}: ${OBJS}
ifeq (${USE_LINKER_SCRIPT}, true)
${CC} -E -P -x c ${DEFS} ${CFLAGS} os.ld > ${OUTPUT_PATH}/os.ld.generated
endif
${CC} ${CFLAGS} ${LDFLAGS} -o ${ELF} $^
${OBJCOPY} -O binary ${ELF} ${BIN}
${OUTPUT_PATH}/%.o : %.c
${CC} ${DEFS} ${CFLAGS} -c -o $@ $<
${OUTPUT_PATH}/%.o : %.S
${CC} ${DEFS} ${CFLAGS} -c -o $@ $<
run: all
@${QEMU} -M ? | grep virt >/dev/null || exit
@echo "Press Ctrl-A and then X to exit QEMU"
@echo "------------------------------------"
@${QEMU} ${QFLAGS} -kernel ${ELF}
.PHONY : debug
debug: all
@echo "Press Ctrl-C and then input 'quit' to exit GDB and QEMU"
@echo "-------------------------------------------------------"
@${QEMU} ${QFLAGS} -kernel ${ELF} -s -S &
@${GDB} ${ELF} -q -x ../gdbinit
.PHONY : code
code: all
@${OBJDUMP} -S ${ELF} | less
.PHONY : clean
clean:
@${RM} ${OUTPUT_PATH}
自动变量表格
| 符号 |
含义 |
示例 |
说明 |
$@ |
当前目标名 |
$(CC) -o $@ |
代表规则中的目标文件名 |
$< |
第一个依赖文件 |
$(CC) -c $< |
代表规则中第一个依赖文件 |
$^ |
所有依赖文件 |
$(CC) $^ -o $@ |
代表规则中所有依赖文件 |
$? |
比目标新的依赖 |
$(CC) $? -o $@ |
只重新编译更新的文件 |
$* |
匹配通配符的部分 |
%.o: %.c 中的 $* |
代表 % 匹配的部分 |
$(@D) |
目标目录部分 |
$(@D)/file |
build/main.o → build |
$(@F) |
目标文件名部分 |
$(@F) |
build/main.o → main.o |
命令前缀表格
| 前缀 |
作用 |
示例 |
@ |
不显示执行的命令 |
@echo "Hello" |
- |
忽略命令的错误 |
-rm file |
+ |
总是执行命令 |
+make sub |