make fclean && make all works, make re 不
make fclean && make all works, make re doesn't
我正在研究我在一本书中找到的高级 makefile。我里面有一些简单的规则:
clean
删除二进制文件
fclean
也删除一些额外的文件(链接到 ln 生成的二进制文件)
all
使所有
re
制作 fclean
然后制作 all
当我执行 make fclean
然后 make all
时,它完美地工作。当我执行 make re
时,出现错误:
error: unable to open output file '/Users/malberte/work/libft/bin/libft/common/ft_atoi.o':
'No such file or directory'
1 error generated.
所以这是我的代码:
$(_MODULE_NAME)_OBJS := $(addsuffix $(_OBJEXT),$(addprefix $($(_MODULE_NAME)_OUTPUT)/,$(basename $(SRCS)))) $(DEPS)
$(_MODULE_NAME)_BINARY := $($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(BINARY_EXT)
$(_MODULE_NAME)_EXPOSE_BINARY := $(_ROOT)/$(BINARY)$(BINARY_EXT)
ifneq ($(_NO_RULES),T)
ifneq ($($(_MODULE_NAME)_DEFINED), T)
_CLEAN := clean-$(_MODULE_NAME)
_FCLEAN := fclean-$(_MODULE_NAME)
_ALL := all-$(_MODULE_NAME)
_RE := re-$(_MODULE_NAME)
_IGNORE := $(shell mkdir -p $($(_MODULE_NAME)_OUTPUT))
.PHONY: all re $(_ALL) $(_RE)
re: fclean all
# re: $(_RE)
# $(_RE): $(_FCLEAN) $(_ALL)
all: $(_ALL)
$(_ALL): $($(_MODULE_NAME)_BINARY)
.PHONY: $(_MODULE_NAME)
$(_MODULE_NAME): $($(_MODULE_NAME)_BINARY)
.PHONY: fclean clean $(_CLEAN)
fclean: $(_FCLEAN)
$(_FCLEAN): $(_CLEAN)
rm -rf $($(patsubst fclean-%,%,$@)_EXPOSE_BINARY)
clean: $(_CLEAN)
$(_CLEAN):
rm -rf $($(patsubst clean-%,%,$@)_OUTPUT)
$($(_MODULE_NAME)_OUTPUT)/%.o: $(_MODULE_PATH)/%.c
@$(COMPILE.c) -o '$@' '$<'
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_LIBEXT): $($(_MODULE_NAME)_OBJS)
@if [ "$(LIBMERGE)" = "F" ]; \
then \
$(AR) r '$@' $^; \
ranlib '$@'; \
else \
libtool -static -o '$@' $^; \
fi
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_EXEEXT): $($(_MODULE_NAME)_OBJS)
$(LINK.c) $^ -o '$@'
$(_MODULE_NAME)_DEFINED := T
endif
endif
我已经尝试了很多东西,我真的不明白当我使用 make re
时发生了什么,它抛出了上面的错误。
有人有想法吗?
您的 makefile 中有这一行:
_IGNORE := $(shell mkdir -p $($(_MODULE_NAME)_OUTPUT))
在解析 makefile 时创建输出目录。然后你 运行 你的 clean
目标调用这个食谱:
rm -rf $($(patsubst clean-%,%,$@)_OUTPUT)
这会导致输出目录被删除。然后你 运行 你的 all
目标调用编译器并要求它将输出文件写入 $($(_MODULE_NAME)_OUTPUT)/%.o
但该目录不再存在。
所以编译器给你错误:
error: unable to open output file '...': No such file or directory
如果你 运行 make
两次,那么第一次清理并删除目录,然后当你 运行 make all
它会 运行 _IGNORE
shell 命令并再次创建目录,这样它就会存在。
如果你 运行 make re
一次,那么 makefile 只被解析一次,输出目录只被创建一次(在它被删除之前)。
好的,非常感谢。这促使我思考 makefile 的真正工作原理,所以这里是我的基本解决方案,感谢您:
$(_MODULE_NAME)_OBJS := $(addsuffix $(_OBJEXT),$(addprefix $($(_MODULE_NAME)_OUTPUT)/,$(basename $(SRCS)))) $(DEPS)
$(_MODULE_NAME)_BINARY := $($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(BINARY_EXT)
$(_MODULE_NAME)_EXPOSE_BINARY := $(_ROOT)/$(BINARY)$(BINARY_EXT)
ifneq ($(_NO_RULES),T)
ifneq ($($(_MODULE_NAME)_DEFINED), T)
_OUTPUT_TREE := output-tree-$(_MODULE_NAME)
_CLEAN := clean-$(_MODULE_NAME)
_FCLEAN := fclean-$(_MODULE_NAME)
_ALL := all-$(_MODULE_NAME)
_RE := re-$(_MODULE_NAME)
# _IGNORE := $(shell mkdir -p $($(_MODULE_NAME)_OUTPUT))
.PHONY: all re $(_ALL) $(_RE)
re: fclean all
# re: $(_RE)
# $(_RE): $(_FCLEAN) $(_ALL)
all: $(_ALL)
$(_ALL): $($(_MODULE_NAME)_BINARY)
.PHONY: $(_MODULE_NAME)
$(_MODULE_NAME): $($(_MODULE_NAME)_BINARY)
.PHONY: fclean clean $(_CLEAN)
fclean: $(_FCLEAN)
$(_FCLEAN): $(_CLEAN)
rm -rf $($(patsubst fclean-%,%,$@)_EXPOSE_BINARY)
clean: $(_CLEAN)
$(_CLEAN):
rm -rf $($(patsubst clean-%,%,$@)_OUTPUT)
$($(_MODULE_NAME)_OUTPUT)/%.o: $(_MODULE_PATH)/%.c | $(_OUTPUT_TREE)
@$(COMPILE.c) -o '$@' '$<'
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_LIBEXT): $($(_MODULE_NAME)_OBJS)
@if [ "$(LIBMERGE)" = "F" ]; \
then \
$(AR) r '$@' $^; \
ranlib '$@'; \
else \
libtool -static -o '$@' $^; \
fi
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_EXEEXT): $($(_MODULE_NAME)_OBJS)
$(LINK.c) $^ -o '$@'
.PHONY: output-tree $(_OUTPUT_TREE)
output-tree: $(_OUTPUT_TREE)
$(_OUTPUT_TREE):
mkdir -p $($(_MODULE_NAME)_OUTPUT)
$(_MODULE_NAME)_DEFINED := T
endif
endif
我向原子目标添加了先决条件订单
$($(_MODULE_NAME)_OUTPUT)/%.o: $(_MODULE_PATH)/%.c | $(_OUTPUT_TREE)
规则如下:
.PHONY: output-tree $(_OUTPUT_TREE)
output-tree: $(_OUTPUT_TREE)
$(_OUTPUT_TREE):
mkdir -p $($(_MODULE_NAME)_OUTPUT)
我会看看是否需要更多调整,但这似乎是正确的方法!
我正在研究我在一本书中找到的高级 makefile。我里面有一些简单的规则:
clean
删除二进制文件
fclean
也删除一些额外的文件(链接到 ln 生成的二进制文件)
all
使所有
re
制作 fclean
然后制作 all
当我执行 make fclean
然后 make all
时,它完美地工作。当我执行 make re
时,出现错误:
error: unable to open output file '/Users/malberte/work/libft/bin/libft/common/ft_atoi.o':
'No such file or directory'
1 error generated.
所以这是我的代码:
$(_MODULE_NAME)_OBJS := $(addsuffix $(_OBJEXT),$(addprefix $($(_MODULE_NAME)_OUTPUT)/,$(basename $(SRCS)))) $(DEPS)
$(_MODULE_NAME)_BINARY := $($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(BINARY_EXT)
$(_MODULE_NAME)_EXPOSE_BINARY := $(_ROOT)/$(BINARY)$(BINARY_EXT)
ifneq ($(_NO_RULES),T)
ifneq ($($(_MODULE_NAME)_DEFINED), T)
_CLEAN := clean-$(_MODULE_NAME)
_FCLEAN := fclean-$(_MODULE_NAME)
_ALL := all-$(_MODULE_NAME)
_RE := re-$(_MODULE_NAME)
_IGNORE := $(shell mkdir -p $($(_MODULE_NAME)_OUTPUT))
.PHONY: all re $(_ALL) $(_RE)
re: fclean all
# re: $(_RE)
# $(_RE): $(_FCLEAN) $(_ALL)
all: $(_ALL)
$(_ALL): $($(_MODULE_NAME)_BINARY)
.PHONY: $(_MODULE_NAME)
$(_MODULE_NAME): $($(_MODULE_NAME)_BINARY)
.PHONY: fclean clean $(_CLEAN)
fclean: $(_FCLEAN)
$(_FCLEAN): $(_CLEAN)
rm -rf $($(patsubst fclean-%,%,$@)_EXPOSE_BINARY)
clean: $(_CLEAN)
$(_CLEAN):
rm -rf $($(patsubst clean-%,%,$@)_OUTPUT)
$($(_MODULE_NAME)_OUTPUT)/%.o: $(_MODULE_PATH)/%.c
@$(COMPILE.c) -o '$@' '$<'
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_LIBEXT): $($(_MODULE_NAME)_OBJS)
@if [ "$(LIBMERGE)" = "F" ]; \
then \
$(AR) r '$@' $^; \
ranlib '$@'; \
else \
libtool -static -o '$@' $^; \
fi
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_EXEEXT): $($(_MODULE_NAME)_OBJS)
$(LINK.c) $^ -o '$@'
$(_MODULE_NAME)_DEFINED := T
endif
endif
我已经尝试了很多东西,我真的不明白当我使用 make re
时发生了什么,它抛出了上面的错误。
有人有想法吗?
您的 makefile 中有这一行:
_IGNORE := $(shell mkdir -p $($(_MODULE_NAME)_OUTPUT))
在解析 makefile 时创建输出目录。然后你 运行 你的 clean
目标调用这个食谱:
rm -rf $($(patsubst clean-%,%,$@)_OUTPUT)
这会导致输出目录被删除。然后你 运行 你的 all
目标调用编译器并要求它将输出文件写入 $($(_MODULE_NAME)_OUTPUT)/%.o
但该目录不再存在。
所以编译器给你错误:
error: unable to open output file '...': No such file or directory
如果你 运行 make
两次,那么第一次清理并删除目录,然后当你 运行 make all
它会 运行 _IGNORE
shell 命令并再次创建目录,这样它就会存在。
如果你 运行 make re
一次,那么 makefile 只被解析一次,输出目录只被创建一次(在它被删除之前)。
好的,非常感谢。这促使我思考 makefile 的真正工作原理,所以这里是我的基本解决方案,感谢您:
$(_MODULE_NAME)_OBJS := $(addsuffix $(_OBJEXT),$(addprefix $($(_MODULE_NAME)_OUTPUT)/,$(basename $(SRCS)))) $(DEPS)
$(_MODULE_NAME)_BINARY := $($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(BINARY_EXT)
$(_MODULE_NAME)_EXPOSE_BINARY := $(_ROOT)/$(BINARY)$(BINARY_EXT)
ifneq ($(_NO_RULES),T)
ifneq ($($(_MODULE_NAME)_DEFINED), T)
_OUTPUT_TREE := output-tree-$(_MODULE_NAME)
_CLEAN := clean-$(_MODULE_NAME)
_FCLEAN := fclean-$(_MODULE_NAME)
_ALL := all-$(_MODULE_NAME)
_RE := re-$(_MODULE_NAME)
# _IGNORE := $(shell mkdir -p $($(_MODULE_NAME)_OUTPUT))
.PHONY: all re $(_ALL) $(_RE)
re: fclean all
# re: $(_RE)
# $(_RE): $(_FCLEAN) $(_ALL)
all: $(_ALL)
$(_ALL): $($(_MODULE_NAME)_BINARY)
.PHONY: $(_MODULE_NAME)
$(_MODULE_NAME): $($(_MODULE_NAME)_BINARY)
.PHONY: fclean clean $(_CLEAN)
fclean: $(_FCLEAN)
$(_FCLEAN): $(_CLEAN)
rm -rf $($(patsubst fclean-%,%,$@)_EXPOSE_BINARY)
clean: $(_CLEAN)
$(_CLEAN):
rm -rf $($(patsubst clean-%,%,$@)_OUTPUT)
$($(_MODULE_NAME)_OUTPUT)/%.o: $(_MODULE_PATH)/%.c | $(_OUTPUT_TREE)
@$(COMPILE.c) -o '$@' '$<'
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_LIBEXT): $($(_MODULE_NAME)_OBJS)
@if [ "$(LIBMERGE)" = "F" ]; \
then \
$(AR) r '$@' $^; \
ranlib '$@'; \
else \
libtool -static -o '$@' $^; \
fi
$($(_MODULE_NAME)_OUTPUT)/$(BINARY)$(_EXEEXT): $($(_MODULE_NAME)_OBJS)
$(LINK.c) $^ -o '$@'
.PHONY: output-tree $(_OUTPUT_TREE)
output-tree: $(_OUTPUT_TREE)
$(_OUTPUT_TREE):
mkdir -p $($(_MODULE_NAME)_OUTPUT)
$(_MODULE_NAME)_DEFINED := T
endif
endif
我向原子目标添加了先决条件订单
$($(_MODULE_NAME)_OUTPUT)/%.o: $(_MODULE_PATH)/%.c | $(_OUTPUT_TREE)
规则如下:
.PHONY: output-tree $(_OUTPUT_TREE)
output-tree: $(_OUTPUT_TREE)
$(_OUTPUT_TREE):
mkdir -p $($(_MODULE_NAME)_OUTPUT)
我会看看是否需要更多调整,但这似乎是正确的方法!