qwert to tylko nazwa docelowa, która prawdopodobnie nie będzie prawdziwym plikiem. Reguły makefile wymagają celu. Jeśli chodzi o błąd składniowy, brakuje niektórych rzeczy - zobacz aktualizację.
paxdiablo
2
Ponieważ zakładasz, że jego powłoka rozpoznaje ((...)), dlaczego nie użyć o wiele prostszego dla ((i = 0; i <WHATEVER; ++ i)); robić ...; Gotowe ?
Idelic
1
Zauważ, że seqpolecenie generujące sekwencję liczb istnieje w większości (wszystkich?) Systemach unixowych, więc możesz pisaćfor number in ``seq 1 1000``; do echo $$number; done (Umieść pojedynczy backstick po każdej stronie polecenia seq, a nie dwa, nie wiem jak poprawnie sformatować to przy użyciu składni stackoverflow)
Suzanne Dupéron
3
Dzięki, brakowało mi podwójnego $$, aby odwołać się do zmiennej pętli for.
Leif Gruenwoldt
1
@Jonz: znak kontynuacji linii jest taki, że makenormalnie traktuje każdą linię jako rzecz do uruchomienia w osobnej podpowłoce. Bez kontynuacji próbowałby uruchomić podpowłokę za pomocą (na przykład) for number in 1 2 3 4 ; do, bez reszty pętli. Dzięki temu skutecznie staje się pojedynczą linią formularza while something ; do something ; done, co jest kompletnym zestawieniem. Odpowiedź na $$pytanie tutaj: stackoverflow.com/questions/26564825/... , z pozornie wyodrębnionym kodem z tej samej odpowiedzi :-)
paxdiablo
265
Jeśli używasz GNU make, możesz spróbować
LICZBY = 1 2 3 4
Zrób to:
$ (foreach var, $ (NUMBERS),. / a.out $ (var);)
Ta odpowiedź jest lepsza IMHO, ponieważ nie wymaga użycia żadnej powłoki, jest to czysty plik makefile (nawet jeśli jest specyficzny dla GNU).
Jocelyn delalande
7
średnik ma kluczowe znaczenie, w przeciwnym razie wykona się tylko pierwsza iteracja
Jeremy Leipzig
7
To rozwiązanie ukrywa kod wyjścia ./a.out 1. ./a.out 2zostanie wykonany niezależnie.
bobbogo
1
@Alexander: czy mógłbyś wyjaśnić, jakie ograniczenia masz na myśli?
Idelic
1
@Idelic, tak. Dla następującego makefile i shellscript, shellscript działa (przekazuje argument do ls), podczas gdy Makefile podaje błąd: make: execvp: / bin / sh: lista argumentów jest za długa Makefile: ix.io/d5L Shellscript: ix.io / d5M Problem ten występuje w funkcji foreach, z którą zetknąłem się w pracy, gdy do polecenia została przekazana niezwykle długa lista nazw plików (z długimi ścieżkami). Musieliśmy znaleźć obejście.
Alexander
107
Głównym powodem, aby make IMHO jest-j flaga.make -j5uruchomi 5 poleceń powłoki jednocześnie. Jest to dobre, jeśli masz 4 procesory i dobry test dowolnego makefile.
dla tego samego efektu (tak, jest to taki sam, jak poprzedni sformułowanie, o ile marka obawia się, po prostu nieco bardziej zwarty).
Dalszy kawałek parametryzacji, abyś mógł określić limit w wierszu poleceń (żmudne jak make nie ma żadnych dobrych makr arytmetycznych, więc oszuka tutaj i użyję $(shell ...))
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Uruchamiasz to make -j5 LAST=550z LASTdomyślną wartością 1000.
To zdecydowanie najlepsza odpowiedź z tego powodu, o którym wspominał bobbogo ( -j ).
dbn
Czy jest jakiś konkretny powód, dla którego używa przyrostków .PHONY? Czy są do czegoś potrzebne?
Seb
6
@seb: Bez polecenia .PHONY: allmake wyszuka plik o nazwie all. Jeśli taki plik istnieje, make sprawdzi następnie czas ostatniej zmiany tego pliku, a makefile prawie na pewno nie zrobi tego, co zamierzałeś. .PHONYDeklaracja mówi sprawi że alljest symbolicznym celem. Marka uzna zatem, że allcel jest zawsze nieaktualny. Idealny. Zobacz instrukcję.
@JoeS gnu.org/software/make/manual/make.html#Static-Pattern (myślę, że miałeś na myśli What for the 2nd * colon * for ). Nie myl ich z nieprzyjemnymi (IMHO) Regułami Wzorów . Statyczne zasady wzór są bardzo przydatne, gdy lista celów może być dopasowana przez jednego z make „s Noddy wzory (samo odnosi się do zależności). Tutaj używam jednego tylko dla wygody, że cokolwiek pasowało %do reguły, jest dostępne jak $*w przepisie.
bobbogo
22
Zdaję sobie sprawę, że pytanie ma kilka lat, ale ten post może nadal być dla kogoś przydatny, ponieważ pokazuje podejście, które różni się od powyższego i nie jest uzależnione od operacji powłoki ani potrzeby dewelopera wykreślenia na stałe ciąg wartości liczbowych.
wbudowane makro $ (eval ....) jest twoim przyjacielem. Lub może być przynajmniej.
To jest uproszczony przykład. Nie skaluje się ładnie przy dużych wartościach - działa, ale ponieważ łańcuch ITERATE_COUNT zwiększy się o 2 znaki (spacja i kropka) dla każdej iteracji, w miarę zwiększania się do tysięcy, policzenie słów zajmuje coraz więcej czasu. Jak napisano, nie obsługuje zagnieżdżonej iteracji (aby to zrobić, potrzebujesz osobnej funkcji iteracji i licznika). Jest to czysto gnu make, nie wymaga powłoki (chociaż oczywiście OP chciał uruchomić program za każdym razem - tutaj po prostu wyświetlam komunikat). Jeśli w ciągu ITERATE ma przechwycić wartość 0, ponieważ $ (słowo ...) w przeciwnym razie popełni błąd.
Zauważ, że rosnący ciąg znaków, który ma służyć jako licznik, jest wykorzystywany, ponieważ wbudowane $ (słowa ...) może zapewnić liczbę arabską, ale to make nie obsługuje operacji matematycznych (nie możesz przypisać 1 + 1 do czegoś i dostać 2, chyba że wywołujesz coś z powłoki, aby to zrobić, lub używasz równie skomplikowanej operacji makra). Działa to świetnie w przypadku licznika INCREMENTAL, ale nie tak dobrze w przypadku DECREMENT.
Nie używam tego osobiście, ale ostatnio musiałem napisać funkcję rekurencyjną, aby ocenić zależności bibliotek w wielo-binarnym, wielobibliotkowym środowisku kompilacji, w którym musisz wiedzieć, aby wprowadzić INNE biblioteki, jeśli dodasz bibliotekę, która sam ma inne zależności (niektóre z nich różnią się w zależności od parametrów kompilacji), a ja używam metody $ (eval) i counter podobnej do powyższej (w moim przypadku licznik jest używany, aby upewnić się, że nie przejdziemy w nieskończoność pętli, a także jako narzędzie diagnostyczne do zgłaszania, ile iteracji było konieczne).
Coś innego nic nie warte, choć nieistotne dla Q OP: $ (eval ...) zapewnia metodę obejścia wewnętrznej wstrętności make do odwołań cyklicznych, co jest dobre i dobre do egzekwowania, gdy zmienna jest typem makra (zainicjalizowana z =), a natychmiastowe przypisanie (zainicjowane za pomocą: =). Są chwile, kiedy chcesz mieć możliwość korzystania ze zmiennej w ramach jej własnego przypisania, a $ (eval ...) pozwoli ci to zrobić. Ważną rzeczą do rozważenia w tym miejscu jest to, że w momencie uruchomienia eval zmienna zostaje rozwiązana, a ta część, która jest rozwiązana, nie jest już traktowana jako makro. Jeśli wiesz, co robisz i próbujesz użyć zmiennej w RHS przypisania do siebie, na ogół i tak chcesz to zrobić.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Utknąłem o krok podczas pisania pliku Makefile. Mam następujący kod: set_var: @ NUM = 0; podczas gdy [[$$ NUM <1]]; do \ echo „Jestem tutaj”; \ echo $$ NUM dump $$ {NUM} .txt; \ var = "SSA_CORE $$ {NUM} _MAINEXEC"; \ echo $$ var; \ var1 = eval echo \$${$(var)}; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var tutaj SSA_CORE0_MAINEXEC to zmienna środowiskowa, która jest już ustawiona, więc chcę, aby ta wartość została oszacowana lub wydrukowana za pomocą zmiennej var1. Próbowałem, jak pokazano powyżej, ale nie działa. proszę pomóż.
XYZ_Linux
2
Jest to rzeczywiście łatwe obejście, jednak powstrzymuje cię od korzystania z przyjemnej opcji „make -j 4”, aby procesy działały równolegle.
TabeaKischka
1
@TabeaKischka: rzeczywiście. Nie był to „ zalecany ” sposób, ale bardziej znaczy, jeśli ktoś potrzebuje pewnych funkcji, które nie są oferowane przez Makefile, wówczas można wrócić do implementacji bashi tym samym korzystać z tych funkcji. Pętla jest jedną z cech, dla których można to wykazać.
Chociaż zestaw narzędzi tabeli GNUmake ma prawdziwą whilepętlę (cokolwiek to oznacza w programowaniu GNUmake z jego dwoma lub trzema fazami wykonania), jeśli potrzebna jest lista iteracyjna, istnieje proste rozwiązanie interval. Dla zabawy zmieniamy też liczby na szesnastkowe:
include gmtt/gmtt.mk
# generate a list of 20 numbers, starting at 3 with an increment of 5
NUMBER_LIST := $(call interval,3,20,5)
# convert the numbers in hexadecimal (0x0 as first operand forces arithmetic result to hex) and strip '0x'
NUMBER_LIST_IN_HEX := $(foreach n,$(NUMBER_LIST),$(call lstrip,$(call add,0x0,$(n)),0x))
# finally create the filenames with a simple patsubst
FILE_LIST := $(patsubst %,./a%.out,$(NUMBER_LIST_IN_HEX))
$(info $(FILE_LIST))
#I have a bunch of files that follow the naming convention
#soxfile1 soxfile1.o soxfile1.sh soxfile1.ini soxfile1.txt soxfile1.err
#soxfile2 soxfile2.o soxfile2.sh soxfile2.ini soxfile2.txt soxfile2.err
#sox... .... ..... .... .... ....
#in the makefile, only select the soxfile1.. soxfile2... to install dir
#My GNU makefile solution follows:
tgt=/usr/local/bin/ #need to use sudo
tgt2=/backup/myapplication/ #regular backup
install:
for var in $$(ls -f sox* | grep -v '\.' ) ; \
do \
sudo cp -f $$var ${TGT} ; \
cp -f $$var ${TGT2} ; \
done
#The ls command selects all the soxfile* including the *.something
#The grep command rejects names with a dot in it, leaving
#My desired executable files in a list.
Odpowiedzi:
Poniższe czynności zrobią to, jeśli, jak zakładam, korzystasz z
./a.out
platformy typu UNIX.Testuj w następujący sposób:
produkuje:
W przypadku większych zakresów użyj:
Daje to od 1 do 10 włącznie, wystarczy zmienić
while
warunek zakończenia z 10 na 1000 dla znacznie większego zakresu, jak wskazano w komentarzu.Zagnieżdżone pętle można wykonać w następujący sposób:
produkujący:
źródło
seq
polecenie generujące sekwencję liczb istnieje w większości (wszystkich?) Systemach unixowych, więc możesz pisaćfor number in ``seq 1 1000``; do echo $$number; done
(Umieść pojedynczy backstick po każdej stronie polecenia seq, a nie dwa, nie wiem jak poprawnie sformatować to przy użyciu składni stackoverflow)make
normalnie traktuje każdą linię jako rzecz do uruchomienia w osobnej podpowłoce. Bez kontynuacji próbowałby uruchomić podpowłokę za pomocą (na przykład)for number in 1 2 3 4 ; do
, bez reszty pętli. Dzięki temu skutecznie staje się pojedynczą linią formularzawhile something ; do something ; done
, co jest kompletnym zestawieniem. Odpowiedź na$$
pytanie tutaj: stackoverflow.com/questions/26564825/... , z pozornie wyodrębnionym kodem z tej samej odpowiedzi :-)Jeśli używasz GNU make, możesz spróbować
które wygenerują i wykonają
źródło
./a.out 1
../a.out 2
zostanie wykonany niezależnie.Głównym powodem, aby make IMHO jest
-j
flaga.make -j5
uruchomi 5 poleceń powłoki jednocześnie. Jest to dobre, jeśli masz 4 procesory i dobry test dowolnego makefile.Zasadniczo chcesz, aby zobaczyłeś coś takiego:
To jest
-j
przyjazne (dobry znak). Czy dostrzegasz płytę kotła? Możemy napisać:dla tego samego efektu (tak, jest to taki sam, jak poprzedni sformułowanie, o ile marka obawia się, po prostu nieco bardziej zwarty).
Dalszy kawałek parametryzacji, abyś mógł określić limit w wierszu poleceń (żmudne jak
make
nie ma żadnych dobrych makr arytmetycznych, więc oszuka tutaj i użyję$(shell ...)
)Uruchamiasz to
make -j5 LAST=550
zLAST
domyślną wartością 1000.źródło
.PHONY: all
make wyszuka plik o nazwieall
. Jeśli taki plik istnieje, make sprawdzi następnie czas ostatniej zmiany tego pliku, a makefile prawie na pewno nie zrobi tego, co zamierzałeś..PHONY
Deklaracja mówi sprawi żeall
jest symbolicznym celem. Marka uzna zatem, żeall
cel jest zawsze nieaktualny. Idealny. Zobacz instrukcję.%
do reguły, jest dostępne jak$*
w przepisie.Zdaję sobie sprawę, że pytanie ma kilka lat, ale ten post może nadal być dla kogoś przydatny, ponieważ pokazuje podejście, które różni się od powyższego i nie jest uzależnione od operacji powłoki ani potrzeby dewelopera wykreślenia na stałe ciąg wartości liczbowych.
wbudowane makro $ (eval ....) jest twoim przyjacielem. Lub może być przynajmniej.
To jest uproszczony przykład. Nie skaluje się ładnie przy dużych wartościach - działa, ale ponieważ łańcuch ITERATE_COUNT zwiększy się o 2 znaki (spacja i kropka) dla każdej iteracji, w miarę zwiększania się do tysięcy, policzenie słów zajmuje coraz więcej czasu. Jak napisano, nie obsługuje zagnieżdżonej iteracji (aby to zrobić, potrzebujesz osobnej funkcji iteracji i licznika). Jest to czysto gnu make, nie wymaga powłoki (chociaż oczywiście OP chciał uruchomić program za każdym razem - tutaj po prostu wyświetlam komunikat). Jeśli w ciągu ITERATE ma przechwycić wartość 0, ponieważ $ (słowo ...) w przeciwnym razie popełni błąd.
Zauważ, że rosnący ciąg znaków, który ma służyć jako licznik, jest wykorzystywany, ponieważ wbudowane $ (słowa ...) może zapewnić liczbę arabską, ale to make nie obsługuje operacji matematycznych (nie możesz przypisać 1 + 1 do czegoś i dostać 2, chyba że wywołujesz coś z powłoki, aby to zrobić, lub używasz równie skomplikowanej operacji makra). Działa to świetnie w przypadku licznika INCREMENTAL, ale nie tak dobrze w przypadku DECREMENT.
Nie używam tego osobiście, ale ostatnio musiałem napisać funkcję rekurencyjną, aby ocenić zależności bibliotek w wielo-binarnym, wielobibliotkowym środowisku kompilacji, w którym musisz wiedzieć, aby wprowadzić INNE biblioteki, jeśli dodasz bibliotekę, która sam ma inne zależności (niektóre z nich różnią się w zależności od parametrów kompilacji), a ja używam metody $ (eval) i counter podobnej do powyższej (w moim przypadku licznik jest używany, aby upewnić się, że nie przejdziemy w nieskończoność pętli, a także jako narzędzie diagnostyczne do zgłaszania, ile iteracji było konieczne).
Coś innego nic nie warte, choć nieistotne dla Q OP: $ (eval ...) zapewnia metodę obejścia wewnętrznej wstrętności make do odwołań cyklicznych, co jest dobre i dobre do egzekwowania, gdy zmienna jest typem makra (zainicjalizowana z =), a natychmiastowe przypisanie (zainicjowane za pomocą: =). Są chwile, kiedy chcesz mieć możliwość korzystania ze zmiennej w ramach jej własnego przypisania, a $ (eval ...) pozwoli ci to zrobić. Ważną rzeczą do rozważenia w tym miejscu jest to, że w momencie uruchomienia eval zmienna zostaje rozwiązana, a ta część, która jest rozwiązana, nie jest już traktowana jako makro. Jeśli wiesz, co robisz i próbujesz użyć zmiennej w RHS przypisania do siebie, na ogół i tak chcesz to zrobić.
Happy make'ing.
źródło
Aby umożliwić obsługę wielu platform, skonfiguruj separator poleceń (do wykonywania wielu poleceń w tym samym wierszu).
Jeśli używasz MinGW na przykład na platformie Windows, separatorem poleceń jest
&
:Spowoduje to wykonanie połączonych poleceń w jednym wierszu:
Jak wspomniano w innym miejscu, na platformie * nix
CMDSEP = ;
.źródło
To nie jest tak naprawdę czysta odpowiedź na pytanie, ale inteligentny sposób na obejście takich problemów:
zamiast pisać złożony plik, po prostu przekaż kontrolę na przykład skryptowi bash, np .: makefile
i script.sh wygląda następująco:
źródło
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var tutaj SSA_CORE0_MAINEXEC to zmienna środowiskowa, która jest już ustawiona, więc chcę, aby ta wartość została oszacowana lub wydrukowana za pomocą zmiennej var1. Próbowałem, jak pokazano powyżej, ale nie działa. proszę pomóż.bash
i tym samym korzystać z tych funkcji. Pętla jest jedną z cech, dla których można to wykazać.Może możesz użyć:
źródło
Możesz użyć
set -e
jako prefiksu dla pętli for. Przykład:make
natychmiast wyjdzie z kodem wyjścia<> 0
.źródło
Chociaż zestaw narzędzi tabeli GNUmake ma prawdziwą
while
pętlę (cokolwiek to oznacza w programowaniu GNUmake z jego dwoma lub trzema fazami wykonania), jeśli potrzebna jest lista iteracyjna, istnieje proste rozwiązanieinterval
. Dla zabawy zmieniamy też liczby na szesnastkowe:Wynik:
źródło
Proste, niezależne od powłoki / platformy, czyste rozwiązanie makro jest ...
źródło
źródło