我正在处理一本书中发现的高级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
时发生了什么,并且它引发了上面的错误。
有人有主意吗?
答案 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)
我看看是否需要更多调整,但这似乎是正确的方法!