今天我要求你提供关于Makefile让我发疯的帮助。那是:
# Executable name
NAME = libft.a
# Compiler and archive linker settings
CC = gcc
AR = ar
CFLAGS = -Wall -Wextra -Werror -O3 -g3
ARFLAGS = -rsc
IFLAGS = -I./includes/
# Project layout
SRC_DIR = ./src/
INC_DIR = ./inc/
OBJ_DIR = ./obj/
OBJ = $(shell grep -r .o ./obj | awk '{print $$3}' | tr '\n' ' ')
.PHONY: all clean fclean re
#------------------------------------------------------------------------------#
all: $(OBJ_DIR) $(NAME)
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(NAME): compile $(OBJ) $(INC_DIR)libft.h
@echo "Linking library $(NAME).\n"
@$(AR) $(ARFLAGS) $(NAME) $(OBJ)
@echo " ✧ $(AR) $(ARFLAGS) $(NAME) object files: OK! √\n"
compile:
make -C src/io
make -C src/lists
make -C src/memory
make -C src/strings
make -C src/tests
我尝试了多种依赖关系,规则等组合,但我还是没有得到它。有时我会让它停止重新链接,但在这种情况下它不会重新编译目标文件,因为$(OBJ)
是空的,并且在我运行编译后没有更新。
这个版本差不多好,但是每次我运行make
它都会执行配方$(NAME)
并执行ar -rsc %(OBJ)
..我怎样才能将它们放在{{1}的依赖项中}
答案 0 :(得分:2)
嗯,基本上你的整个方法都不会成功。仅举一个例子:您正在尝试使用grep
找到目标文件(老实说,我根本不理解shell命令;从{{1}的输出中打印$3
字是什么你不是这里只是grep -r
吗?)这将扩展到子目录中的所有目标文件。但是,当您的顶级makefile被解析时,该shell命令会运行,并且在 make运行任何规则之前解析 ...所以,还没有构建任何目标文件!所以,这个目标不依赖于任何东西。即使在构建了一些目标文件之后,它也只依赖于已存在的目标文件,而不依赖于构建期间创建的目标文件。
如果我是你,我会完全不同地做到这一点。但是,使makefile正常工作的最简单方法是使用递归make来构建find $(OBJ_DIR) -name \*.o
;像这样更改你的makefile:
$(NAME)
此处all: compile
$(NAME): $(OBJ) $(INC_DIR)libft.h
@echo "Linking library $(NAME).\n"
@$(AR) $(ARFLAGS) $@ $^
@echo " ✧ $(AR) $(ARFLAGS) $@ object files: OK! √\n"
compile:
mkdir -p $(OBJ_DIR)
$(MAKE) -C src/io
$(MAKE) -C src/lists
$(MAKE) -C src/memory
$(MAKE) -C src/strings
$(MAKE) -C src/tests
$(MAKE) $(NAME)
不依赖all
;相反,$(NAME)
步骤首先构建所有内容,然后在结束时递归调用自身构建compile
;在这一点上,我们知道一切都是最新的,我们可以依赖于现有的目标文件。
其他事项:注意我在这里使用自动变量$(NAME)
而不是$^
;该变量是一个运行shell脚本的简单变量:它很昂贵!每次展开$(OBJ)
变量时,您都需要支付该费用,因此您只需要这样做一次。或者,您可以使用$(OBJ)
来设置:=
,这样每个make实例只调用一次OBJS
。这仍然是你需要的时间,但避免这将是痛苦的。
我还将mkdir移到了compile
规则中。它比all
的先决条件更清洁。
最后,您不应该直接使用make
命令调用子品牌。始终使用$(MAKE)
变量,否则各种操作都无法正常工作。
答案 1 :(得分:0)
上一篇文章明显解决了这个问题。
您需要使用$(MAKE)
变量以$(NAME)
规则递归调用您的make文件,而不是将$(NAME)
作为all
依赖项,后续调用您的基础Makefile再次使用$(MAKE)
变量。