Подавите делают вывод ошибок правила

У меня есть правило, которое создает каталог

bin:
    -mkdir $@

Однако после в первый раз, когда каталог был сгенерирован, я получаю этот вывод:

mkdir bin
mkdir: cannot create directory `bin': File exists
make: [bin] Error 1 (ignored)

Есть ли некоторый способ, которым я могу только выполнить правило, если каталог не существует или подавляет вывод, когда каталог уже существует?

11
задан Matt Joiner 13 August 2010 в 13:46
поделиться

5 ответов

Традиционным способом создания каталога является использование файла штампа, от которого зависит создание каталога в качестве побочного эффекта. Удалите файл штампа при выполнении distclean или любой другой вашей «действительно чистой» цели:

bin/.dirstamp:
    mkdir -p $(DIRS)
    touch $@

bin/foo: bin/.dirstamp
    $(MKFOO) -o $@

distclean:
    rm -rf bin

Причина этого следующая: всякий раз, когда файл в bin создается/удаляется, обновляется mtime содержащего каталога. Если цель зависит от bin, то при следующем запуске make она воссоздаст файлы, которые ей не нужны.

7
ответ дан 3 December 2019 в 03:34
поделиться

Ошибка игнорируется уже ведущими '-' в командной строке. Если вы действительно хотите потерять сообщения об ошибках от mkdir, используйте перенаправление ввода/вывода:

bin:
    -mkdir bin 2> /dev/null

Однако вы все равно получите предупреждение 'ignored' от make, поэтому лучше использовать опцию к mkdir, которая не вызывает ошибку, когда цель уже существует, а именно опцию -p:

MKDIR_P = mkdir -p

bin:
    ${MKDIR_P} $@

Опция -p фактически создает все каталоги, которые отсутствуют в заданных путях, поэтому она может создать большое количество каталогов за один вызов, но побочным эффектом является то, что она не выдает ошибку для уже существующих каталогов. Это предполагает POSIX-подобную реализацию mkdir; старые машины могут ее не поддерживать (хотя она уже давно является стандартной).

7
ответ дан 3 December 2019 в 03:34
поделиться

Правило не должно выполняться, если его цель не существует или устарела из-за своих зависимостей. Другими словами, вы никогда не должны столкнуться с этой ошибкой.

[Пример добавлен]

[max@truth tmp]$ ls -la
total 20
drwxr-xr-x.  2 max users 4096 Aug 14 21:11 .
drwx------. 80 max max   4096 Aug 14 18:25 ..
-rw-rw-r--   1 max max     38 Aug 14 21:11 Makefile
[max@truth tmp]$ cat Makefile 
.PHONY: all
all: bin

bin:
    mkdir $@

[max@truth tmp]$ make
mkdir bin
[max@truth tmp]$ ls -la
total 24
drwxr-xr-x.  3 max users 4096 Aug 14 21:11 .
drwx------. 80 max max   4096 Aug 14 18:25 ..
drwxrwxr-x   2 max max   4096 Aug 14 21:11 bin
-rw-rw-r--   1 max max     38 Aug 14 21:11 Makefile
[max@truth tmp]$ make
make: Nothing to be done for `all'.
[max@truth tmp]$ make
make: Nothing to be done for `all'.

Ваша папка от чего-либо зависит? Ваша папка - фальшивая цель?

-1
ответ дан 3 December 2019 в 03:34
поделиться

Я закончил с этой конструкцией, может быть, кто-то сочтет ее полезной или прокомментирует ее:

BINDIR = .
TMPDIR = tmp
OUTDIRS = $(BINDIR) $(TMPDIR)
$(OUTDIRS):
    @test -d $@ || mkdir $@
-1
ответ дан 3 December 2019 в 03:34
поделиться

Make предполагает, что первая цель является целью по умолчанию. Если это ваш полный make-файл, то он всегда должен пытаться переделать цель по умолчанию, которой является bin. Вставьте следующие строки в начало вашего make-файла:

all: bin
.PHONY: all
-1
ответ дан 3 December 2019 в 03:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: