come prevenire l'errore "la directory esiste già" in un makefile quando si utilizza mkdir

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

  •  01-07-2019
  •  | 
  •  

Domanda

Devo generare una directory nel mio makefile e vorrei non ricevere più e più volte l'errore "directory già esistente" anche se posso facilmente ignorarlo.

Utilizzo principalmente mingw/msys ma vorrei qualcosa che funzioni anche su altre shell/sistemi.

Ho provato questo ma non ha funzionato, qualche idea?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
È stato utile?

Soluzione

Su UNIX basta usare questo:

mkdir -p $(OBJDIR)

L'opzione -p di mkdir impedisce il messaggio di errore se la directory esiste.

Altri suggerimenti

Guardando il funzionario fa la documentazione, ecco un buon modo per farlo:

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)

Dovresti vedere qui l'uso del | Operatore di tubi, che definisce un ordine solo prerequisito.Ciò significa che il $(OBJDIR) target dovrebbe essere esistente (invece di più recente) per costruire l'obiettivo attuale.

Nota che ho usato mkdir -p.IL -p flag è stato aggiunto rispetto all'esempio dei documenti.Vedi altre risposte per un'altra alternativa.

Puoi usare il comando test:

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

Ecco un trucco che utilizzo con GNU make per creare directory di output del compilatore.Per prima cosa definisci questa regola:

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

Quindi rendi tutti i file che vanno nella directory dipendenti dal file .d in quella directory:

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

Nota l'uso di $< invece di $^.

Infine, impedisci la rimozione automatica dei file .d:

 .PRECIOUS: %/.d

Saltare il file .d e dipendere direttamente dalla directory non funzionerà, poiché l'ora di modifica della directory viene aggiornata ogni volta che un file viene scritto in quella directory, il che forzerebbe la ricostruzione ad ogni invocazione di make.

Se avere la directory già esistente non è un problema per te, potresti semplicemente reindirizzare stderr per quel comando, eliminando il messaggio di errore:

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

All'interno del tuo makefile:

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

Su Windows

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

Su unix | Linux

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

Che funziona anche per più directory, ad es.

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

$(OBJDIRS):
    mkdir $@

Aggiunta $(OBJDIR) poiché il primo obiettivo funziona bene.

Funziona con mingw32/msys/cygwin/linux

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

Se ignori esplicitamente il codice di ritorno e scarichi il flusso di errori, il tuo make ignorerà l'errore se si verifica:

mkdir 2>/dev/null || true

Ciò non dovrebbe causare rischi di corsa in una produzione parallela, ma non l'ho testato per esserne sicuro.

Un po' più semplice della risposta di Lars:

something_needs_directory_xxx : xxx/..

e regola generica:

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

Nessun file touch da pulire o rendere .PRECIOUS :-)

Se vuoi vedere un altro piccolo trucchetto generico con gmake, o se sei interessato a make non ricorsivo con un'impalcatura minima, potresti dare un'occhiata Altri due trucchi gmake economici e gli altri post relativi al make in quel blog.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top