根目录Makefile
初始化一些变量
TARGETS := model executiontb cpu
ROOT_DIR?=$(abspath $(CURDIR))
OUT_DIR?=$(abspath $(CURDIR))
ADDR_FILE:=$(ROOT_DIR)/build/mmu_addr.txt
make all 执行 make help
all: help
.PHONY后面跟的目标都被称为伪目标,也就是说我们 make 命令后面跟的参数如果出现在.PHONY 定义的伪目标中,那就直接在Makefile中就执行伪目标的依赖和命令。不管Makefile同级目录下是否有该伪目标同名的文件,即使有也不会产生冲突。另一个就是提高执行makefile时的效率
.PHONY: session_dump_file
session_dump_file:
ifndef SESSION_DUMP
$(error No SESSION_DUMP file provided)
endif
echo和@echo的区别
make 在执行命令之前会把要执行的命令进行输出,称之为回显
如果要执行的命令以字符 @ 开始,则不会回显,例如:
1. @echo XXX
在执行命令时,将输出
XXX
2. echo XXX
在执行命令时,将输出
echo XXX
XXX
@echo "Binarizing $(SESSION_DUMP) -> ${OUT_DIR}/src/session_dump.c"
build/bin2a.sh -l $(SESSION_DUMP) g_session_dump > ${OUT_DIR}/src/session_dump.c
.PHONY: self_check
self_check:
ifdef SELF_CHECK
@echo "SELF_CHECK enabled: Binarizing $(SELF_CHECK) -> ${OUT_DIR}/src/self_check_reference.c"
build/bin2a.sh -i $(SELF_CHECK) g_self_check_reference > ${OUT_DIR}/src/self_check_reference.c
endif
define
endef
定义一个函数
可以通过$(call xxx)来进行调用
define target_rule
$(1): session_dump_file self_check
ifeq ($(PRE_CONVERT_PTABLE), 1)
$$(MAKE) -f build/compile-$(1).mk ROOT_DIR=$(ROOT_DIR) OUT_DIR=$(OUT_DIR) ADDR_FILE=$(ADDR_FILE)
python $(ROOT_DIR)/build/mmu_restore.py -i $(SESSION_DUMP) -s $(ADDR_FILE) -b 0
/bin/rm -rf obj bin
/bin/rm $(ADDR_FILE)
/bin/mv $(SESSION_DUMP).tmp $(SESSION_DUMP)
build/bin2a.sh -l $(SESSION_DUMP) g_session_dump > ${OUT_DIR}/src/session_dump.c
endif
顶层Makefile使用make -f调用子目录中的文件(文件名可以随意,不一定用Makefile作为文件名)作为Makefile,经测试,在顶层Makefile中使用-f选项,例如make -f ./xxx/xx/build.mk 此时make命令的工作目录仍然是顶层目录,即CUDIR变量依然是./目录而不是./xxx/xx/目录
$$(MAKE) -f build/compile-$(1).mk ROOT_DIR=$(ROOT_DIR) OUT_DIR=$(OUT_DIR)
.PHONY: $(1)
endef
$(foreach target,$(TARGETS),$(eval $(call target_rule,$(target))))
clean: realclean
realclean:
@echo "Removing obj & bin"
/bin/rm -rf obj bin
TARBALL = $(abspath $(CURDIR)/../$(notdir $(CURDIR)).tar.bz2)
tarball: realclean
@echo "Packaging $(TARBALL)"
cd ..; \
tar cjf $(TARBALL) $(notdir $(CURDIR))
help:
@echo "==============================="
@echo ""
@echo "make SESSION_DUMP=session_dump.mvedump"
@echo " [AFBC=1]"
@echo " [ARCH=MVE550] [CPU=8-A.32] [MCPU=a53] [OPTS=\"<extra compile flags>\"]"
@echo " [START_ADDRESS=0x80008000] [HEAP_ADDRESS=0x86000000] [UNCACHED_BUFFER=0x88000000]"
@echo " [MODEL_LIB=<model library>]"
@echo " [SELF_CHECK=<reference_output_file>]"
@echo " [ $(foreach target,$(TARGETS),$(target) |) tarball | clean | realclean ]"
@echo ""
@echo "SESSION_DUMP : Dump file created with mve_decode/mve_encode with option --save_session"
@echo "START_ADDRESS : Binary image entry point"
@echo "HEAP_ADDRESS : Heap & stack address. Please see generated scatter file"
@echo "UNCACHED_BUFFER : Uncached memory region where output buffers are allocated"
@echo "OPTS : Extra compile flags passed to the source."
@echo " -DMVEVERBOSE - extra verbose"
@echo " -DMVEDEBUG - extra debug"
@echo " -DDHEAP_SIZE - size of memory pool for dynamic allocation. If not specified"
@echo " 160MB (0xA000000) is used. Please note that aprox. 6.5MB"
@echo " (6.7MiB) and 25MB (25.9MiB) is needed per HD and UHD frame"
@echo " respectively."
@echo "SELF_CHECK : Enable built-in comparison with output reference file, instead of saving output"
@echo "NO_UART : UART is not present in the testbench"
@echo "NO_GIC : GIC is not present in the testbench"
@echo "clean : Clean all binary and object files"
@echo "realclean : Clean all binary and object files"
@echo ""
@echo "==============================="
.PHONY: clean realclean tarball help
检查变量
ifeq ($(ROOT_DIR),)
$(error "ROOT_DIR is not defined")
endif
ifeq ($(OBJ_DIR),)
$(error "OBJ_DIR is not defined")
endif
ifeq ($(BIN_DIR),)
$(error "BIN_DIR is not defined")
endif
ifeq ($(SESSION_DUMP),)
$(error "SESSION_DUMP is not defined")
endif
ifdef SELF_CHECK
CHECK=1
else
CHECK=0
endif
CREATE_VARIOUS_DIRS__EVAL_FOR_SIDE_EFFECTS := $(shell mkdir -p $(OBJ_DIR) && mkdir -p $(BIN_DIR))
# Case
upper_case = $(shell echo $(1) | tr a-z A-Z)
lower_case = $(shell echo $(1) | tr A-Z a-z)
# Hash
# $(1) : Prefix
# $(2) : String
hash = $(1)_$(shell echo $(2) | md5sum | cut -d ' ' -f1)
ARCH ?= MVE550
# Top main source file
TOP_MAIN := src/miniplayer.c
TEST_OBJS := $(OBJ_DIR)/$(subst .c,.o,$(notdir $(TOP_MAIN)))
# User CFLAGS
COMMON_OPTS := $(OPTS)
COMMON_OPTS += $(if $(MVE_BASE), -DMVE_BASE=$(MVE_BASE),)
COMMON_OPTS += $(if $(MVE_IRQ), -DMVE_IRQ=$(MVE_IRQ),)
COMMON_OPTS += $(if $(IN_FILE), -DIN_FILE=\"$(IN_FILE)\",)
COMMON_OPTS += $(if $(OUT_FILE), -DOUT_FILE=\"$(OUT_FILE)\",)
COMMON_OPTS += $(if $(filter 1, $(SAVE_SESSION_V2)), -DSAVE_SESSION_V2,)
COMMON_OPTS += -DMEM_MAPPING_INFO
# 64/32 bit builds
ifndef SYSTEM
ifeq ($(shell uname -m),x86_64)
SYSTEM := 64
else
SYSTEM := 32
endif
$(info "SYSTEM is not defined. Using SYSTEM=$(SYSTEM)")
endif
# Generate source file from binary
# $(1) : Source binary dir
# $(2) : Source binary file variable name
# $(3) : Int array
# $(4) : Target C array name
define bin2a_rule
$(2)_C := $(OBJ_DIR)/$(call hash,auto_gen_$(call lower_case,$(2)),$(1)/$($(2))).c
$$($(2)_C): ./build/bin2a.sh $(1)/$($(2))
@echo "Generating $$@"
rm -rf $(OBJ_DIR)/auto_gen_$(call lower_case,$(2))_*
$$< $(if $(3),-i,-c) $(1)/$($(2)) $(4) > $$@
endef
# Generate this rule to track CFLAGS and embedded file name changes
# $(1) : All concerned objects
# $(2) : CFLAGS variable
define cflags_rule
$(1): $(OBJ_DIR)/CFLAGS
.PHONY: force
$(OBJ_DIR)/CFLAGS: force
test -e $$@ || touch $$@
echo "$(2)" > $$@.tmp
cmp -s $$@ $$@.tmp || cp $$@.tmp $$@
rm $$@.tmp
endef
初始化变量
TARGET_DIR := model
OBJ_DIR ?= $(ROOT_DIR)/obj/$(TARGET_DIR)
BIN_DIR ?= $(ROOT_DIR)/bin/$(TARGET_DIR)
# Build testbench by default
all: model
include $(ROOT_DIR)/build/common.mk
CC := gcc
LD := gcc
AR := ar
###############################################################################
#
# Model
#
定义编译出来的执行文件
model: $(BIN_DIR)/model_test
定义要编译的源文件
MODEL_SRCS := src/mve_communication.c \
src/mve_core.c \
src/mve_fw_manager.c \
src/mve_hw.c \
src/mve_mmu.c \
src/mve_port_linux_emul.c \
src/mve_port_linux_emul_utils.c \
src/session_dump.c \
$(TOP_MAIN)
#ifdef SELF_CHECK
#CHECK=1
#else
#CHECK=0
#endif
addprefix 是makefile中的函数,是添加前缀的函数
例如:
$(addprefix src/,foo bar)
返回值为"src/foo src/bar"
SRCS_ABS := $(addprefix $(ROOT_DIR)/,$(MODEL_SRCS))
MODEL_DIR := $(ROOT_DIR)/../model
MODEL_LIB ?= $(MODEL_DIR)/libmvemodel$(SYSTEM).so
wildcard, $(wildcard 指定文件类型), 显示指定路径下指定文件类型的所有文件
ifeq ($(wildcard $(MODEL_LIB)),)
$(error "Can't find $(MODEL_LIB)")
endif
MODEL_CFLAGS := -D_POSIX_C_SOURCE=199309L -O2 -m$(SYSTEM) -std=c99 -pthread -DTARGET_LINUX$(SYSTEM)
$(dir <names...> )
名称:取目录函数------dir。
功能:从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠("/")之前的部分。如果没有反斜杠,那么返回"./"。返回:返回文件名序列<names>的目录部分。示例: $(dir src/foo.c hacks)返回值是"src/ ./"
$(if $(filter 1,$(CHECK)),-DMVE_SELF_CHECK=1,) -I$(dir $(MODEL_LIB)) $(INC_COMMON) $(COMMON_OPTS)
MODEL_LDFLAGS := -m$(SYSTEM) -pthread $(COMMON_OPTS)
MODEL_LDLIBS := -lm -lrt
notdir
名称:取文件函数------notdir。包括后缀,去除文件夹路径
功能:从文件名序列<names>中取出非目录部分。非目录部分是指最后一个反斜杠("/"
)之后的部分。
返回:返回文件名序列<names>的非目录部分。
示例: $(notdir src/foo.c hacks)返回值是"foo.c hacks"
get_model_obj = $(addprefix $(OBJ_DIR)/,$(notdir $(patsubst %.c,%.o,$(1))))
define model_rule
$(call get_model_obj,$(1)): $(1) $(OMX_DIR)
@echo "Compiling $1"
$(CC) -MM -MG $(MODEL_CFLAGS) $$< | sed -e 's,^\([^:]*\)\.o[ ]*:,$$(@D)/\1.o $$(@D)/\1.d:,' >$$(@:.o=.d)
$(CC) -c -o $$@ $1 $(MODEL_CFLAGS)
endef
$(foreach file,$(SRCS_ABS),$(eval $(call model_rule,$(file))))
OBJS := $(call get_model_obj,$(SRCS_ABS))
$(BIN_DIR)/model_test: $(OBJS) $(MODEL_LIB)
@echo " >> Building $@"
$(LD) -o $@ $(MODEL_LDFLAGS) $^ $(MODEL_LDLIBS)
###############################################################################
#
# CFLAGS
#
#
$(eval $(call cflags_rule,$(OBJS),$(MODEL_CFLAGS) $(MODEL_LDFLAGS) $(MODEL_LIB)))
###############################################################################
#
# Dependencies
#
DEPS := $(OBJS:.o=.d)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif