сделать fclean && сделать все работает, сделать ре не - PullRequest
0 голосов
/ 21 октября 2018

Я работаю над продвинутым make-файлом, который я нашел в книге.У меня есть несколько простых правил: 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 и выдает ошибку выше.У кого-нибудь есть идея, пожалуйста?

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Хорошо, большое спасибо.Это заставило меня задуматься о том, как на самом деле работает make-файл, поэтому вот мое базовое решение, благодаря вам:

$(_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)

Я посмотрю, нужно ли мне больше настроек, но, похоже, это правильный путь!

0 голосов
/ 21 октября 2018

У вас есть эта строка в вашем make-файле:

_IGNORE := $(shell mkdir -p $($(_MODULE_NAME)_OUTPUT))

, которая создает выходной каталог во время синтаксического анализа make-файла.Затем вы запускаете свою цель 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 и снова создаст каталог, чтобы он существовал.

Если вы запускаете make re один раз, то make-файл анализируется только один раз, а выходной каталог создается только один раз (до его удаления).

...