NOTE此篇文章由VSCodearm-none-eabi-gcc交叉编译Makefile构建OpenOCD基于STM32标准库的保姆级教程派生而来对makefile脚本需要修改的地方作补充说明。一些修改说明①TARGETF401CCU6_demo修改生成的xxx.elf、xxx.hex、xxx.bin、xxx.map文件名称。例如上述的F401CCU6_demo会在build文件夹中生成②# 编译优化等级的选项# -O0无任何优化# -O11级优化,# -O2: 2级优化,# -Os: 2.5级优化,# -O3: 最高级优化。# -Og优化调试体验。 -Og启用不会干扰调试的优化。 它是标准编辑 - 编译 - 调试周期可以选择的优化级别提供合理的优化级别同时保持快速编译和良好的调试体验。# -g -gdwarf-2是调试选项其中-g表示在生成的文件中添加调试信息-gdwarf-2表示调试信息的格式为DWARF版本号为2。调试信息将在对应的GDB(比如arm-none-eabi-gdb)中使用。# LTOLink Time Optimization即链接时优化。ifeq($(DEBUG),1)# Debug 模式CFLAGS 和 LDFLAGS 都不开 LTO保证调试体验CFLAGS-Og-g-gdwarf-2 -fno-lto ASFLAGS-Og-g-gdwarf-2 LTO_FLAG-fno-ltoelse# Release 模式CFLAGS 和 LDFLAGS 同时开 LTO最强优化压缩代码体积CFLAGS-O2-fltoASFLAGS-O2LTO_FLAG-fltoendif代码优化等级更改。嵌入式领域中在正式发行代码版本时会严格区分Release和Debug版本Debug版本一般用于开发人员内部开发调试Release版本一般发布给外部的市场客户此时的Release版本代码往往就会设置代码优化等级目的是为了将MCU的RAM和Flash资源利用最大化以及优化客户体验Tips代码优化过后可能会出现一些玄学一样的bug③CPU-mcpucortex-m4 FPU-mfpufpv4-sp-d16 FLOAT_ABI-mfloat-abihard THUMB-mthumb-mthumb-interwork MCU$(CPU)$(FPU)$(FLOAT_ABI)$(THUMB)编译选项参数设置需要根据不同MCU型号修改④C_DEFS\-DUSE_STDPERIPH_DRIVER\-DSTM32F401xx宏定义展开设置需要根据不同MCU型号修改⑤C_SOURCES\$(wildcard ./CMSIS/Source/*.c)\$(wildcard ./Core/Src/*.c)\$(wildcard ./STM32F4xx_StdPeriph_Driver/src/*.c)\$(wildcard ./User/Src/*.c)使用通配符 wildcard 匹配文件夹下的所有源文件。修改为你工程目录中需要参与编译的源文件路径。⑥ASM_SOURCES$(wildcard ./startup_s/*.s)使用通配符 wildcard 匹配文件夹下的MCU汇编启动文件。修改为你工程目录中需要参与编译的启动文件路径。⑦C_INCLUDES\-ICore/Inc\-ICMSIS/Include\-ISTM32F4xx_StdPeriph_Driver/inc\-IUser/Inc匹配文件夹下的所有头文件。修改为你工程目录中需要参与编译的头文件路径。⑧LDSCRIPT./link_script/STM32F401CCUx_FLASH.ld匹配文件夹下的MCU链接脚本。修改为你工程目录中参与链接的链接脚本路径。Makefile脚本内容########################################################################################################################### File automatically-generated by tool: [projectgenerator] version: [4.2.0-B44] date: [Fri Jul 05 19:24:39 CST 2024]########################################################################################################################### Generic Makefile (based on gcc)#SHELLcmd# 顶层路径#TOPDIR : $(SHELL)#export TOPDIR####################################### target-------编译生成目标烧写软件的名称######################################TARGETF401CCU6_demo####################################### building variables####################################### debug build# /*# 编译选项是否debug模式如果DEBUG1,则可以后续使用调试软件gdb等工具进行在线调试# 如果DEBUG0,则不能支持在线调试# 且DEBUG1,生成的文件比DEBUG0大因为里面包含了调试信息。# */DEBUG1######################################## paths######################################## Build path# /*# 编译路径 生成的编译文件保存在build文件夹中# 这样做的好处是工程框架比较清晰且清除编译文件比较简单。# */BUILD_DIRbuild####################################### source-------工程所有需要编译的C文件 指定需要编译的C文件名称相对路径######################################C_SOURCES\$(wildcard ./CMSIS/Source/*.c)\$(wildcard ./Core/Src/*.c)\$(wildcard ./STM32F4xx_StdPeriph_Driver/src/*.c)\$(wildcard ./User/Src/*.c)# 工程所有需要编译的汇编文件 指定需要编译的汇编文件名称相对路径# ASM_SOURCES # ASM_SOURCES $(wildcard ./startup_s/*.s)ASM_SOURCES$(wildcard ./startup_s/*.s)# ASM sourcesASMM_SOURCES######################################## binaries######################################## /*# 工程使用编译的类型 arm-none-eabi-是基于arm芯片开发的编译器# none表示无操作系统eabi表示交叉编译器即在linux上编译嵌入式arm芯片的代码# 生成可烧写文件。# */PREFIXarm-none-eabi-# The gcc compiler bin path can be either defined in make command via GCC_PATH variable ( make GCC_PATHxxx)# either it can be added to the PATH environment variable.# /*# 编译器路径宏表示arm-none-eabi-gcc在linux中调用是否需要带路径# 一般情况安装好arm-none-eabi-gcc后系统将安装的可执行程序路径放在了系统的环境变量中# 无需要路径即可执行所以GCC_PATH不用宏定义。# */ifdef GCC_PATH#如果定义了GCC_PATH的本地路径则进行本地索引编译CC$(GCC_PATH)/$(PREFIX)gcc AS$(GCC_PATH)/$(PREFIX)gcc-xassembler-with-cpp CP$(GCC_PATH)/$(PREFIX)objcopy SZ$(GCC_PATH)/$(PREFIX)sizeelse# 否则索引环境变量的路径编译CC$(PREFIX)gcc AS$(PREFIX)gcc-xassembler-with-cpp CP$(PREFIX)objcopy SZ$(PREFIX)size endif HEX$(CP)-Oihex BIN$(CP)-Obinary-S# cpu# 编译选型CPU类型STM32芯片的内核是cortex-m4指定该内核对应的寄存器库CPU-mcpucortex-m4# fpu# 编译选型FPU浮点计算器STM32支持浮点运算FPU-mfpufpv4-sp-d16# float-abi# 编译选型浮点计算类型设定硬件浮点运算还可选型纯软件浮点计算或者结合形式FLOAT_ABI-mfloat-abihard THUMB-mthumb-mthumb-interwork# MCU编译选项M4内核支持浮点运算浮点计算采用硬件浮点计算器指定生成thumb精简指令集【默认不开启允许编译器进行ARM指令和Thumb指令的相互调用】MCU$(CPU)$(FPU)$(FLOAT_ABI)$(THUMB)# macros for gcc# AS defines# 汇编编译宏定义该Makefile宏定义将在汇编代码中有效AS_DEFS# C defines# C文件编译宏定义该Makefile宏定义将在C代码中有效C_DEFS\-DUSE_STDPERIPH_DRIVER\-DSTM32F401xx# AS includes----------汇编头文件路径编译过程中文件内的头文件搜索路径AS_INCLUDES# C includes--------C文件的头文件路径编译过程中文件内的头文件搜索路径C_INCLUDES\-ICore/Inc\-ICMSIS/Include\-ISTM32F4xx_StdPeriph_Driver/inc\-IUser/Inc# compile gcc flags# 汇编编译选型s汇编文件编译成Obj文件需要的设置选项ASFLAGS$(MCU)$(AS_DEFS)$(AS_INCLUDES)-Wall-fdata-sections -ffunction-sections -fno-common -fmessage-length0# C编译选型C文件编译成Obj文件需要的设置选项CFLAGS$(MCU)$(C_DEFS)$(C_INCLUDES)-Wall-fdata-sections -ffunction-sections -fno-common -fmessage-length0# 编译优化等级的选项# -O0无任何优化# -O11级优化,# -O2: 2级优化,# -Os: 2.5级优化,# -O3: 最高级优化。# -Og优化调试体验。 -Og启用不会干扰调试的优化。 它是标准编辑 - 编译 - 调试周期可以选择的优化级别提供合理的优化级别同时保持快速编译和良好的调试体验。# -g -gdwarf-2是调试选项其中-g表示在生成的文件中添加调试信息-gdwarf-2表示调试信息的格式为DWARF版本号为2。调试信息将在对应的GDB(比如arm-none-eabi-gdb)中使用。# LTOLink Time Optimization即链接时优化。ifeq($(DEBUG),1)# Debug 模式CFLAGS 和 LDFLAGS 都不开 LTO保证调试体验CFLAGS-Og-g-gdwarf-2 -fno-lto ASFLAGS-Og-g-gdwarf-2 LTO_FLAG-fno-ltoelse# Release 模式CFLAGS 和 LDFLAGS 同时开 LTO最强优化压缩代码体积CFLAGS-O2-fltoASFLAGS-O2LTO_FLAG-fltoendif# Generate dependency information# /*# C文件自动依赖关系 -MMD -MP -MF$(:%.o%.d)# 自动生成.d文件里面保存了对应的源文件C代码中包含的非标准库的头文件路径和名称# 生成.d文件的目的是产生C文件生成obj的依赖文件# 当关联的头文件发生变化时触发make重新生成obj文件。# -MMD等同于-MM -MF-MM表示依赖的头文件不包括标准头文件夹-M则是所有头文件# -MF生成依赖文件。# */CFLAGS-MMD-MP-MF$(:%.o%.d)######################################## LDFLAGS######################################## link script# /*# 可执行文件链接脚本 STM32F401CCUx_FLASH.ld# 文件中详细给出了芯片的RAM和ROM片区分类区间与大小# 代码、全局变量、常数、堆栈等的分配区间。# */# LDSCRIPT STM32F103VETx_FLASH.ldLDSCRIPT./link_script/STM32F401CCUx_FLASH.ld# libraries# 编译选型 依赖的标准库# -lc链接嵌入式标准C库(newlib)-lm链接libm库(数学函数库)-lnosys告诉arm-gcc编译器没有操作系统并提供 空 实现的系统函数(_read, _write, _exit…)LIBS-lc-lm-lnosys# 编译选型 依赖的指定路径库.a库文件window中的lib文件需要转换成.a文件才能识别LIBDIR# 链接工具的总选项# MCU 芯片类型# -u _printf_float显式启用浮点数打印。-u _scanf_float显式启用浮点数输入。# specsSpecifying Subprocesses缩写子进程。# -specsnano.specs链接精简版C库nano.specs将-lc替换成-lc_nano即 用精简微型C库newlib-nano替代嵌入式标准C库newlib减少.elf体量。含有-lc功能。# -specsnosys.specs告诉arm-gcc编译器没有操作系统。含有-lnosys功能。# -T 依赖的可执行文件链接脚本。# $(LIBS) 嵌入式标准C库文件 $(LIBDIR) 指定路径的库文件。# -Wl,--gc-sections 链接使用的分段方式需要配合C文件/汇编生成obj的时候同样选型分段方式好处是链接的时候源文件中的未使用变量和未调用# 函数将不会被链接到elf文件中最终可执行文件elf会很精简。# --no-warn-rwx-segments消除 LOAD segment with RWX permissions 警告# --warn-common: 输出警告——全局变量重复定义问题# -Wl,-Map$(BUILD_DIR)/$(TARGET).map生成map文件# --cref开启后给 map 文件增加「符号交叉引用表」# --print-memory-usage选项提供链接器文件中定义的每个内存区域使用的内存的详细信息LDFLAGS\$(MCU)\-u_printf_float\-u_scanf_float\-specsnano.specs\-specsnosys.specs\-T$(LDSCRIPT)\$(LIBDIR)\$(LIBS)\$(LTO_FLAG)\-Wl,--gc-sections,--no-warn-rwx-segments,--warn-common\-Wl,-Map$(BUILD_DIR)/$(TARGET).map,--cref,--print-memory-usage# default action: build all# Makefile总目标 这是伪目标在第一依赖关系位置输入make指令时必定执行该目标# 可执行文件elf , hex 和 bin 是arm的常用烧写文件all: version makefile_shell$(BUILD_DIR)/$(TARGET).elf$(BUILD_DIR)/$(TARGET).hex$(BUILD_DIR)/$(TARGET).bin# 终端输出make使用的SHELL类型makefile_shell: echomakeshell$(SHELL)# 在正式编译前输出 gcc 版本信息。version:$(CC)--version######################################## build the application######################################## list of objectsOBJECTS$(addprefix$(BUILD_DIR)/,$(notdir$(C_SOURCES:.c.o)))vpath %.c$(sort$(dir$(C_SOURCES)))# /*# 指定C文件的搜索路径 $(sort $(dir $(C_SOURCES)))# $(dir $(C_SOURCES))所有源文件只保留文件路径# sort对所有路径排序 ‘d g a’ - a d g# */# list of ASM program objectsOBJECTS$(addprefix$(BUILD_DIR)/,$(notdir$(ASM_SOURCES:.s.o)))vpath %.s$(sort$(dir$(ASM_SOURCES)))OBJECTS$(addprefix$(BUILD_DIR)/,$(notdir$(ASMM_SOURCES:.S.o)))vpath %.S$(sort$(dir$(ASMM_SOURCES)))# # /*# # 通配符%指定所有c文件编译成OBJ文件# # $(BUILD_DIR)/%.o 生成OBJ文件的路径固定不变在BUILD_DIR文件夹# # %.c依赖源文件C文件地址未指定Makefile将在本地目录和vpath %c目录下搜索源文件# # Makefile Makefile文件自己也是生成obj文件的依赖文件Makefile文件变化时会重新编译# # | $(BUILD_DIR) 竖线左边的依赖文件是正常依赖文件竖线右边的依赖文件是命令提前的依赖文件即BUILD_DIR会自动执行编译生成OBJ前生成build文件夹。# # -Wa,-a,-ad,-alms$(BUILD_DIR)/$(notdir $(:.c.lst))生成临时中间文件# # -c仅编译不链接 $第一个依赖文件即C文件 $ 目标文件# # */# $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)# $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms$(BUILD_DIR)/$(notdir $(:.c.lst)) $ -o $# # /*# # 通配符%指定所有汇编文件编译成OBJ文件# # $(BUILD_DIR)/%.o 生成OBJ文件的路径固定不变在BUILD_DIR文件夹# # %.c依赖源文件C文件地址未指定Makefile将在本地目录和vpath %c目录下搜索源文件# # Makefile Makefile文件自己也是生成obj文件的依赖文件Makefile文件变化时会重新编译# # | $(BUILD_DIR) 竖线坐标的依赖文件是正常依赖文件竖线右边的依赖文件是命令提前的依赖文件# # -c仅编译不链接 $第一个依赖文件即C文件 $ 目标文件# # */# $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)# $(AS) -c $(CFLAGS) $ -o $# $(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)# $(AS) -c $(CFLAGS) $ -o $# # 生成可执行文件ELF文件依赖于所有OBJ文件# $(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile# $(CC) $(OBJECTS) $(LDFLAGS) -o $# $(SZ) $# # 生成HEX文件依赖于elf文件和build文件夹# $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)# $(HEX) $ $# # 生成BIN文件依赖于elf文件和build文件夹# $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)# $(BIN) $ $# # 生成build文件夹伪指令# # 通过上面的优先依赖关系生成# $(BUILD_DIR):# mkdir $OBJ_DIRobj$(BUILD_DIR)/%.o: %.c Makefile|$(BUILD_DIR)$(CC)-c$(CFLAGS)-Wa,-a,-ad,-alms$(BUILD_DIR)/$(notdir$(:.c.lst))$-o$echo$(notdir$(:.c.o))$(BUILD_DIR)/%.o: %.s Makefile|$(BUILD_DIR)$(AS)-c$(ASFLAGS)$-o$echo$(notdir$(:.s.o))$(BUILD_DIR)/%.o: %.S Makefile|$(BUILD_DIR)$(AS)-c$(ASFLAGS)$-o$echo$(notdir$(:.S.o))$(BUILD_DIR)/$(TARGET).elf:$(OBJECTS)Makefile $(CC)$(OBJECTS)$(LDFLAGS)-o$echo linking...$(SZ)$rm-fR$(BUILD_DIR)/$(OBJ_DIR)mkdir$(BUILD_DIR)/$(OBJ_DIR)$(BUILD_DIR)/%.hex:$(BUILD_DIR)/%.elf|$(BUILD_DIR)$(HEX)$$$(BUILD_DIR)/%.bin:$(BUILD_DIR)/%.elf|$(BUILD_DIR)$(BIN)$$mv-f$(BUILD_DIR)/*.o$(BUILD_DIR)/$(OBJ_DIR)/mv-f$(BUILD_DIR)/*.d$(BUILD_DIR)/$(OBJ_DIR)/mv-f$(BUILD_DIR)/*.lst$(BUILD_DIR)/$(OBJ_DIR)/$(BUILD_DIR):mkdir$######################################## clean up######################################## /* 清除编译结果将build文件中所有文件和子文件夹删除。*/clean:# Linux下的makefile语法请使用xpack-windows-build-tools二进制发行工具包中的make.exe(GNU Make)rm-fR./$(BUILD_DIR)/*# Window CMD终端的语法请反注释本makefile脚本顶部的 SHELLcmd 虽然这样同样可以清除build目录但是会导致构建工程失败暂未找到原因# rmdir /q /s $(BUILD_DIR)######################################## dependencies######################################## 添加所有.d依赖文件-include$(wildcard$(BUILD_DIR)/*.d)# *** EOF ***参考链接STM32 Makefile的设置和工程管理使用GCC编译STM32工程(GCC)STM32CubeMX生成的Makefile详解arm gcc编译选项M4内核的FPU/DSP使用总结STM32 HAL库 CUBEMX FPU 和 DSP库 使用GCC编译器的常用参数及用法你都清楚吗GCC Arm 12.2编译提示 LOAD segment with RWX permissions 警告STM32CubeMX 生成的 Makefile 文件解析