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

Makefile递归编译子目录失效问题求助

Makefile子目录编译异常原因分析

问题场景

目录结构

├── Makefile
├── prime_probe.c
└── utils
    ├── Makefile
    ├── caches_info.c
    ├── caches_info.h
    ├── caches_util.c
    ├── caches_util.h
    ├── configure.h
    ├── list_struct.h
    ├── list_utils.c
    └── list_utils.h

主目录Makefile内容

THIS_DIR  := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
OBJDIR = obj

CFLAGS = -I./$(OBJDIR) -g -fPIC -std=gnu99

UTILS_DIR := utils
OBJS_UTL   = $(addprefix $(UTILS_DIR)/$(OBJDIR)/,$(notdir $(patsubst %.c,%.o,$(shell find $(UTILS_DIR)/*.c))))
SRCS_PRIME =                  \
    prime_probe.c       

OBJS_PRIME = $(addprefix $(OBJDIR)/,$(patsubst %.c,%.o,$(SRCS_PRIME)))
all: clean utils $(OBJS_PRIME) 
$(OBJDIR)/%.o: %.c | objdir
    $(CC) $(CFLAGS) -c $< -o $(OBJDIR)/$(notdir $@)


utils:
    $(MAKE) -C $(UTILS_DIR) 

objdir:
    @mkdir -p $(OBJDIR)

clean:
    rm -rf $(OBJDIR)
    $(MAKE) clean -C $(UTILS_DIR)/

子目录utils/Makefile内容

THIS_DIR  := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
##################
# Build directory
##################
OBJDIR = obj

CFLAGS = -I./$(OBJDIR) -g -fPIC -std=gnu99 -static
####################
# Files and folders
####################

SRCS_PRIME = $(shell find ./*.c)

OBJS_PRIME = $(addprefix $(OBJDIR)/,$(patsubst %.c,%.o,$(SRCS_PRIME)))

##########
# Targets
##########

all:  $(OBJS_PRIME)
$(OBJDIR)/%.o: %.c | objdir
    $(CC) $(CFLAGS) -c $< -g -o $@

objdir:
    @mkdir -p $(OBJDIR)

clean:
    rm -rf $(OBJDIR)

执行输出

root@096b64b8fd50:/usr/local/src/gem5/programs/covert_channel# make
rm -rf obj
make clean -C utils/
make[1]: Entering directory '/usr/local/src/gem5/programs/covert_channel/utils'
rm -rf obj
make[1]: Leaving directory '/usr/local/src/gem5/programs/covert_channel/utils'
cc -I./obj -g -fPIC -std=gnu99 -c prime_probe.c -o obj/prime_probe.o

root@096b64b8fd50:/usr/local/src/gem5/programs/covert_channel# make utils
make: 'utils' is up to date.

root@096b64b8fd50:/usr/local/src/gem5/programs/covert_channel/utils# cd utils/
root@096b64b8fd50:/usr/local/src/gem5/programs/covert_channel/utils# make
cc -I./obj -g -fPIC -std=gnu99 -static -c caches_info.c -g -o obj/./caches_info.o
cc -I./obj -g -fPIC -std=gnu99 -static -c caches_util.c -g -o obj/./caches_util.o
cc -I./obj -g -fPIC -std=gnu99 -static -c list_utils.c -g -o obj/./list_utils.o

核心原因

  1. utils目标未标记为伪目标(.PHONY):主目录下存在同名的utils目录,Make会将utils目标与该目录文件关联。由于目录的修改时间被视为目标的时间戳,且utils目标无依赖项,Make判定该目标已处于最新状态,不会执行对应的$(MAKE) -C $(UTILS_DIR)命令。

  2. utils目标无实际依赖关联:主Makefile中虽定义了子目录的目标文件变量OBJS_UTL,但未将其设为utils目标的依赖。Make无法感知子目录需要生成的文件状态,自然不会触发编译动作。

修复方案

方案1:标记utils为伪目标

在主Makefile中添加.PHONY声明,让Make忽略同名目录,强制执行目标命令:

.PHONY: all utils clean objdir

all: clean utils $(OBJS_PRIME) 
# 其余内容保持不变

方案2:让utils目标依赖子目录生成文件

将OBJS_UTL设为utils目标的依赖,让Make通过文件状态判断是否需要编译:

utils: $(OBJS_UTL)

$(OBJS_UTL):
    $(MAKE) -C $(UTILS_DIR)

可选优化:修正子Makefile路径

子Makefile中生成的目标路径存在冗余的./,可简化规则:

$(OBJDIR)/%.o: %.c | objdir
    $(CC) $(CFLAGS) -c $< -g -o $@

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:10:45