2010-08-13 5 views
7

J'ai une règle qui crée un répertoireSuppress faire sortie d'erreur de règle

bin: 
    -mkdir [email protected] 

Cependant, après la première fois le répertoire a été généré, je reçois cette sortie:

mkdir bin 
mkdir: cannot create directory `bin': File exists 
make: [bin] Error 1 (ignored) 

Est-il possible Je peux seulement exécuter la règle si le répertoire n'existe pas, ou supprimer la sortie quand le répertoire existe déjà?

+0

Près de dupliquer: http://stackoverflow.com/questions/3477292/what-do-and-do-as-prefixes-to-recipe-lines-in-make – reinierpost

Répondre

8

La façon traditionnelle de gérer la création de répertoire est d'utiliser un fichier de timbre qui dépend et crée le répertoire comme un effet secondaire. Supprimez le fichier de tampon lors de distclean ou quel que soit votre cible « vraiment propre » est:

bin/.dirstamp: 
    mkdir -p $(DIRS) 
    touch [email protected] 

bin/foo: bin/.dirstamp 
    $(MKFOO) -o [email protected] 

distclean: 
    rm -rf bin 

La raison est la suivante: chaque fois qu'un fichier bin est créé/supprimé, le mtime du répertoire contenant est mis à jour . Si une cible dépend de bin, la prochaine fois que make sera exécutée, elle recréera les fichiers dont elle n'a pas besoin.

+0

Est-ce que le répertoire dep va sur tous les fichiers générés dans cet emplacement? –

+0

Chaque fichier créé dans ce répertoire devrait dépendre, directement ou indirectement, du fichier de cachet pour s'assurer qu'il a été créé avant utilisation. –

7

L'erreur est déjà ignorée par le '-' sur la ligne de commande. Si vous voulez vraiment perdre les messages d'erreur de mkdir, utilisez la redirection d'E/S:

bin: 
    -mkdir bin 2> /dev/null 

Vous obtiendrez toujours le « ignoré » avertissement de make, cependant, il pourrait être préférable d'utiliser l'option de mkdir qui ne provoque pas l'échec lorsque la cible existe déjà, ce qui est l'option -p:

MKDIR_P = mkdir -p 

bin: 
    ${MKDIR_P} [email protected] 

l'option -p crée en fait tous les répertoires qui manquent sur les chemins donnés, il peut générer aa nombre de répertoires dans une invocation, mais comme ide-effect est qu'il ne génère pas d'erreur pour les répertoires déjà existants. Cela suppose une implémentation POSIX-ish de mkdir; les machines plus anciennes ne le supportent peut-être pas (bien que cela soit standard depuis longtemps maintenant).

+0

pourquoi une telle redirection '2> & 1' aide? Je comprendrais '2>/dev/null' pour envoyer stderr à l'oubli mais l'envoyer à stdout .....? – humanityANDpeace

+0

@humanityANDpeace: Vous avez raison - un thinko en 2010. Je l'ai réparé. Merci. –

0

Votre règle ne doit pas être exécutée sauf si sa cible n'existe pas ou est obsolète en raison de ses dépendances. En d'autres termes, vous ne devriez jamais rencontrer cette erreur.

[Exemple Ajouté]

[[email protected] tmp]$ ls -la 
total 20 
drwxr-xr-x. 2 max users 4096 Aug 14 21:11 . 
drwx------. 80 max max 4096 Aug 14 18:25 .. 
-rw-rw-r-- 1 max max  38 Aug 14 21:11 Makefile 
[[email protected] tmp]$ cat Makefile 
.PHONY: all 
all: bin 

bin: 
    mkdir [email protected] 

[[email protected] tmp]$ make 
mkdir bin 
[[email protected] tmp]$ ls -la 
total 24 
drwxr-xr-x. 3 max users 4096 Aug 14 21:11 . 
drwx------. 80 max max 4096 Aug 14 18:25 .. 
drwxrwxr-x 2 max max 4096 Aug 14 21:11 bin 
-rw-rw-r-- 1 max max  38 Aug 14 21:11 Makefile 
[[email protected] tmp]$ make 
make: Nothing to be done for `all'. 
[[email protected] tmp]$ make 
make: Nothing to be done for `all'. 

Est-ce que votre dossier dépend de quoi que ce soit? Votre dossier est une cible bidon?

+0

Non. C'est toujours démodé, ce que vous voyez dans l'OP est ce que j'ai. –

0

Eh bien, je fini avec cette construction, peut-être quelqu'un trouvera utile ou peut commenter:

BINDIR = . 
TMPDIR = tmp 
OUTDIRS = $(BINDIR) $(TMPDIR) 
$(OUTDIRS): 
    @test -d [email protected] || mkdir [email protected] 
+0

Faire fait 'test' pour vous de toute façon, donc il finit par stater le répertoire deux fois. Cela cache juste le problème que la cible par défaut est. (Point). –

0

Marque assume la première cible est la cible par défaut. Si c'est votre makefile complet, alors il doit toujours essayer de refaire la cible par défaut, qui est bin. Insérez les lignes suivantes en haut de votre makefile:

all: bin 
.PHONY: all 
12

Une autre façon de supprimer la sortie make: error ... (ignored) consiste à ajouter || true à une commande qui pourrait échouer.Exemple avec grep qui vérifie les erreurs dans un fichier journal LaTeX:

undefined: 
    @grep -i undefined *.log || true 

Sans || true, se plaint quand faire grep ne trouve aucune correspondance.

Cela fonctionne pour toutes les commandes, pas seulement mkdir; C'est pourquoi j'ai ajouté cette réponse.

+0

daniel, le préfixe '-' d'une commande dans une règle make fait la même chose sans que le shell ne doive le gérer. C'est probablement plus rapide, et moins susceptible de se retourner contre. –

+7

Le préfixe '-' provoque la sortie de la sortie ennuyante" erreur ignorée ", ce que ma solution ne fait pas. Donc non, les deux ne font pas la même chose. –

+0

Juste appel. Merci –