2014-09-24 16 views
5

È possibile eseguire un make clean dalla directory padre che pulisce anche ricorsivamente tutte le sottodirectory senza dover includere un makefile in ciascuna sottodirectory?Utilizzo di Makefile per pulire le sottodirectory

Per esempio, attualmente nel mio Makefile, ho qualcosa di simile:

SUBDIRS = src, src1 

.PHONY: clean subdirs $(SUBDIRS) 

clean: $(SUBDIRS) 
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c 

$(SUBDIRS): 
    $(MAKE) -C $(SUBDIRS) clean 

Tuttavia, questo mi richiede di avere un Makefile sia src e src1. In caso contrario, vorrei avere l'errore

No rule to make target clean 

Dal momento che ho solo voglia di eseguire il comando "rm-rf * .o ~ nucleo .depend. .cmd * * .ko .mod.c" in ogni sottodirectory comunque, sembra ridondante dover includere un Makefile in ogni sottodirectory con la stessa identica linea per clean. Non c'è modo di avere semplicemente lo stesso comando pulito eseguito in ciascuna sottodirectory?

+0

Probabilmente si desidera semplicemente avere il comando clean per eliminare i file in modo ricorsivo. Vedi: https: // superutente.it/questions/61258/use-rm-to-remove-files-and-directories-ricorsivamente –

+0

Quello o semplicemente loop in clean su '$ (SUBDIRS)' ed esegui 'rm' in ognuno manualmente. –

+0

In realtà, se scrivi il tuo makefile di primo livello con attenzione (o scrivi un makefile separato di clean.mk che includi) allora puoi '$ (MAKE) -C $ @ -f clean.mk clean' in quella ricetta credo. (Si noti '$ @' invece di '$ (SUBDIRS)'. '-C' prende un singolo argomento non una lista.) –

risposta

0

Sono d'accordo sul fatto che si può semplicemente avere il comando rm operare su sottodirectory. Ma qualcosa del genere permette di fare ricorsivamente usando solo un singolo makefile:

SUBDIRS = . src src1 
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS)) 

clean: $(SUBDIRSCLEAN) 

clean_curdir: 
    rm -rfv *.o *~ core .depend .*.cmd *.ko *.mod.c 

%clean: % 
    $(MAKE) -C $< -f $(PWD)/Makefile clean_curdir 
+0

Come ricorri una volta in src o src1 ... come fai a sapere quante sottodirectory ci sono e costruisci una nuova versione della variabile 'SUBDIRS'? –

+0

L'esempio è completo. L'esecuzione di 'make --debug' mostrerà cosa sta succedendo. Qualcosa come 'find' potrebbe probabilmente rilevare le sottodirectory se un elenco hard-coded non lo farà. – robert

0

Non è possibile senza un programma esterno. Il meglio è uno script di shell che fa la ricorsione e le chiamate make in ciascuna sottodirectory (guarda il mio commento a @robert nella sua risposta) Qualcosa come questo farà il lavoro (e non dipende dalle funzionalità di GNU)

#!/bin/sh 
ROOTDIR=`/bin/pwd` 
for dir in `find . -type d -print` 
do 
    make -C "${dir}" -f "${ROOTDIR}"/Makefile clean 
done 

naturalmente, si può mettere questa sequenza (in target cleanrec) all'interno del vostro Makefile

cleanrec: 
    ROOT=`/bin/pwd`; \ 
    for dir in `find . -type d -print`; \ 
    do \ 
     make -C "$${dir}" -f "$${ROOTDIR}"/Makefile clean; \ 
    done 

e conservare la vostra clean obiettivo per la pulizia locale di una singola directory. Il motivo è che Makefile ha solo informazioni statiche per fare il make, e devi ottenere qualche aiuto esterno per sapere quali sottodirectory hai in ogni directory. Quindi, nel caso in cui si sta per ottenere un aiuto esterno, è meglio utilizzare un buon strumento come find (1) e sh (1)

1

Invece di usare la ricorsione, si potrebbe sborsare per find per ottenere una lista di directory e fare una singola iterazione per generare i caratteri jolly:

SUBDIR_ROOTS := foo bar 
DIRS := . $(shell find $(SUBDIR_ROOTS) -type d) 
GARBAGE_PATTERNS := *.o *~ core .depend .*.cmd *.ko *.mod.c 
GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(GARBAGE_PATTERNS))) 

clean: 
    rm -rf $(GARBAGE) 
0

una variazione di @Christoph risposta:

# Exclude directory from find . command 
# https://stackoverflow.com/questions/4210042/exclude-directory-from-find-command 
GARBAGE_TYPES   := "*.gz(busy)" *.aux *.log *.pdf *.aux *.bbl *.log *.out *.synctex.gz *.fls 
DIRECTORIES_TO_CLEAN := $(shell find -not -path "./.git**" -not -path "./images**" -type d) 
GARBAGE_TYPED_FOLDERS := $(foreach DIR, $(DIRECTORIES_TO_CLEAN), $(addprefix $(DIR)/,$(GARBAGE_TYPES))) 

clean: 
    $(RM) -rf $(GARBAGE_TYPED_FOLDERS) 
    # echo $(GARBAGE_TYPED_FOLDERS) 

Questo è un exampl e per i file in lattice. Il primo motivo su GARBAGE_TYPES ha le virgolette doppie attorno a esso a causa della parentesi sul nome del tipo di file. Senza di esso, rm non è possibile rimuoverli. Gli altri modelli non hanno bisogno delle virgolette.

Il secondo DIRECTORIES_TO_CLEAN utilizza l'opposto di un elenco di directory da pulire, ovvero un elenco di directory da non pulire. Ciò è utile quando hai solo una o due directory come .git e images che non vuoi pulire, ma vuoi pulire tutto il resto.