Comment empêcher "l'erreur de répertoire existe déjà" dans un fichier Make quand on utilise mkdir
Question
Je dois générer un répertoire dans mon fichier makefile et je ne souhaite pas que le " répertoire existe déjà avec une erreur " encore et encore, même si je peux facilement l'ignorer.
J'utilise principalement mingw / msys, mais j'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
La solution
Sous UNIX, utilisez simplement ceci:
mkdir -p $(OBJDIR)
L'option -p de mkdir empêche le message d'erreur si le répertoire existe.
Autres conseils
En regardant la documentation sur la marque officielle , voici un bon moyen de fais-le:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) <*>lt;
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 générer la cible actuelle.
Notez que j'ai utilisé mkdir -p
. L'indicateur -p
a été ajouté par rapport à l'exemple de la documentation.
Voir les autres réponses pour une autre alternative.
Vous pouvez utiliser la commande de test:
test -d $(OBJDIR) || mkdir $(OBJDIR)
Voici une astuce que j'utilise avec GNU pour créer des répertoires de sortie du compilateur. Définissez d'abord cette règle:
%/.d:
mkdir -p $(@D)
touch $@
Faites en sorte que tous les fichiers qui entrent dans le répertoire dépendent du fichier .d de ce répertoire:
obj/%.o: %.c obj/.d
$(CC) $(CFLAGS) -c -o $@ .PRECIOUS: %/.d
lt;
Notez l'utilisation de $ < au lieu de $ ^.
Enfin, empêchez la suppression automatique des fichiers .d:
<*>Sauter 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 appel de make.
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
Dans votre fichier Make:
target:
if test -d dir; then echo "hello world!"; else mkdir dir; fi
Sous Windows
if not exist "$(OBJDIR)" mkdir $(OBJDIR)
Sous Unix | Linux
if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
ifeq "$(wildcard $(MY_DIRNAME) )" ""
-mkdir $(MY_DIRNAME)
endif
$(OBJDIR):
mkdir $@
Ce qui fonctionne également pour plusieurs répertoires, par exemple ..
OBJDIRS := $(sort $(dir $(OBJECTS)))
$(OBJDIRS):
mkdir $@
Ajouter $ (OBJDIR)
en tant que 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 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 fabrication parallèle - mais je ne l’ai pas testé pour en ê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 .PRECIOUS: -)
Si vous voulez voir un autre petit truc générique gmake, ou si vous êtes intéressé par une fabrication non récursive avec un échafaudage minimal, vous voudrez peut-être consulter Deux autres astuces gmake bon marché et les autres publications relatives à la création dans ce blog.