Makefile编译报错:missing separator及NUL字符问题排查求助
Makefile跨目录编译报错调试
问题重现
编写了用于编译C源码的Makefile,希望将.o、.d文件存放在与.c源码不同的路径下,Makefile内容如下:
SHELL=/bin/bash EXEC=./bin OBJ=./obj CC=mpicc CFLAGS=-O3 -Wall LFLAGS=-lm -lstdc++ -lmpi $(OBJ)/%.o: %.c $(CC) -c $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) -MM $*.c > $(OBJ)/$*.d FWI_OBJ = $(FWI_SRC:%.c=$(OBJ)/%.o) FWI_SRC = \ testmpi.c \ printneigh.c fwi2D: $(FWI_OBJ) fd.h $(CC) $(LFLAGS) $(FWI_OBJ) -o $(EXEC)/xtestmpi all: fwi2D .PHONY: clean clean: rm -f $(OBJ)/*.o $(OBJ)/*.d $(EXEC)/* install: clean all -include $(FWI_OBJ:$(OBJ)/.o=$(OBJ)/.d)
执行make后报错:
obj/testmpi.o:1: warning: NUL character seen; rest of line ignored obj/testmpi.o:1: *** missing separator. Stop.
错误原因分析
Include语句替换规则错误
最后一行的-include $(FWI_OBJ:$(OBJ)/.o=$(OBJ)/.d)存在语法错误:模式替换需要使用%通配符匹配任意字符,原写法缺少%,导致替换未生效,Makefile实际尝试包含的是obj/testmpi.o等二进制目标文件。二进制文件包含大量NUL字符,Makefile读取时无法解析,因此抛出错误。变量定义顺序颠倒
FWI_OBJ在FWI_SRC之前定义,此时FWI_SRC尚未赋值,导致FWI_OBJ为空,后续编译规则会出现依赖缺失问题。依赖文件(.d)生成不规范
手动用-MM生成依赖时,输出的目标是当前目录的testmpi.o,而非obj/testmpi.o,这会导致依赖关系错误,后续增量编译时无法正确识别文件更新。
修正后的Makefile
SHELL=/bin/bash EXEC=./bin OBJ=./obj CC=mpicc CFLAGS=-O3 -Wall -MMD -MP # 添加-MMD自动生成.d文件,-MP避免头文件删除后报错 LFLAGS=-lm -lstdc++ -lmpi # 先定义源码列表,再生成目标文件列表 FWI_SRC = \ testmpi.c \ printneigh.c FWI_OBJ = $(FWI_SRC:%.c=$(OBJ)/%.o) # 确保obj、bin目录存在 $(shell mkdir -p $(OBJ) $(EXEC)) $(OBJ)/%.o: %.c $(CC) -c $(CFLAGS) $< -o $@ fwi2D: $(FWI_OBJ) fd.h $(CC) $(LFLAGS) $(FWI_OBJ) -o $(EXEC)/xtestmpi all: fwi2D .PHONY: clean clean: rm -f $(OBJ)/*.o $(OBJ)/*.d $(EXEC)/* install: clean all # 正确包含.d依赖文件 -include $(FWI_OBJ:%.o=%.d)
关键修改点
- 调整
FWI_SRC和FWI_OBJ的定义顺序,确保FWI_OBJ能正确生成目标文件路径。 - 使用
-MMD -MP参数替代手动生成.d文件:-MMD会自动生成包含正确路径的依赖文件,-MP会自动为每个头文件生成空目标,避免头文件被删除后Make报错。 - 修正include语句的替换规则:
$(FWI_OBJ:%.o=%.d)将所有.o路径替换为.d路径,确保包含的是依赖文件而非二进制目标文件。 - 添加
$(shell mkdir -p $(OBJ) $(EXEC))自动创建输出目录,避免因目录不存在导致编译失败。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

