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
Sous UNIX, utilisez simplement ceci:
mkdir -p $(OBJDIR)
L'option -p de mkdir empêche le message d'erreur si le répertoire existe.
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.
Vous pouvez utiliser la commande de test:
test -d $(OBJDIR) || mkdir $(OBJDIR)
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.
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 makefile:
target:
if test -d dir; then echo "hello world!"; else mkdir dir; fi
Sur 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 $@
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.
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 marque 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 à 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.