web-dev-qa-db-fra.com

comment empêcher "le répertoire existe déjà erreur" dans un fichier make quand mkdir est utilisé

J'ai besoin de générer un répertoire dans mon makefile et j'aimerais ne pas avoir l'erreur "le répertoire existe déjà" encore et encore, même si je peux facilement l'ignorer.

J'utilise principalement mingw/msys mais aimerais quelque chose qui fonctionne aussi sur d'autres shells/systèmes.

J'ai essayé ça mais ça n'a pas marché, des idées?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
106
KPexEA

Sous UNIX, utilisez simplement ceci:

mkdir -p $(OBJDIR)

L'option -p de mkdir empêche le message d'erreur si le répertoire existe.

104
tchen

En regardant la documentation officielle de la marque , voici un bon moyen de le faire:

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)

Vous devriez voir ici l'utilisation de la | opérateur de pipe, définissant un ordre uniquement comme condition préalable. Cela signifie que la cible $(OBJDIR) doit être existante (au lieu de plus récente ) afin de construire la cible actuelle.

Notez que j'ai utilisé mkdir -p. L'indicateur -p A été ajouté par rapport à l'exemple de la documentation. Voir d'autres réponses pour une autre alternative.

119
ofavre

Vous pouvez utiliser la commande de test:

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

Voici une astuce que j'utilise avec GNU permet de créer des répertoires de sortie du compilateur. Commençons par définir cette règle:

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

Ensuite, associez tous les fichiers qui entrent dans le répertoire au fichier .d de ce répertoire:

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

Notez l'utilisation de $ <au lieu de $ ^.

Enfin, empêchez les fichiers .d d'être supprimés automatiquement:

 .PRECIOUS: %/.d

Ignorer le fichier .d et dépendre directement du répertoire ne fonctionnera pas, car l'heure de modification du répertoire est mise à jour à chaque fois qu'un fichier est écrit dans ce répertoire, ce qui forcerait la reconstruction à chaque invocation de make.

18
Lars Hamrén

Si le répertoire existe déjà ne pose pas de problème, vous pouvez simplement rediriger stderr pour cette commande, en éliminant le message d'erreur suivant:

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

Dans votre makefile:

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

Sur Windows

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

Sur Unix | Linux

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

Ce qui fonctionne également pour plusieurs annuaires, par exemple ..

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

$(OBJDIRS):
    mkdir $@

Ajouter $(OBJDIR) en tant que première cible fonctionne bien.

6
Martin Fido

Cela fonctionne sous mingw32/msys/cygwin/linux

ifeq "$(wildcard .dep)" ""
-include $(Shell mkdir .dep) $(wildcard .dep/*)
endif
3
lygstate

Si vous ignorez explicitement le code de retour et videz le flux d'erreur, votre marque ignorera l'erreur si elle se produit:

mkdir 2>/dev/null || true

Cela ne devrait pas causer de risque de course dans une marque parallèle - mais je ne l’ai pas testé pour en être sûr.

0
Andrew

Un peu plus simple que la réponse de Lars:

something_needs_directory_xxx : xxx/..

et règle générique:

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

Pas de fichiers tactiles à nettoyer ou à faire .PRECIOUS :-)

Si vous voulez voir un autre petit truc générique de gmake, ou si vous êtes intéressé par une fabrication non récursive avec un échafaudage minimal, vous voudrez peut-être jeter un œil à Deux autres trucs de gmake moins chers et l'autre lié à make. messages dans ce blog.

0
Mischa