Windows下Make执行最终链接时崩溃,第二次运行正常
在Windows 10 MSYS2环境下Makefile首次构建崩溃、二次构建正常的问题
现象
- 首次执行
make all时,所有目标文件编译完成,但在生成静态库的链接步骤前make程序崩溃,报错如下:
Finished prerequisites of target file 'lib/espeak_mini.lib'. Must remake target 'lib/espeak_mini.lib'. Unhandled exception filter called from program make ExceptionCode = c0000005 ExceptionFlags = 0 ExceptionAddress = 0x00007FFF80E6F398 Access violation: write operation at address 0x0000000102ADDB4F
- 二次执行
make all时,构建可正常完成;执行make clean后重新尝试,仍会出现「首次崩溃、二次正常」的循环现象。
涉及的Makefile内容
CC = clang WARNINGS = -Wno-attributes -Wno-deprecated-declarations -Wno-pointer-sign -Wno-int-conversion CFLAGS = -Iinclude -fvisibility=hidden -fno-exceptions -fwrapv $(WARNINGS) # Set platform specific flags ifdef OS RM = del /Q LIB_EXT = .lib EXEC_EXT = .exe FixPath = $(subst /,\,$1) else RM = rm -f LIB_EXT = .a EXEC_EXT = FixPath = $1 endif # Define targets LIB_OUT = espeak_mini$(LIB_EXT) OBJ_DIR = obj LIB_DIR = lib # UCD sources _UCD = ucd/case.o ucd/categories.o ucd/ctype.o ucd/proplist.o ucd/scripts.o ucd/tostring.o UCD = $(patsubst %,$(OBJ_DIR)/%,$(_UCD)) # Espeak sources _OBJ = common.o mnemonics.o error.o ieee80.o compiledata.o compiledict.o dictionary.o encoding.o intonation.o langopts.o numbers.o phoneme.o phonemelist.o readclause.o setlengths.o soundicon.o spect.o ssml.o synthdata.o synthesize.o tr_languages.o translate.o translateword.o voices.o wavegen.o speech.o espeak_api.o OBJ = $(patsubst %,$(OBJ_DIR)/%,$(_OBJ)) # Obj compilation rule $(OBJ_DIR)/%.o: src/%.c $(CC) -c -o $@ $< $(CFLAGS) # Clean up rule clean: $(RM) $(call FixPath, $(OBJ_DIR)/*.o $(OBJ_DIR)/ucd/*.o $(OBJ_DIR)/*.d $(OBJ_DIR)/ucd/*.d $(LIB_DIR)/espeak_mini.* example/example$(EXEC_EXT)) # Compiles the static library all: $(LIB_DIR)/$(LIB_OUT) example/example$(EXEC_EXT) $(LIB_DIR)/$(LIB_OUT): $(OBJ) $(UCD) ar rcs -o $@ $^ # Build the example project example/example$(EXEC_EXT): example/example.c $(LIB_DIR)/$(LIB_OUT) $(CC) -o $@ $< -Iinclude -L$(LIB_DIR) -lespeak_mini
修复方案
1. 提前创建必要目录
首次构建时lib、obj/ucd目录可能不存在,导致make处理路径时触发异常。在Makefile开头添加目录创建逻辑:
# 预创建目标目录 $(shell mkdir -p $(OBJ_DIR)/ucd $(LIB_DIR))
或者新增dirs目标作为all的前置依赖:
dirs: mkdir -p $(OBJ_DIR)/ucd $(LIB_DIR) all: dirs $(LIB_DIR)/$(LIB_OUT) example/example$(EXEC_EXT)
2. 切换MSYS2的make版本
MSYS2默认的make可能存在兼容性问题,替换为mingw-w64版本的make:
- 安装:
pacman -S mingw-w64-x86_64-make - 执行构建时用
mingw32-make all替代make all
3. 调整路径处理逻辑
Windows下的路径转义可能触发make内部错误,修改为MSYS兼容的路径处理方式:
ifdef OS RM = rm -f # 使用MSYS的rm替代原生del命令 LIB_EXT = .lib EXEC_EXT = .exe FixPath = $1 # 取消路径转义,保留MSYS风格路径 else RM = rm -f LIB_EXT = .a EXEC_EXT = FixPath = $1 endif
4. 显式指定ar命令
MSYS2中可能存在多个ar版本冲突,直接指定clang配套的llvm-ar:
AR = llvm-ar # 修改库构建规则 $(LIB_DIR)/$(LIB_OUT): $(OBJ) $(UCD) $(AR) rcs -o $@ $^
内容的提问来源于stack exchange,提问作者rscarson
相关产品推荐
相关产品推荐

