comment éviter que «répertoire existe déjà une erreur» dans un makefile lors de l’utilisation de mkdir

J’ai besoin de générer un répertoire dans mon fichier makefile et je ne voudrais pas que le “répertoire existe déjà erreur” encore et encore, même si je peux facilement l’ignorer.

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

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

ifeq (,$(findssortingng $(OBJDIR),$(wildcard $(OBJDIR) ))) -mkdir $(OBJDIR) endif 

Sous UNIX Utilisez simplement ceci:

 mkdir -p $(OBJDIR) 

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

En regardant la documentation officielle , 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 du | opérateur de pipe, définissant une condition préalable à la commande uniquement. Cela signifie que la cible $(OBJDIR) devrait exister (au lieu d'être 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 des documents. Voir d'autres réponses pour une autre alternative.

Vous pouvez utiliser la commande test:

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

Voici un truc que j’utilise avec GNU make pour créer des répertoires de sortie du compilateur. Définissez d’abord cette règle:

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

Ensuite, faites tous les fichiers qui vont dans le répertoire dépendant du fichier .d dans ce répertoire:

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

Notez l'utilisation de $

Enfin, empêchez la suppression automatique des fichiers .d:

  .PRECIOUS: %/.d 

Ignorer le fichier .d, et dépendant 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 appel de make.

À l’intérieur de votre makefile:

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

Si avoir le répertoire déjà existant ne vous pose aucun problème, vous pouvez simplement redirect stderr pour cette commande, en éliminant le message d’erreur suivant:

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

Sous Windows

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

Sur Unix | Linux

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

Qui fonctionne également pour plusieurs répertoires, par exemple.

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

Ajouter $(OBJDIR) comme première cible fonctionne bien.

Cela fonctionne sous mingw32 / msys / cygwin / linux

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

Si vous ignorez explicitement le code retour et que vous videz le stream 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 fabrication parallèle – mais je ne l’ai pas testé pour être sûr.

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 à créer.

Si vous voulez voir un autre truc générique de gmake, ou si vous êtes intéressé par une création non récursive avec un minimum d’échafaudage, vous pouvez consulter deux autres astuces de gmake bon marché et les autres publications sur ce blog.