为何SafeRTOS项目MakeFile适配HighTec make.exe却不兼容MinGW make.exe
项目结构
SafeRTOS_VNP_RDB2_MakeFile\ -> board\ -> Common\ -> generate\ -> include\ -> Project_Settings\ -> RTD\ -> SafeRTOS\ -> src\ -> SW32_RTD_4_4_3_0_2_D2203\ -> Makefile -> (Debug_RAM - 存放.o文件的目录)
此前在Eclipse中使用该Makefile构建SafeRTOS项目完全正常,更换新电脑后安装MinGW的make.exe,无法完成编译。无论在Eclipse还是命令行执行构建,均报错提示"系统找不到指定路径",构建终止。
已确认新旧电脑上gcc工具路径均正确,但脚本中的make version目标执行结果异常:旧电脑使用HighTec IDE的make.exe执行可输出环境信息,新电脑用MinGW的make.exe执行仅输出Windows版本信息,即使简化version目标仅打印字符串,结果仍不变。
现提出两个疑问:
- 不同工具链的
make.exe是否存在显著差异? - 我的Makefile是否存在HighTec的
make.exe未检测到/忽略的错误?若有,具体是什么?
附完整Makefile代码
ifdef COMSPEC SHELL := ${COMSPEC} else ifdef ComSpec SHELL := ${ComSpec} else SHELL := cmd.exe endif # NOTE: Set TOOLCHAIN_ROOT to reflect the path to the desired cross compiler. # This may be set here, or by defining an environment variable TOOLCHAIN_ROOT. ifndef TOOLCHAIN_ROOT TOOLCHAIN_ROOT := C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10 endif ifndef NXP_S32DS_INSTALL_PATH NXP_S32DS_INSTALL_PATH := C:\nxp\S32DS.3.5\eclipse\../ endif CROSS_COMPILE := arm-none-eabi- OBJDIR := Debug_RAM APPNAME := SafeRTOS_VNP_RDB2_MakeFile CC := "${TOOLCHAIN_ROOT}/bin/"${CROSS_COMPILE}gcc AS := "${TOOLCHAIN_ROOT}/bin/"${CROSS_COMPILE}as LD := "${TOOLCHAIN_ROOT}/bin/"${CROSS_COMPILE}gcc SIZE := "${TOOLCHAIN_ROOT}/bin/"${CROSS_COMPILE}size OBJCOPY := "${TOOLCHAIN_ROOT}/bin/"${CROSS_COMPILE}objcopy RM := rm -rf # Processor options. ARCH_FLAGS = -mcpu=cortex-m7 -mthumb -mlittle-endian -mfloat-abi=hard -mfpu=fpv5-sp-d16 C_FLAGS := -Wall -Wno-unknown-pragmas -Wextra -c -fno-short-enums -funsigned-bitfields -fno-common -Wunused -Wstrict-prototypes -Wsign-compare -Werror=implicit-function-declaration -Wundef -Wdouble-promotion C_FLAGS += -O0 -funsigned-char -fstack-usage -fdump-ipa-all -fomit-frame-pointer -g3 -ggdb3 -pedantic ${ARCH_FLAGS} C_FLAGS += -specs=nano.specs -specs=nosys.specs --sysroot="${NXP_S32DS_INSTALL_PATH}S32DS/build_tools/gcc_v9.2/gcc-9.2-arm32-eabi/arm-none-eabi/newlib" ASM_FLAGS := -c -x assembler-with-cpp -g3 ASM_FLAGS += $(ARCH_FLAGS) ASM_FLAGS += -specs=nano.specs -specs=nosys.specs --sysroot="${NXP_S32DS_INSTALL_PATH}S32DS/build_tools/gcc_v9.2/gcc-9.2-arm32-eabi/arm-none-eabi/newlib" LD_FLAGS := -nostartfiles --entry=Reset_Handler -ggdb3 # LD_FLAGS += -T "./Project_Settings/Linker_Files/linker_ram.ld" LD_FLAGS += -Wl,-Map,"${APPNAME}.map" LD_FLAGS += $(ARCH_FLAGS) LD_FLAGS += -specs=nano.specs -specs=nosys.specs --sysroot="${NXP_S32DS_INSTALL_PATH}S32DS/build_tools/gcc_v9.2/gcc-9.2-arm32-eabi/arm-none-eabi/newlib" default: all version: @echo ${TOOLCHAIN_ROOT} @echo ${CROSS_COMPILE} @echo ${SHELL} @echo ${PATH} @echo ==================================== @echo Running compiler to check version: $(COMPILER) --version # this throws away any error message for if the directory already exists $(OBJDIR): -mkdir $(OBJDIR) 2> NUL SAFERTOS_SUBDIRS = \ ./SafeRTOS/kernel \ ./SafeRTOS/api/252_ARMv7M_MPU \ ./SafeRTOS/api/PrivWrapperStd \ ./SafeRTOS/portable/252_ARMv7M_MPU \ ./SafeRTOS/portable/252_ARMv7M_MPU/003_GCC \ SAFERTOS_INCLUDE_PATH := \ -I"SafeRTOS/api/252_ARMv7M_MPU" \ -I"SafeRTOS/api/PrivWrapperStd" \ -I"SafeRTOS/config" \ -I"SafeRTOS/kernel/include_api" \ -I"SafeRTOS/kernel/include_prv" \ -I"SafeRTOS/portable/252_ARMv7M_MPU" \ -I"SafeRTOS/portable/252_ARMv7M_MPU/003_GCC" \ SAFERTOS_CSRCS = $(foreach dir, $(SAFERTOS_SUBDIRS), $(wildcard $(dir)/*.c)) SAFERTOS_SSRCS = $(foreach dir, $(SAFERTOS_SUBDIRS), $(wildcard $(dir)/*.s)) DEMO_SUBDIRS = \ ./Project_Settings/Startup_Code \ ./RTD/src \ ./board \ ./generate/src \ ./src \ ./Common \ DEMO_INCLUDE_PATH = \ -I"Common/include" \ -I"include" \ -I"RTD/include" \ -I"generate/include" \ -I"board" \ -I"Common/include" \ -I"include" \ -I"SW32_RTD_4_4_3_0_2_D2203/Base_TS_T40D11M30I2R0/header" \ -I"SW32_RTD_4_4_3_0_2_D2203/Base_TS_T40D11M30I2R0/include" \ -I"SW32_RTD_4_4_3_0_2_D2203/Platform_TS_T40D11M30I2R0/startup/include" \ DEMO_SRCS = $(foreach dir, $(DEMO_SUBDIRS), $(wildcard $(dir)/*.c)) EXCLUDES := \ ./Common/comtest.c \ ./src/serial.c \ CSRC := $(filter-out $(EXCLUDES),$(DEMO_SRCS)) DEMO_DEFINES += -DUSE_SW_VECTOR_MODE -DD_CACHE_ENABLE -DI_CACHE_ENABLE -DENABLE_FPU -DMPU_ENABLE -DGCC -DCPU_S32G274A -DS32G2XX -DCPU_CORTEX_M7 THIRD_PARTY_SUBDIRS = THIRD_PARTY_INCLUDE_PATH = THIRD_PARTY_DEFINES = THIRD_PARTY_SRCS = $(foreach dir, $(THIRD_PARTY_SUBDIRS), $(wildcard $(dir)/*.c)) S_SRCS = \ /Project_Settings/Startup_Code/startup_cm7.s \ /Project_Settings/Startup_Code/Vector_Table.s \ LINKER_SCRIPT := ./Project_Settings/Linker_Files/linker_ram.ld C_SRCS = $(CSRC) $(SAFERTOS_CSRCS) $(THIRD_PARTY_SRCS) S_SRCS += $(SAFERTOS_SSRCS) VPATH = $(DEMO_SUBDIRS) $(SAFERTOS_SUBDIRS) $(THIRD_PARTY_SUBDIRS) OBJ_NAMES = $(notdir $(C_SRCS)) OBJS = $(addprefix $(OBJDIR)/,$(OBJ_NAMES:%.c=%.o)) SOBJ_NAMES = $(notdir $(S_SRCS:%.S=%.s)) OBJS += $(addprefix $(OBJDIR)/,$(SOBJ_NAMES:%.s=%.o)) C_DEPS = $(OBJS:%.o=%.d) DEFINES = $(DEMO_DEFINES) $(THIRD_PARTY_DEFINES) INCLUDES = $(SAFERTOS_INCLUDE_PATH) $(DEMO_INCLUDE_PATH) $(THIRD_PARTY_INCLUDE_PATH) ifneq ($(MAKECMDGOALS),clean) -include $(C_DEPS) endif $(OBJDIR)/%.o: %.s @echo 'Building file: $<' @echo 'Invoking: ${CC}' $(CC) $(ASM_FLAGS) $(INCLUDES) $(DEFINES) -o"$@" -c "$<" @echo 'Finished building: $<' @echo ' ' $(OBJDIR)/%.o: %.c @echo 'Building file: $<' @echo 'Invoking: ${CC}' $(CC) $(C_FLAGS) $(INCLUDES) $(DEFINES) -MMD -MP -MF"$(@:%.o=%.d)" -c -o"$@" "$<" @echo 'Finished building: $<' @echo ' ' EXECUTABLES += \ ${APPNAME}.elf \ # All Target all: $(EXECUTABLES) secondary-outputs # Tool invocations ${APPNAME}.elf: $(OBJDIR) $(OBJS) ${LINKER_SCRIPT} Makefile @echo 'Building target: $@' $(LD) -Bstatic $(LD_FLAGS) \ -T ${LINKER_SCRIPT} \ -Wl,-Map="${APPNAME}.map" \ $(OBJS) \ -o ${APPNAME}.elf @echo 'Finished building target: $@' @echo ' ' $(MAKE) --no-print-directory post-build ${OBJCOPY} -O binary ${APPNAME}.elf ${APPNAME}.bin # Other Targets clean: $(RM) $(C_DEPS) $(EXECUTABLES) "${APPNAME}.map" "${APPNAME}.bin" $(RM) $(OBJDIR) post-build: $(SIZE) "${APPNAME}.elf" @echo ' ' secondary-outputs: .PHONY: all clean dependents version .SECONDARY: post-build
1. 不同工具链的make.exe是否存在显著差异?
是,存在明显差异:
- HighTec的make:属于嵌入式开发工具链的一部分,基于GNU Make做了Windows环境适配,对路径处理、shell兼容性有特殊优化,甚至内置了嵌入式项目的扩展规则,容错性更强。
- MinGW的make:是标准GNU Make的Windows移植版,严格遵循POSIX规范,对Windows下的路径、shell命令解析更贴近原生POSIX行为,没有针对嵌入式场景的特殊兼容处理。
两者核心功能一致,但在Windows环境的细节处理(路径分隔符、shell命令执行、环境变量解析)上差异明显,这是项目迁移后报错的核心原因。
2. Makefile中存在的问题(HighTec忽略但MinGW报错)
你的Makefile有多个不符合严格规范的问题,HighTec的make做了兼容,但MinGW的make会触发错误:
(1) 未定义COMPILER变量
version目标中调用$(COMPILER) --version,但整个Makefile从未定义该变量。MinGW make会将其视为空值,执行命令变为--version,这在Windows cmd下会调用系统ver命令(输出Windows版本),与你描述的异常现象完全匹配。
修复:添加COMPILER := $(CC),或直接将$(COMPILER)替换为已定义的$(CC)。
(2) 启动文件路径错误
S_SRCS中的启动文件使用了绝对路径前缀/Project_Settings/...,Windows下会被解析为磁盘根目录下的路径(如C:\Project_Settings\...),而非项目目录下的相对路径,导致编译时找不到文件,触发"系统找不到指定路径"错误。
修复:改为相对路径:
S_SRCS = \ ./Project_Settings/Startup_Code/startup_cm7.s \ ./Project_Settings/Startup_Code/Vector_Table.s \
(3) Shell命令兼容性问题
RM := rm -rf:MinGW的rm是POSIX工具,若MinGW的bin目录未加入系统PATH,cmd会找不到该命令。建议替换为Windows原生命令:RM := rd /s /q。mkdir $(OBJDIR) 2> NUL:虽然你指定了SHELL := cmd.exe,但MinGW make对cmd语法的兼容可能存在歧义,可保留但需确保PATH中没有其他冲突的mkdir工具。
(4) 路径解析歧义
NXP_S32DS_INSTALL_PATH := C:\nxp\S32DS.3.5\eclipse\../中的../可能导致MinGW make解析路径出错,建议简化为明确路径:C:\nxp\S32DS.3.5\。
关键修复步骤总结
- 补充
COMPILER变量定义:COMPILER := $(CC) - 修正启动文件路径为相对路径
- 替换
RM命令为Windows原生命令 - 简化
NXP_S32DS_INSTALL_PATH路径为明确值
内容的提问来源于stack exchange,提问作者jonny123

