diff --git a/build.sh b/build.sh index 7db741e..8016564 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,9 @@ +# 设置脚本在遇到任何错误时立即退出,避免错误累积 set -e +# 定义使用帮助函数,当参数不正确时显示帮助信息 usage() { + # 输出脚本的使用方法到标准错误输出 echo "usage: $0 [variants] [--evmy] [--cache] [--cpri/--ecpri/--jesd] [--pcie] [--test caseid] " 1>&2 msg=${1:-} if [ ! -z "${msg}" ]; then @@ -9,98 +12,103 @@ usage() { exit 1 } -variants= -fronthaul_option="cpri" -backhaul_option="tmac" -cache_option="no" -test_option="no" -case_id=0 -board_option="EVB" -arm_version=`git log --decorate -1 | sed -n '1p' | awk '{print substr($2,0)}'` -arm_build_date=`date +"%Y-%m-%d-%H:%M:%S"` +# 初始化默认参数值 +variants= # 存储其他未指定参数 +fronthaul_option="cpri" # 默认前传接口(CPRI) +backhaul_option="tmac" # 默认回传接口(TMAC) +cache_option="no" # 默认不启用缓存 +test_option="no" # 默认不运行测试 +case_id=0 # 默认测试用例ID +board_option="EVB" # 默认板卡类型为EVB -#判断tag是否存在 +# 获取Git仓库信息用于版本控制 +arm_version=`git log --decorate -1 | sed -n '1p' | awk '{print substr($2,0)}'` # 获取最新的commit hash +arm_build_date=`date +"%Y-%m-%d-%H:%M:%S"` # 获取当前时间作为构建时间 + +# 检查是否存在Git标签(用于版本号) if [ -z `git log --decorate -1 | grep -oP '(?<=tag: ).*' | awk '{print substr($1,0)}'` ] then - arm_tag="NULL"; + arm_tag="NULL"; # 如果不存在标签则设为NULL else - arm_tag=`git log --decorate -1 | grep -oP '(?<=tag: ).*' | awk '{print substr($1,0)}'` - arm_tag=${arm_tag%?} + arm_tag=`git log --decorate -1 | grep -oP '(?<=tag: ).*' | awk '{print substr($1,0)}'` + arm_tag=${arm_tag%?} # 去除末尾特殊字符 fi +# 解析用户输入的参数 while [[ "$#" > 0 ]]; do case $1 in - --cache) cache_option="yes"; shift;; - - --evmy) board_option="EVMY"; shift;; - --evb) board_option="EVB"; shift;; - --evmyf) board_option="EVMYF"; shift;; - --evmyt) board_option="EVMYT"; shift;; - - --cpri) fronthaul_option="cpri"; shift;; - --ecpri) fronthaul_option="ecpri"; shift;; - --jesd) fronthaul_option="jesd"; shift;; - --pcie) backhaul_option="pcie"; shift;; - - --test) test_option="yes"; + --cache) cache_option="yes"; shift;; # 启用缓存功能 + --evmy) board_option="EVMY"; shift;; # 设置板卡类型为EVMY + --evb) board_option="EVB"; shift;; # 设置板卡类型为EVB + --evmyf) board_option="EVMYF"; shift;; # 设置板卡类型为EVMYF + --evmyt) board_option="EVMYT"; shift;; # 设置板卡类型为EVMYT + --cpri) fronthaul_option="cpri"; shift;;# 设置前传接口为CPRI + --ecpri) fronthaul_option="ecpri"; shift;;# 设置前传接口为eCPRI + --jesd) fronthaul_option="jesd"; shift;;# 设置前传接口为JESD + --pcie) backhaul_option="pcie"; shift;; # 设置回传接口为PCIe + --test) test_option="yes"; # 启用测试模式 + # 检查是否提供了测试用例ID(必须为数字) if [[ ! -z "$2" ]] && [[ -n "$(echo $2 | sed -n " /^[0-9]\+$/p")" ]]; then - case_id=$2; shift; + case_id=$2; shift; # 设置测试用例ID fi shift;; - - --*| -*) usage "unknown option $1"; exit 1;; - *) variants+=" $1"; shift;; + --*| -*) usage "unknown option $1"; exit 1;; # 遇到未知选项报错 + *) variants+=" $1"; shift;; # 其他未定义参数存入variants变量 esac; done -export arm_version=${arm_version} -export arm_tag=${arm_tag} -export arm_build_date=${arm_build_date} + +# 导出环境变量供后续编译使用 +export arm_version=${arm_version} # 版本号 +export arm_tag=${arm_tag} # Git标签 +export arm_build_date=${arm_build_date} # 构建时间 +# 打印版本信息 printf "#arm_version[%s], arm_tag[%s], arm_build_date:[%s]\n" $arm_version $arm_tag $arm_build_date -export DIR_ROOT=$(cd `dirname "$0"`;pwd) -#echo "# script_dir:${DIR_ROOT}" -export BUILD_DIR=${DIR_ROOT}/build +# 设置工程根目录和构建目录 +export DIR_ROOT=$(cd `dirname "$0"`;pwd) # 获取脚本所在目录作为根目录 +export BUILD_DIR=${DIR_ROOT}/build # 构建输出目录 +# 清理旧的构建目录并新建 if [ -d ${BUILD_DIR} ]; then rm -rf ${BUILD_DIR} fi - mkdir -p ${BUILD_DIR} -if [[ "${fronthaul_option}" == "jesd" ]]; then - export RFIC_DIR=${DIR_ROOT}/driver/rfic/rf/ - export CJSON_DIR=${DIR_ROOT}/driver/rfic/ucp/cJSON/inc/ - export RFIC_APP_DIR=${DIR_ROOT}/rfic - export BOARD_TYPE=${board_option} +# 特殊处理JESD前传接口的编译 +if [[ "${fronthaul_option}" == "jesd" ]]; then + export RFIC_DIR=${DIR_ROOT}/driver/rfic/rf/ # JESD驱动代码路径 + export CJSON_DIR=${DIR_ROOT}/driver/rfic/ucp/cJSON/inc/ # JSON库头文件路径 + export RFIC_APP_DIR=${DIR_ROOT}/rfic # RFIC应用代码路径 + export BOARD_TYPE=${board_option} # 当前板卡类型 + + # 编译JESD库和RFIC应用 echo -e "\n" - echo "###### start building libjesd.a and librfic.a and rfic.out ######" + echo "###### 开始编译JESD库和RFIC应用 ######" cd ${DIR_ROOT}/driver/rfic - #chmod +x build.sh - source ./build.sh + source ./build.sh # 执行子编译脚本 + # 将生成的库文件和头文件拷贝到指定位置 cp ${RFIC_DIR}/out/jesd/*.a ${BUILD_DIR} cp ${RFIC_DIR}/out/jesd/*.h ${DIR_ROOT}/interface - cp ${RFIC_DIR}/out/rfic/*.a ${DIR_ROOT}/lib cp ${RFIC_DIR}/out/rfic/ucp_api_rfic.h ${RFIC_APP_DIR}/inc/ cp ${CJSON_DIR}/xzJSON.h ${RFIC_APP_DIR}/inc/ - - cp ${RFIC_DIR}/out/app/*.out ${BUILD_DIR} - - #echo -e "\n" - #echo "###### start building rfic.out ######" - #cd ${RFIC_APP_DIR}/ - #make + cp ${RFIC_DIR}/out/app/*.out ${BUILD_DIR} # 拷贝可执行文件 fi +# 编译TFU驱动 cd ${DIR_ROOT}/driver/tfu source ./build.sh +# 拷贝生成的库文件和头文件 cp build/libstc.a ${DIR_ROOT}/lib cp build/libstc.a ${BUILD_DIR} cp stc/inc/stc_drv_api.h ${DIR_ROOT}/interface +# 编译主程序 echo -e "\n" -echo "###### start building msgTransfer.out and libmsgTransfer.a ######" +echo "###### 开始编译主程序和消息传输模块 ######" cd ${DIR_ROOT}/ +# 调用make命令,传入所有配置参数 make cache_option=${cache_option} fronthaul_option=${fronthaul_option} backhaul_option=${backhaul_option} test_option=${test_option} test_id=${case_id} - + +# 清理临时库文件目录 cd ${DIR_ROOT}/lib rm -rf *.* diff --git a/makefile b/makefile index d536200..64d04a8 100644 --- a/makefile +++ b/makefile @@ -1,178 +1,198 @@ #======================================================================================================== # platform makefile -#FileName: makefile -#Author: xianfeng.du -#Data: 2022-08-10 -#Description: top makefile +# FileName: makefile +# Author: xianfeng.du +# Date: 2022-08-10 +# Description: 项目管理主Makefile,控制代码编译和链接流程 #======================================================================================================== -VERSION = 1.00 +VERSION = 1.00 # 定义Makefile版本号 +#--------------------------------------------------------------------- +# 编译器配置 +#--------------------------------------------------------------------- +# 选择编译工具链(默认使用交叉编译) OPTION ?= -ifeq ($(OPTION),GCC) - CROSS_CC ?= +ifeq ($(OPTION),GCC) # 如果手动指定GCC则用本地gcc + CROSS_CC ?= # 使用系统默认gcc else -# TOOLS ?= /opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin -# CROSS_CC ?= $(TOOLS)/aarch64-linux-gnu- - CROSS_CC ?= aarch64-linux-gnu- + # 示例交叉编译工具链路径(当前注释状态) + #TOOLS ?= /opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin + #CROSS_CC ?= $(TOOLS)/aarch64-linux-gnu- + CROSS_CC ?= aarch64-linux-gnu- # 默认交叉编译工具前缀 endif -AR = ar -CC = $(CROSS_CC)gcc -#$(info "CC=" $(CC)) +AR = ar # 静态库打包工具 +CC = $(CROSS_CC)gcc # C编译器定义 +#$(info "CC=" $(CC)) # 调试信息:显示当前使用的编译器 -DEFINES ?= -#DEFINES ?= UBLOX_ENABLE +#--------------------------------------------------------------------- +# 宏定义配置 +#--------------------------------------------------------------------- +DEFINES ?= # 初始化空宏定义 +#DEFINES ?= UBLOX_ENABLE # 示例宏定义(当前注释状态) -DEFINES += ARM_VERSION=\"${arm_version}\" -DEFINES += ARM_TAG=\"${arm_tag}\" -DEFINES += ARM_BUILD_DATE=\"${arm_build_date}\" +# 通过环境变量传递的版本信息(来自shell脚本) +DEFINES += ARM_VERSION=\"${arm_version}\" # Git commit版本 +DEFINES += ARM_TAG=\"${arm_tag}\" # Git标签版本 +DEFINES += ARM_BUILD_DATE=\"${arm_build_date}\" # 构建时间 +# 前传接口条件编译 ifeq ($(fronthaul_option),jesd) - DEFINES += ENABLE_JESD_TEST + DEFINES += ENABLE_JESD_TEST # 启用JESD测试 + # PCIe与JESD的组合支持 ifeq ($(backhaul_option),pcie) DEFINES += PCIE_WITH_JESD endif endif -#optimization level -O2 -C_OPT_FLAGS ?= -O2 +#--------------------------------------------------------------------- +# 编译选项 +#--------------------------------------------------------------------- +C_OPT_FLAGS ?= -O2 # 优化级别设置为O2 -CC_FLAGS ?= $(C_OPT_FLAGS) -Wall -g -CC_FLAGS += -Werror -Wno-unused-function -CC_FLAGS += $(foreach d,$(DEFINES),-D$(d)) -CC_FLAGS += -fPIC +# 公共编译选项 +CC_FLAGS ?= $(C_OPT_FLAGS) -Wall -g # 基本选项:O2优化,显示所有警告,生成调试信息 +CC_FLAGS += -Werror -Wno-unused-function # 将警告视为错误(除未使用函数警告) +CC_FLAGS += $(foreach d,$(DEFINES),-D$(d)) # 添加所有宏定义 +CC_FLAGS += -fPIC # 生成位置无关代码(用于库文件) -LIB_DIRS ?= ./lib +LIB_DIRS ?= ./lib # 库文件搜索目录 -SRC_DIRS ?= ./app/src -SRC_DIRS += ./osp/src -SRC_DIRS += ./driver/arm_csu/src -SRC_DIRS += ./driver/init/src +#--------------------------------------------------------------------- +# 源文件配置 +#--------------------------------------------------------------------- +SRC_DIRS ?= ./app/src # 主程序源码目录 +SRC_DIRS += ./osp/src # 操作系统抽象层源码 +SRC_DIRS += ./driver/arm_csu/src # ARM CSU驱动源码 +SRC_DIRS += ./driver/init/src # 初始化模块源码 +# 头文件包含路径配置 INCLUDE_DIRS ?= ./app/inc INCLUDE_DIRS += ./osp/inc INCLUDE_DIRS += ./driver/arm_csu/inc INCLUDE_DIRS += ./driver/init/inc -INCLUDE_DIRS += ./driver/tfu/stc/inc -test ?= $(test_option) -case ?= $(test_id) +INCLUDE_DIRS += ./driver/tfu/stc/inc # TFU驱动头文件 + +# 测试用例配置(通过--test参数激活) +test ?= $(test_option) # 是否启用测试模式 +case ?= $(test_id) # 测试用例ID ifeq ($(test),yes) - DEFINES += PALLADIUM_TEST -#testbench + DEFINES += PALLADIUM_TEST # 定义测试模式宏 + + # 添加测试用例目录 CASE_ID := $(case) TEST_DIR := ./test/case$(CASE_ID) - SRC_DIRS += $(TEST_DIR)/src - INCLUDE_DIRS += $(TEST_DIR)/inc + SRC_DIRS += $(TEST_DIR)/src # 测试用例源码目录 + INCLUDE_DIRS += $(TEST_DIR)/inc # 测试用例头文件目录 endif +# 缓存功能配置(通过--cache参数激活) cache ?= $(cache_option) ifeq ($(cache),yes) - DEFINES += CACHE_ENABLE + DEFINES += CACHE_ENABLE # 开启缓存功能宏 endif -LD_FLAGS ?= -lgcc -lc -LD_FLAGS += -lm -ldl -Wl,-rpath=./ -LD_FLAGS += -lpthread -LD_FLAGS += -rdynamic -funwind-tables -ffunction-sections +#--------------------------------------------------------------------- +# 链接选项 +#--------------------------------------------------------------------- +LD_FLAGS ?= -lgcc -lc # 基础C库 +LD_FLAGS += -lm -ldl -Wl,-rpath=./ # 数学库、动态加载库、运行时路径 +LD_FLAGS += -lpthread # 线程库 +LD_FLAGS += -rdynamic -funwind-tables -ffunction-sections # 动态符号表相关 + +# 根据前传接口添加特定库 ifeq ($(fronthaul_option),jesd) -LD_FLAGS += -lrfic -lstc +LD_FLAGS += -lrfic -lstc # JESD模式需要rfic和stc库 endif -LD_FLAGS += -lstc -$(info "DEFINES=" $(DEFINES)) +LD_FLAGS += -lstc # 默认链接stc库 -#Flatten files and remove the duplicate by sort +$(info "DEFINES=" $(DEFINES)) # 打印最终的宏定义(调试用) + +#--------------------------------------------------------------------- +# 文件收集与处理 +#--------------------------------------------------------------------- +# 获取所有源码目录的绝对路径 ABS_SRC_DIRS := $(foreach d,$(SRC_DIRS),$(abspath $(d))) +# 收集所有.c文件(使用通配符匹配) SRC_FILES := $(foreach d,$(ABS_SRC_DIRS),$(wildcard $(d)/*.c)) -#main.c +# 主函数文件特殊处理 MAIN_DIR := ./app/src -MAIN_FILE := ./app/src/main.c +MAIN_FILE := ./app/src/main.c # 主程序入口文件 -# Allow certain files to be excluded from the build +# 需要排除的源文件列表(如主程序文件单独处理) EXCL_SRCS ?= $(MAIN_FILE) -#EXCL_SRCS += ./app/src/main.c +#EXCL_SRCS += ./app/src/main.c # 示例其他排除文件(当前注释状态) -# Filter source files (allow files to be excluded) +# 过滤生成最终参与编译的源文件列表 FINAL_SRCS_FILES += $(foreach f,$(SRC_FILES),$(if $(findstring $(abspath $(f)),$(abspath $(EXCL_SRCS))),,$(f))) -#$(info "FINAL_SRCS_FILES=" $(FINAL_SRCS_FILES)) +#$(info "FINAL_SRCS_FILES=" $(FINAL_SRCS_FILES)) # 调试输出最终文件列表 -# ============================================================================== -# Variables: Output Files -# ============================================================================== -BUILD_DIR := ./build -OBJ_MAIN_DIR := $(BUILD_DIR)/main -OBJ_DIR := $(BUILD_DIR)/obj -#BIN_DIR := $(BUILD_DIR)/bin -#LIB_DIR := $(BUILD_DIR)/lib -#ELF_FILE := $(BIN_DIR)/test.elf -BIN_FILE := $(BUILD_DIR)/msgtransfer.out -LIB_FILE := $(BUILD_DIR)/libmsgtransfer.a +#--------------------------------------------------------------------- +# 输出文件定义 +#--------------------------------------------------------------------- +BUILD_DIR := ./build # 构建输出根目录 +OBJ_MAIN_DIR := $(BUILD_DIR)/main # 主程序对象文件目录 +OBJ_DIR := $(BUILD_DIR)/obj # 常规对象文件目录 +BIN_FILE := $(BUILD_DIR)/msgtransfer.out # 最终生成的可执行文件 +LIB_FILE := $(BUILD_DIR)/libmsgtransfer.a # 生成的静态库文件 +# 生成对象文件路径列表(普通文件) OBJ_FILES += $(foreach f,$(FINAL_SRCS_FILES),$(OBJ_DIR)/$(patsubst %.c,%.o,$(notdir $(f)))) +# 生成主程序对象文件路径列表 OBJ_MAIN_FILES += $(foreach f,$(MAIN_FILE),$(OBJ_MAIN_DIR)/$(patsubst %.c,%.o,$(notdir $(f)))) -#ifeq ($(fronthaul_option),jesd) -#OBJ_FILES += $(wildcard $(RFIC_DIR)/*.o) -#RFIC_OBJ_DIR := $(BUILD_DIR)/rfic_obj -#RFIC_OBJ_FILES := $(wildcard $(RFIC_OBJ_DIR)/*.o) -#else -#RFIC_OBJ_FILES := -#endif - -# ============================================================================== -# Rules: Compilation -# ============================================================================== +#--------------------------------------------------------------------- +# 编译规则定义 +#--------------------------------------------------------------------- +# 定义对象文件生成规则模板 define DO_BUILD_OBJ $(2)/%.o: $(1)/%.c | $(2) - @echo "# Compiling $$< -> $$@" - $(CC) $(CC_FLAGS) -o $$@ -c $$< $(patsubst %,-I %,$(INCLUDE_DIRS)) -#OBJ_TGTS += $(foreach f,$(wildcard $(1)/*.c),$(OBJ_DIR)/$(notdir $(basename $(1)))/$(patsubst %.c,%.o,$(notdir $(f)))) + @echo "# 正在编译 $$< -> $$@" # 显示编译进度 + $(CC) $(CC_FLAGS) -o $$@ -c $$< $(patsubst %,-I %,$(INCLUDE_DIRS)) # 编译命令 endef +# 定义目录创建规则模板 define DO_BUILD_DIR $(1): - @echo "# Creating directory $$@" + @echo "# 创建目录 $$@" mkdir -p $$@ endef +# 组合构建规则:创建目录 + 编译源文件 define DO_BUILD - $(eval $(call DO_BUILD_DIR,$(1))) - $(foreach d,$(sort $(2)),$(eval $(call DO_BUILD_OBJ,$(d),$(1)))) + $(eval $(call DO_BUILD_DIR,$(1))) # 先创建目录 + $(foreach d,$(sort $(2)),$(eval $(call DO_BUILD_OBJ,$(d),$(1)))) # 遍历编译每个目录 endef +# 应用构建规则到常规对象目录和主程序对象目录 $(eval $(call DO_BUILD,$(OBJ_DIR),$(ABS_SRC_DIRS))) $(eval $(call DO_BUILD,$(OBJ_MAIN_DIR), $(abspath $(MAIN_DIR)))) +# 可执行文件链接规则 $(BIN_FILE):$(OBJ_FILES) $(OBJ_MAIN_FILES) -# @echo "# Creating bin directory $(BIN_DIR)" -# mkdir -p $(BIN_DIR) - - @echo "# Linking objects to form $@" - $(CC) -o $@ $^ $(LD_FLAGS) $(patsubst %,-L %,$(LIB_DIRS)) -# $(CC) -o $@ $^ $(LD_FLAGS) -T$(LINK_FILE) + @echo "# 正在链接对象文件生成 $@" + $(CC) -o $@ $^ $(LD_FLAGS) $(patsubst %,-L %,$(LIB_DIRS)) # 链接所有对象文件 -#$(LIB_FILE):$(OBJ_FILES) $(RFIC_OBJ_FILES) +# 静态库生成规则 $(LIB_FILE):$(OBJ_FILES) -# @echo "# Creating lib directory $(LIB_DIR)" -# mkdir -p $(LIB_DIR) + @echo "# 正在生成静态库 $@" + $(AR) -rcs $@ $^ # 使用ar工具打包对象文件 + +#--------------------------------------------------------------------- +# 目标规则 +#--------------------------------------------------------------------- +.DEFAULT_GOAL := all # 默认目标为all +.PHONY: build lib clean # 声明伪目标 + +all: build lib # 默认目标:同时构建可执行文件和库 + +build: $(BIN_FILE) # 构建可执行文件 - @echo "# Linking objects to form $@" - $(AR) -rcs $@ $^ -# $(CC) -shared -o $@ $^ $(LD_FLAGS) +lib: $(LIB_FILE) # 构建静态库 -# ============================================================================== -# Rules: Targets -# ============================================================================== -.DEFAULT_GOAL := all -.PHONY: build lib clean -all: build lib - -build: $(BIN_FILE) - -lib: $(LIB_FILE) - -clean: - @echo "deleted all files" +clean: # 清理构建产物 + @echo "正在删除所有构建文件..." rm -rf $(BUILD_DIR)