You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU Make:Makefile无法检测目标可执行文件已构建的问题求助

解决方案

问题根源分析

  1. 重复链接问题:你将目标可执行文件${PROJ}标记为.PHONY,伪目标的特性是make会忽略其实际文件的存在和时间戳,每次都会强制执行对应的构建命令,这就是即使可执行文件已存在仍重复链接的原因。
  2. options重复输出问题:all目标直接依赖options(同样是伪目标),无论可执行文件是否需要重建,make都会执行options的打印逻辑。

修改后的Makefile实现(推荐方案)

通过将选项打印逻辑与可执行文件的构建条件绑定,仅在需要编译/链接时才输出选项,同时移除伪目标标记让make正常检测文件时间戳:

PROJ := comms_test

CSRCS = $(PROJ).c

CC := cc
LD := gcc

INCLUDES := \
        -I. 

LDFLAGS = 

CPPFLAGS = 

CFLAGS := \
      -O0 \
      -Wpedantic


OBJS += $(CSRCS:%.c=%.o)


.PHONY: all clean echo test
all: $(PROJ)

# 仅当需要构建可执行文件时,先打印选项再执行链接
$(PROJ): $(OBJS)
	@# 检查可执行文件是否不存在,或者依赖的.o文件更新时间晚于可执行文件
	@if [ ! -f "$@" ] || [ "$(filter-out $@,$^)" -nt "$@" ]; then \
		echo "$(PROJ) build options:"; \
		echo "CC           = $(CC)"; \
		echo "CFLAGS       = $(CFLAGS)"; \
		echo "CPPFLAGS     = $(CPPFLAGS)"; \
		echo "INCLUDES     = $(INCLUDES)"; \
		echo "LDFLAGS      = $(LDFLAGS)"; \
	fi
	${LD} -o "$@" ${OBJS} ${LDFLAGS}

%.o: %.c
	${CC} ${CPPFLAGS} ${CFLAGS} ${INCLUDES} -c "$<" -o "$@"

clean:
	rm -rf ${OBJS} ${PROJ}

echo:
	@echo ${CSRCS}
	@echo ${OBJS}

效果说明

  • 当可执行文件comms_test已存在且所有.o依赖文件未修改时,执行make或make comms_test只会输出make: 'comms_test' is up to date.(若需隐藏此提示,可在all目标后添加@:)。
  • 当.c文件修改导致.o更新,或可执行文件被删除时,make会先打印编译选项,再执行编译和链接操作。

备选方案(使用中间标记文件)

如果偏好通过make的目标依赖而非shell逻辑实现,可使用一个临时标记文件控制选项打印:

PROJ := comms_test

CSRCS = $(PROJ).c

CC := cc
LD := gcc

INCLUDES := \
        -I. 

LDFLAGS = 

CPPFLAGS = 

CFLAGS := \
      -O0 \
      -Wpedantic


OBJS += $(CSRCS:%.c=%.o)


.PHONY: all clean echo test
all: $(PROJ)

# 可执行文件依赖中间标记文件,确保选项仅在需要时打印
$(PROJ): .build-mark
	${LD} -o "$@" ${OBJS} ${LDFLAGS}

# 中间标记文件依赖.o文件,更新时打印选项并创建标记
.build-mark: $(OBJS)
	@echo "$(PROJ) build options:"; \
	echo "CC           = $(CC)"; \
	echo "CFLAGS       = $(CFLAGS)"; \
	echo "CPPFLAGS     = $(CPPFLAGS)"; \
	echo "INCLUDES     = $(INCLUDES)"; \
	echo "LDFLAGS      = $(LDFLAGS)"; \
	touch "$@"

# 编译.o文件时删除标记,触发下次构建重新打印选项
%.o: %.c
	${CC} ${CPPFLAGS} ${CFLAGS} ${INCLUDES} -c "$<" -o "$@"
	@rm -f .build-mark

clean:
	rm -rf ${OBJS} ${PROJ} .build-mark

echo:
	@echo ${CSRCS}
	@echo ${OBJS}

内容的提问来源于stack exchange,提问作者kollie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:54:55