2012-11-29 20 views
7

Chciałbym wykonać zadanie w kilku katalogach, ale do tej pory nie znalazłem rozwiązania "podobnego do pliku Makefile". Wiem, że jest to często zadawane pytanie i wiem, jak go rozwiązać dla sub-makfiles i tak dalej, ale szukam czegoś prostszego.Iterowanie listy katalogów w Makefile

Zamiast robić

copy: 
    cd module1 && mkdir foo 
    cd module2 && mkdir foo 
    cd module3 && mkdir foo 

Chciałbym mieć coś takiego

directories = module1 module2 module3 

copy: $(directories) 
    cd $< && mkdir foo 

ale to nie działa, ponieważ receipe jest wywoływana tylko raz z pierwszego katalogu. Wpadłem na to rozwiązanie, które działa, ale prawdopodobnie nie jest w stylu Makefile:

directories = module1 module2 module3 

copy: 
    for d in $(directories); do cd $$d && mkdir foo && cd ..; done 

Jak mogę to zrobić ładniej?

Odpowiedz

6

Istnieje wiele sposobów na to robi.

Możesz robić co Andrew sugeruje, bez sztywnego kodowania prefiks:

directories = module1 module2 module2 

%/foo: ; mkdir -p -- "[email protected]" 

copy: $(addsuffix /foo,$(directories)) 

co daje

$ make -n copy 
mkdir -p -- "module1/foo" 
mkdir -p -- "module2/foo" 
mkdir -p -- "module3/foo" 

Można również wygenerować cel copy z makefile:

directories = module1 module2 module2 

define copy-target 
    copy:: ; cd $1 && mkdir foo 
endef 

$(foreach dir,$(directories),$(eval $(call copy-target,$(dir)))) 

Daje to:

$ make -n copy 
cd module1 && mkdir foo 
cd module2 && mkdir foo 
cd module3 && mkdir foo 

Można również generować polecenia, a nie cel:

directories = module1 module2 module2 

copy: ; $(foreach dir,$(directories),(cd $(dir) && mkdir foo) &&) : 

co skutkuje

$ make -n copy 
(cd module1 && mkdir foo) && (cd module2 && mkdir foo) && (cd module3 && mkdir foo) && : 
+0

Dzięki, to działa. Wybrałem rozwiązanie 2 (generuję cel 'copy' z pliku makefile), ponieważ nie jest ono powiązane z przypadkiem' mkdir'. Niestety, nie różni się zbytnio od używania pętli-for-loop, ale to nie ma znaczenia. – Robert

2

W plikach Makefiles, gdy chcesz utworzyć plik, zrób regułę z nazwą pliku jako celem i wydaj polecenie, aby utworzyć plik docelowy.

copy: module1/foo module2/foo module3/foo 

module%/foo: 
     mkdir [email protected] 

Jeśli chcesz parametryzacji że nieco aby uniknąć powielania, można również napisać coś podobnego

MODULE_NUMBERS = 1 2 3 

copy: ${MODULE_NUMBERS:%=module%/foo} 

module%/foo: 
     mkdir [email protected] 
+0

Dzięki. Niestety, nie mogę zastosować twojego rozwiązania, ponieważ nie mogę zaadresować odpowiednich katalogów za pomocą symbolu wieloznacznego ("moduł%" w twoim przykładzie), ponieważ mam wiele katalogów z tym samym prefiksem i chcę użyć zmiennej ("katalogi" w moim przykładzie), aby wybrać tylko niektóre z nich. BTW: Użyłem "mkdir" jako przykładowego polecenia (właściwie nie chcę tworzyć katalogów, ale przesyłam pliki z każdego katalogu na serwer), więc rozwiązanie powinno działać niezależnie od wykonywanego zadania. – Robert