使用Makefile编译C多文件程序出现警告,请求排查原因
编译K.N.King《C程序设计现代方法》多文件程序的Makefile警告问题
问题描述
编译该书第二版中的库存管理多文件程序时,出现以下警告:
clang: warning: readline.o: 'linker' input unused [-Wunused-command-line-argument] clang: warning: inventory2.o: 'linker' input unused [-Wunused-command-line-argument] clang: warning: argument unused during compilation: '-Wall' [-Wunused-command-line-argument]
用户使用的Makefile如下:
############ # makefile # ############ CC = gcc CFLAGS = -c -Wall BIN=inventory2 $(BIN): $(BIN).o readline.o #readline.h $(CC) $(CFLAGS) readline.o $(BIN).o -o $(BIN) $(BIN).o: $(BIN).c $(CC) $(CFLAGS) $(BIN).c -o $(BIN).o readline.o: readline.c readline.h $(CC) $(CFLAGS) readline.c -o readline.o clean: $(RM) -rf $(BIN) *.dSYM $(RM) -rf readline.o $(RM) -rf $(BIN).o run: all ./$(BIN)
警告原因
- 链接阶段错误使用
-c参数:-c是GCC/Clang的编译选项,作用是只编译源文件生成目标文件(.o),不执行链接操作。但在生成最终可执行文件$(BIN)的规则里,你把包含-c的CFLAGS传给了编译器,导致编译器忽略了传入的.o文件(因为-c让它只处理源文件,不链接),因此提示这些链接输入未被使用。 -Wall属于编译参数,不应该出现在链接阶段:-Wall用来开启编译时的警告,链接阶段不需要这个参数,因此被标记为未使用。
解决办法
修正Makefile的核心是区分编译阶段和链接阶段的参数:
- 把
CFLAGS中的-c移除,CFLAGS只保留编译相关的警告/优化参数 - 链接阶段不再使用
CFLAGS,直接用编译器链接目标文件即可 - 修复
run目标的依赖(原Makefile没有all目标,改为依赖最终可执行文件$(BIN))
修正后的Makefile如下:
############ # makefile # ############ CC = gcc CFLAGS = -Wall # 只保留编译阶段的参数,移除-c BIN = inventory2 # 默认目标,执行make时直接编译生成可执行文件 all: $(BIN) $(BIN): $(BIN).o readline.o $(CC) $^ -o $@ # $^代表所有依赖文件,$@代表目标文件,简化写法 $(BIN).o: $(BIN).c $(CC) $(CFLAGS) -c $< -o $@ # -c在这里单独指定,只编译源文件 readline.o: readline.c readline.h $(CC) $(CFLAGS) -c $< -o $@ clean: $(RM) -rf $(BIN) *.dSYM $(RM) -rf readline.o $(BIN).o run: $(BIN) ./$(BIN)
关键修改说明
- 拆分
-c的使用:仅在编译源文件为目标文件的规则中添加-c,链接阶段完全移除 - 使用自动变量
$^(所有依赖)和$<(第一个依赖)简化命令,让Makefile更简洁易维护 - 添加
all目标作为默认目标,符合Makefile的常规写法 - 修复
run目标的依赖,确保执行make run前先完成编译
内容的提问来源于stack exchange,提问作者ecjb
相关产品推荐
相关产品推荐

