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

使用Make静态模式规则编译子目录C文件到obj目录失败如何解决?

现有写法的问题

  • 目标依赖错误:$(NAME)目标的依赖写为$(SRC_NAMES)(根目录下的.o文件名),而非实际要生成的$(SRC_NAMES_O)(obj目录下的.o文件),Make会优先尝试在当前目录生成.o,而非走你预期的输出到obj目录的逻辑。
  • 模式规则路径匹配错误:通用模式规则%.o: %.c中,$@是目标的完整文件名,如果你要将所有.o都统一放在obj根目录,不管源文件在哪个目录,当前的$(OBJ_DIR)$@写法会出现路径拼接错误,比如bonus/xxx.c对应的目标如果是xxx.o,你需要直接输出到obj/xxx.o,不能带bonus前缀。
  • Bonus规则逻辑错误:你写的$(BONUS_PATH): %.o: %.c静态模式规则,目标是.c源文件而非.o目标文件,完全无法匹配;同时bonus目标的依赖写的是源文件列表$(BONUS_PATH),而非你要编译的obj下的.o文件列表。
  • 缺少SRC_DIR变量定义:你代码里用到了SRC_PATH=$(addprefix $(SRC_DIR), $(SRC_FILES)),但没给SRC_DIR赋值,按照你的目录结构,SRC_DIR应该是根目录也就是./。

修改方案

你不需要写两套编译规则,只要写两套匹配不同源目录的模式规则,就能同时匹配根目录和bonus目录下的c文件,统一输出到obj目录。修改后的完整Makefile如下:

SRC_FILES=  ft_atoi.c       \
            ft_bzero.c      \
            ...

BONUS_FILES=ft_lstadd_back.c    \
            ft_lstadd_front.c   \
            ...

NAME=libft.a
LIBSO=libft.so
CC=gcc
CFLAGS=-Wall -Wextra -Werror

# 目录定义
SRC_DIR=./
BONUS_DIR=bonus/
OBJ_DIR=obj/
HDR_DIR=./

HDR_NAME=libft.h
BONUS_HDR=_bonus.h

# 源文件路径拼接
SRC_PATH=$(addprefix $(SRC_DIR), $(SRC_FILES))
BONUS_PATH=$(addprefix $(BONUS_DIR), $(BONUS_FILES))

# 目标文件路径拼接(所有.o都直接放在obj目录下)
SRC_NAMES_O=$(addprefix $(OBJ_DIR), $(SRC_FILES:.c=.o))
BONUS_NAMES_O=$(addprefix $(OBJ_DIR), $(BONUS_FILES:.c=.o))

HDR= $(addprefix $(HDR_DIR),$(HDR_NAME))

all: $(NAME)

# 生成静态库的依赖改为obj下的.o文件
$(NAME): $(OBJ_DIR) $(SRC_NAMES_O)
	ar -rc $@ $(SRC_NAMES_O)
	ranlib $@

$(OBJ_DIR):
	mkdir -p $@

# 通用模式规则1:匹配根目录下的c文件,输出.o到obj目录
$(OBJ_DIR)%.o: $(SRC_DIR)%.c
	$(CC) $(CFLAGS) -c $< -o $@ -I$(HDR_DIR)

# 通用模式规则2:匹配bonus目录下的c文件,同样输出到obj目录
$(OBJ_DIR)%.o: $(BONUS_DIR)%.c
	$(CC) $(CFLAGS) -c $< -o $@ -I$(HDR_DIR)

# bonus目标依赖obj下的bonus相关.o
bonus: $(OBJ_DIR) $(BONUS_NAMES_O)
	ar -r $(NAME) $(BONUS_NAMES_O)
	ranlib $(NAME)

clean:
	rm -rf $(OBJ_DIR)
	rm -rf *.o

sclean: clean
	rm -rf $(NAME) $(LIBSO) a.out

fclean: clean
	rm -f $(NAME)

re: fclean all

so:
	$(CC) -nostartfiles -fPIC $(CFLAGS) $(SRC_PATH) $(BONUS_PATH) -I$(HDR_DIR)
	$(CC) -nostartfiles -shared -o $(LIBSO) $(SRC_PATH) $(BONUS_PATH)

.PHONY: all clean fclean re so bonus

注意:Makefile中所有命令行必须用Tab缩进,不能用空格。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 06:15:00