使fclean &&使所有工作,使re不

时间:2018-10-21 18:55:05

标签: makefile gnu-make

我正在处理一本书中发现的高级Makefile。我里面有一些简单的规则: //Function to open object and file by the name that was entered ifstream inFile; inFile.open(fileName); //checking for error, sends error message if unable to open if(inFile.fail()){ cerr << "This file is unable to be opened.\n"; exit(1); } //Goes on to complete necessary functions if input is valid else { //loop with the condition being a function that checks to the end of the file //so the items are read in till the end of the file while(!inFile.eof()){ //almost like cin, values are read in from the object inFile and stored in variable readIn; inFile >> readIn; //counter adds one for every line if value is existent itemCount++; //calculates product of values product = product * readIn; //stores largest value if(max < readIn){ max = readIn; } //calculates sum of values sum = sum + readIn; //calculation of average average = sum / itemCount; } 删除二进制文件 clean也删除一些额外的文件(链接到ln生成的二进制文件) fclean使一切 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 时发生了什么,并且它引发了上面的错误。 有人有主意吗?

2 个答案:

答案 0 :(得分:1)

您的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仅被解析一次,而输出目录仅被创建一次(在删除之前)。

答案 1 :(得分:0)

很好,谢谢。这促使我思考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)

我看看是否需要更多调整,但这似乎是正确的方法!