使用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
相关产品推荐
相关产品推荐

