跳转至

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.obuild
$(@F) 目标文件名部分 $(@F) build/main.omain.o

命令前缀表格

前缀 作用 示例
@ 不显示执行的命令 @echo "Hello"
- 忽略命令的错误 -rm file
+ 总是执行命令 +make sub