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

Makefile编译独立C程序:分文件编译与目录创建失效求助

问题场景

现有目录结构如下:

build
ch01
  foo.c
  bar.c
ch02
  baz.c
  meow.c

需求:每个.c文件都是独立程序,编译后需放到build/目录下对应同名子文件夹中,最终结构如下:

build
  ch01
    foo, bar
  ch02
    baz, meow
现有Makefile的问题

当前使用的Makefile能实现需求,但存在两个痛点:

  1. 必须拆分编译/链接阶段,手动删除中间目标文件,因为找不到更优方式从完整构建路径还原源文件名。
  2. 尝试用标准前置目标方式单独创建目录时,$(BUILD_DIR)目标完全不执行:
    all: $(OBJS) | $(BUILD_DIR)
    
    $(BUILD_DIR):
      $(MD) -p $@
    
优化后的解决方案

子目录Makefile(ch01、ch02下各放一份)

CC = gcc
CFLAGS = -g -Wall -Wextra -ansi
MD = mkdir -p

# 匹配当前目录下所有C源文件
SRCS = $(wildcard *.c)
# 生成build目录下的可执行文件路径
BINS = $(patsubst %.c, ../build/$(shell basename $(CURDIR))/%, $(SRCS))
BUILD_DIR = ../build/$(shell basename $(CURDIR))

# 默认目标:构建所有可执行文件
all: $(BINS)

# 直接从C源文件编译链接到目标可执行文件
$(BUILD_DIR)/%: %.c | $(BUILD_DIR)
	$(CC) $(CFLAGS) $< -o $@

# 创建build子目录的目标
$(BUILD_DIR):
	$(MD) $@

# 清理生成的可执行文件目录
clean:
	rm -rf $(BUILD_DIR)

优化说明

  1. 解决手动删除目标文件问题:
    不再生成中间.o文件,直接将.c文件一步编译链接为build目录下的可执行文件。目标路径$(BUILD_DIR)/%与源文件%.c一一对应,无需处理中间文件,自然省去手动删除步骤。

  2. 解决目录创建目标不执行问题:
    将最终可执行文件的编译规则依赖前置条件$(BUILD_DIR),Make在构建可执行文件前会自动检查目录是否存在,不存在则执行目录创建规则。原方案失效是因为all依赖的是.o文件,而.o文件的规则未关联目录创建逻辑,调整目标为最终可执行文件后,前置条件生效。

可选:顶层统一编译Makefile

如果需要在根目录一键编译所有子目录,可在根目录创建如下Makefile:

SUBDIRS = ch01 ch02

all: $(SUBDIRS)

$(SUBDIRS):
	$(MAKE) -C $@

clean:
	for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:52:48