Makefile解析(ARM LINLON V5/V7 VPU firmware tools例)

根目录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

common.mk

复制代码
检查变量
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

compile-module.mk

复制代码
初始化变量
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
相关推荐
A小辣椒3 小时前
TShark:基础知识
linux
AlfredZhao5 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao19 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334661 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪1 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5202 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩2 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
古城小栈2 天前
Unix 与 Linux 异同小叙
linux·服务器·unix