как предотвратить ошибку «каталог уже существует» в make-файле при использовании mkdir

StackOverflow https://stackoverflow.com/questions/99132

  •  01-07-2019
  •  | 
  •  

Вопрос

Мне нужно создать каталог в моем make-файле, и я бы не хотел снова и снова получать сообщение об ошибке «каталог уже существует», даже если я могу легко его проигнорировать.

В основном я использую mingw/msys, но хотелось бы, чтобы что-то работало и в других оболочках/системах.

Я попробовал это, но это не сработало, есть идеи?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
Это было полезно?

Решение

В UNIX Просто используйте это:

mkdir -p $(OBJDIR)

Опция -p команды mkdir предотвращает появление сообщения об ошибке, если каталог существует.

Другие советы

Смотря на официальная документация производителя, вот хороший способ сделать это:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir -p $(OBJDIR)

Вы должны увидеть здесь использование | Оператор трубы, определяющий только заказ только обязанности.Это означает, что $(OBJDIR) цель должна существовать (вместо более свежий), чтобы построить текущую цель.

Обратите внимание, что я использовал mkdir -p-p флаг был добавлен по сравнению с примером из документации.Смотрите другие ответы для другой альтернативы.

Вы можете использовать тестовую команду:

test -d $(OBJDIR) || mkdir $(OBJDIR)

Вот трюк, который я использую с GNU make для создания каталогов вывода компилятора.Сначала определите это правило:

  %/.d:
          mkdir -p $(@D)
          touch $@

Затем сделайте все файлы, попадающие в каталог, зависимыми от файла .d в этом каталоге:

 obj/%.o: %.c obj/.d
    $(CC) $(CFLAGS) -c -o $@ $<

Обратите внимание на использование $< вместо $^.

Наконец, запретите автоматическое удаление файлов .d:

 .PRECIOUS: %/.d

Пропустить файл .d и напрямую зависеть от каталога не получится, поскольку время изменения каталога обновляется каждый раз, когда в этом каталоге записывается файл, что приведет к принудительному перестроению при каждом вызове make.

Если наличие уже существующего каталога для вас не проблема, вы можете просто перенаправить stderr для этой команды, избавившись от сообщения об ошибке:

-mkdir $(OBJDIR) 2>/dev/null

Внутри вашего make-файла:

target:
    if test -d dir; then echo "hello world!"; else mkdir dir; fi

В Windows

if not exist "$(OBJDIR)" mkdir $(OBJDIR)

На Unix | Linux

if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
ifeq "$(wildcard $(MY_DIRNAME) )" ""
  -mkdir $(MY_DIRNAME)
endif
$(OBJDIR):
    mkdir $@

Это также работает для нескольких каталогов, например.

OBJDIRS := $(sort $(dir $(OBJECTS)))

$(OBJDIRS):
    mkdir $@

Добавление $(OBJDIR) поскольку первая цель работает хорошо.

Он работает под mingw32/msys/cygwin/linux.

ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif

Если вы явно игнорируете код возврата и выгружаете поток ошибок, то ваш make будет игнорировать ошибку, если она произойдет:

mkdir 2>/dev/null || true

Это не должно вызвать опасность гонки в параллельной версии, но я не проверял это, чтобы быть уверенным.

Немного проще, чем ответ Ларса:

something_needs_directory_xxx : xxx/..

и общее правило:

%/.. : ;@mkdir -p $(@D)

Никаких сенсорных файлов, которые нужно очищать или делать .PRECIOUS :-)

Если вы хотите увидеть еще один небольшой общий трюк с gmake или если вас интересует нерекурсивный make с минимальными каркасами, вы можете проверить Еще два дешевых трюка с Gmake и другие сообщения, связанные с make, в этом блоге.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top