Das Folgende wird es tun, wenn Sie sich, wie ich durch Ihre Verwendung von ./a.outannehme, auf einer UNIX-Plattform befinden.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Test wie folgt:
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
produziert:
1
2
3
4
Verwenden Sie für größere Reichweiten:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
Dies gibt 1 bis einschließlich 10 aus. Ändern Sie einfach die whileAbschlussbedingung von 10 auf 1000 für einen viel größeren Bereich, wie in Ihrem Kommentar angegeben.
Verschachtelte Schleifen können folgendermaßen ausgeführt werden:
qwert ist nur ein Zielname, bei dem es sich wahrscheinlich nicht um eine echte Datei handelt. Makefile-Regeln benötigen ein Ziel. Was den Syntaxfehler betrifft, fehlen Ihnen einige Dinge - siehe Update.
Paxdiablo
2
Da Sie davon ausgehen, dass seine Shell ((...)) erkennt, können Sie das viel einfachere für ((i = 0; i <WHATEVER; ++ i)) verwenden. machen ...; getan ?
Idelic
1
Beachten Sie, dass der seqBefehl, der eine Folge von Zahlen generiert, auf den meisten (allen?) Unix-Systemen vorhanden ist, sodass Sie schreiben können for number in ``seq 1 1000``; do echo $$number; done(Setzen Sie einen einzelnen Backtick auf jede Seite des seq-Befehls, nicht auf zwei, ich weiß nicht, wie ich das richtig formatieren soll unter Verwendung der Syntax von stackoverflow)
Suzanne Dupéron
3
Danke, mir fehlte das doppelte $$, um auf die for-Schleifenvariable zu verweisen.
Leif Gruenwoldt
1
@Jonz: Das Zeilenfortsetzungszeichen ist, weil makenormalerweise jede Zeile als eine Sache behandelt wird, die in einer separaten Unter-Shell ausgeführt werden soll. Ohne Fortsetzung würde es versuchen, eine Subshell mit nur (zum Beispiel) for number in 1 2 3 4 ; doohne den Rest der Schleife auszuführen . Damit wird es effektiv zu einer einzelnen Zeile des Formulars while something ; do something ; done, was eine vollständige Aussage ist. Die $$Frage wird hier beantwortet: stackoverflow.com/questions/26564825/… , wobei der Code scheinbar aus dieser Antwort extrahiert wurde :-)
paxdiablo
265
Wenn Sie GNU make verwenden, können Sie es versuchen
ZAHLEN = 1 2 3 4
Tu es:
$ (foreach var, $ (NUMBERS) ,. / a.out $ (var);)
Diese Antwort ist meiner Meinung nach besser, da keine Shell verwendet werden muss, sondern ein reines Makefile (auch wenn es GNU-spezifisch ist).
Jocelyn delalande
7
Das Semikolon ist entscheidend, sonst wird nur die erste Iteration ausgeführt
Jeremy Leipzig
7
Diese Lösung verbirgt den Exit-Code von ./a.out 1. ./a.out 2wird trotzdem ausgeführt.
Bobbogo
1
@Alexander: Könnten Sie näher erläutern, auf welche Einschränkung Sie sich beziehen?
Idelic
1
@ Idelic, ja. Für das folgende Makefile und Shellscript funktioniert das Shellscript (übergibt das Argument an ls), während das Makefile einen Fehler ausgibt: make: execvp: / bin / sh: Argumentliste zu lang Makefile: ix.io/d5L Shellscript: ix.io. / d5M Dies ist ein Problem in der foreach-Funktion, auf das ich bei der Arbeit gestoßen bin, als eine ungewöhnlich lange Liste von Dateinamen (auch mit langen Pfaden) an einen Befehl übergeben wurde. Wir mussten eine Problemumgehung finden.
Alexander
107
Der Hauptgrund für make IMHO ist die -jFlagge. make -j5führt 5 Shell-Befehle gleichzeitig aus. Dies ist gut, wenn Sie 4 CPUs haben und einen guten Test für jedes Makefile.
für den gleichen Effekt (ja, dies ist das gleiche wie die vorherige Formulierung, was die Marke betrifft, nur ein bisschen kompakter).
Eine weitere Parametrisierung, damit Sie ein Limit in der Befehlszeile festlegen können (mühsam, da makees keine guten arithmetischen Makros gibt, also werde ich hier schummeln und verwenden $(shell ...))
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Sie führen dies mit aus make -j5 LAST=550, wobei LASTstandardmäßig 1000 verwendet wird.
Dies ist definitiv die beste Antwort aus dem Grund, den Bobbogo erwähnte ( -j ).
dbn
Gibt es einen bestimmten Grund, warum .PHONY-Suffixe verwendet werden? Werden sie für irgendetwas benötigt?
Seb
6
@seb: Ohne .PHONY: allsucht make nach einer Datei namens all. Wenn eine solche Datei vorhanden ist, überprüft make die zuletzt geänderte Zeit dieser Datei, und das Makefile wird mit ziemlicher Sicherheit nicht das tun, was Sie beabsichtigt haben. Die .PHONYDeklaration sagt make, dass dies allein symbolisches Ziel ist. Make wird daher das allZiel als immer veraltet betrachten. Perfekt. Siehe das Handbuch.
@JoeS gnu.org/software/make/manual/make.html#Static-Pattern (Ich denke, Sie meinten, wofür ist der 2. * Doppelpunkt * ). Verwechseln Sie sie nicht mit den unschönen (IMHO) Musterregeln . Statische Musterregeln sind immer dann nützlich, wenn die Liste der Ziele mit einem der Knotenmuster von make abgeglichen werden kann (dies gilt auch für die Abhängigkeiten). Hier verwende ich eine nur, um die Bequemlichkeit zu gewährleisten, dass alles, was mit %der Regel übereinstimmt, wie $*im Rezept verfügbar ist .
Bobbogo
22
Mir ist klar, dass die Frage mehrere Jahre alt ist, aber dieser Beitrag kann für jemanden von Nutzen sein, da er einen Ansatz zeigt, der sich von den oben genannten unterscheidet und weder von Shell-Operationen noch von der Notwendigkeit abhängt, dass der Entwickler einen fest codierten Ansatz erstellt Zeichenfolge numerischer Werte.
Das in $ (eval ....) eingebaute Makro ist dein Freund. Oder kann es zumindest sein.
Das ist ein vereinfachtes Beispiel. Es wird für große Werte nicht schön skaliert - es funktioniert, aber da die ITERATE_COUNT-Zeichenfolge für jede Iteration um 2 Zeichen (Leerzeichen und Punkt) erhöht wird, dauert das Zählen der Wörter zunehmend länger, wenn Sie zu Tausenden aufsteigen. Wie geschrieben, werden verschachtelte Iterationen nicht verarbeitet (dazu benötigen Sie eine separate Iterationsfunktion und einen Zähler). Dies ist rein gnu make, keine Shell-Anforderung (obwohl das OP offensichtlich jedes Mal ein Programm ausführen wollte - hier zeige ich lediglich eine Nachricht an). Das if in ITERATE soll den Wert 0 abfangen, da sonst $ (word ...) fehlerhaft wird.
Beachten Sie, dass die wachsende Zeichenfolge, die als Zähler dient, verwendet wird, da das eingebaute $ (Wörter ...) eine arabische Zählung liefern kann, aber make ansonsten keine mathematischen Operationen unterstützt (Sie können etwas nicht 1 + 1 zuweisen und 2 erhalten, es sei denn, Sie rufen etwas aus der Shell auf, um es für Sie zu erledigen, oder verwenden eine ebenso komplizierte Makrooperation. Dies funktioniert hervorragend für einen INCREMENTAL-Zähler, jedoch nicht so gut für einen DECREMENT-Zähler.
Ich benutze dies nicht selbst, aber kürzlich musste ich eine rekursive Funktion schreiben, um Bibliotheksabhängigkeiten in einer Umgebung mit mehreren Binärdateien und mehreren Bibliotheken zu bewerten, in der Sie wissen müssen, wie Sie ANDERE Bibliotheken einbinden können, wenn Sie eine Bibliothek hinzufügen, die selbst hat andere Abhängigkeiten (von denen einige abhängig von den Build-Parametern variieren), und ich verwende eine $ (eval) - und Zählermethode ähnlich der oben genannten (in meinem Fall wird der Zähler verwendet, um sicherzustellen, dass wir nicht irgendwie in ein Endlos geraten Schleife und auch als Diagnose, um zu melden, wie viel Iteration erforderlich war).
Etwas anderes, das nichts wert ist, obwohl es für das Q: $ (eval ...) des OP nicht von Bedeutung ist, bietet eine Methode, um die interne Abscheu von make gegenüber Zirkelverweisen zu umgehen. Dies ist alles gut und in Ordnung, wenn eine Variable ein Makrotyp ist (initialisiert mit =) gegen eine sofortige Zuordnung (initialisiert mit: =). Es gibt Zeiten, in denen Sie eine Variable innerhalb ihrer eigenen Zuweisung verwenden möchten, und mit $ (eval ...) können Sie dies tun. Hierbei ist zu beachten, dass zum Zeitpunkt der Ausführung der Auswertung die Variable aufgelöst wird und der aufgelöste Teil nicht mehr als Makro behandelt wird. Wenn Sie wissen, was Sie tun, und Sie versuchen, eine Variable auf der rechten Seite einer Zuweisung für sich selbst zu verwenden, möchten Sie dies im Allgemeinen trotzdem tun.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Ich bin beim Schreiben eines Makefiles bei einem Schritt hängen geblieben. Ich habe folgenden Code: set_var: @ NUM = 0; während [[$$ NUM <1]]; do \ echo "Ich bin hier"; \ 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 here SSA_CORE0_MAINEXEC ist eine Umgebungsvariable, die bereits festgelegt ist. Daher möchte ich, dass dieser Wert mit der Variablen var1 ausgewertet oder gedruckt wird. Ich habe es wie oben gezeigt versucht, aber es funktioniert nicht. Bitte helfen Sie.
XYZ_Linux
2
Dies ist in der Tat eine einfache Problemumgehung, verhindert jedoch, dass Sie die nette Option "make -j 4" verwenden, um Prozesse parallel auszuführen.
TabeaKischka
1
@ TabeaKischka: in der Tat. Es war nicht der " empfohlene " Weg, aber es ist eher gemeint, wenn man einige Funktionen benötigt, die nicht von einem Makefile angeboten werden, kann man auf eine Implementierung in zurückgreifen bashund somit die Funktionen verwenden. Die Schleife ist eines der Merkmale, für die dies demonstriert werden kann.
Obwohl das GNUmake-Tabellen-Toolkit eine echte whileSchleife hat (was auch immer dies in der GNUmake-Programmierung mit zwei oder drei Ausführungsphasen bedeutet), gibt es eine einfache Lösung mit, wenn eine iterative Liste benötigt wird interval. Zum Spaß konvertieren wir die Zahlen auch in Hex:
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.
Antworten:
Das Folgende wird es tun, wenn Sie sich, wie ich durch Ihre Verwendung von
./a.out
annehme, auf einer UNIX-Plattform befinden.Test wie folgt:
produziert:
Verwenden Sie für größere Reichweiten:
Dies gibt 1 bis einschließlich 10 aus. Ändern Sie einfach die
while
Abschlussbedingung von 10 auf 1000 für einen viel größeren Bereich, wie in Ihrem Kommentar angegeben.Verschachtelte Schleifen können folgendermaßen ausgeführt werden:
Herstellung:
quelle
seq
Befehl, der eine Folge von Zahlen generiert, auf den meisten (allen?) Unix-Systemen vorhanden ist, sodass Sie schreiben könnenfor number in ``seq 1 1000``; do echo $$number; done
(Setzen Sie einen einzelnen Backtick auf jede Seite des seq-Befehls, nicht auf zwei, ich weiß nicht, wie ich das richtig formatieren soll unter Verwendung der Syntax von stackoverflow)make
normalerweise jede Zeile als eine Sache behandelt wird, die in einer separaten Unter-Shell ausgeführt werden soll. Ohne Fortsetzung würde es versuchen, eine Subshell mit nur (zum Beispiel)for number in 1 2 3 4 ; do
ohne den Rest der Schleife auszuführen . Damit wird es effektiv zu einer einzelnen Zeile des Formularswhile something ; do something ; done
, was eine vollständige Aussage ist. Die$$
Frage wird hier beantwortet: stackoverflow.com/questions/26564825/… , wobei der Code scheinbar aus dieser Antwort extrahiert wurde :-)Wenn Sie GNU make verwenden, können Sie es versuchen
die generieren und ausführen
quelle
./a.out 1
../a.out 2
wird trotzdem ausgeführt.Der Hauptgrund für make IMHO ist die
-j
Flagge.make -j5
führt 5 Shell-Befehle gleichzeitig aus. Dies ist gut, wenn Sie 4 CPUs haben und einen guten Test für jedes Makefile.Grundsätzlich möchten Sie etwas sehen lassen wie:
Das ist
-j
freundlich (ein gutes Zeichen). Kannst du die Kesselplatte erkennen? Wir könnten schreiben:für den gleichen Effekt (ja, dies ist das gleiche wie die vorherige Formulierung, was die Marke betrifft, nur ein bisschen kompakter).
Eine weitere Parametrisierung, damit Sie ein Limit in der Befehlszeile festlegen können (mühsam, da
make
es keine guten arithmetischen Makros gibt, also werde ich hier schummeln und verwenden$(shell ...)
)Sie führen dies mit aus
make -j5 LAST=550
, wobeiLAST
standardmäßig 1000 verwendet wird.quelle
.PHONY: all
sucht make nach einer Datei namensall
. Wenn eine solche Datei vorhanden ist, überprüft make die zuletzt geänderte Zeit dieser Datei, und das Makefile wird mit ziemlicher Sicherheit nicht das tun, was Sie beabsichtigt haben. Die.PHONY
Deklaration sagt make, dass diesall
ein symbolisches Ziel ist. Make wird daher dasall
Ziel als immer veraltet betrachten. Perfekt. Siehe das Handbuch.%
der Regel übereinstimmt, wie$*
im Rezept verfügbar ist .Mir ist klar, dass die Frage mehrere Jahre alt ist, aber dieser Beitrag kann für jemanden von Nutzen sein, da er einen Ansatz zeigt, der sich von den oben genannten unterscheidet und weder von Shell-Operationen noch von der Notwendigkeit abhängt, dass der Entwickler einen fest codierten Ansatz erstellt Zeichenfolge numerischer Werte.
Das in $ (eval ....) eingebaute Makro ist dein Freund. Oder kann es zumindest sein.
Das ist ein vereinfachtes Beispiel. Es wird für große Werte nicht schön skaliert - es funktioniert, aber da die ITERATE_COUNT-Zeichenfolge für jede Iteration um 2 Zeichen (Leerzeichen und Punkt) erhöht wird, dauert das Zählen der Wörter zunehmend länger, wenn Sie zu Tausenden aufsteigen. Wie geschrieben, werden verschachtelte Iterationen nicht verarbeitet (dazu benötigen Sie eine separate Iterationsfunktion und einen Zähler). Dies ist rein gnu make, keine Shell-Anforderung (obwohl das OP offensichtlich jedes Mal ein Programm ausführen wollte - hier zeige ich lediglich eine Nachricht an). Das if in ITERATE soll den Wert 0 abfangen, da sonst $ (word ...) fehlerhaft wird.
Beachten Sie, dass die wachsende Zeichenfolge, die als Zähler dient, verwendet wird, da das eingebaute $ (Wörter ...) eine arabische Zählung liefern kann, aber make ansonsten keine mathematischen Operationen unterstützt (Sie können etwas nicht 1 + 1 zuweisen und 2 erhalten, es sei denn, Sie rufen etwas aus der Shell auf, um es für Sie zu erledigen, oder verwenden eine ebenso komplizierte Makrooperation. Dies funktioniert hervorragend für einen INCREMENTAL-Zähler, jedoch nicht so gut für einen DECREMENT-Zähler.
Ich benutze dies nicht selbst, aber kürzlich musste ich eine rekursive Funktion schreiben, um Bibliotheksabhängigkeiten in einer Umgebung mit mehreren Binärdateien und mehreren Bibliotheken zu bewerten, in der Sie wissen müssen, wie Sie ANDERE Bibliotheken einbinden können, wenn Sie eine Bibliothek hinzufügen, die selbst hat andere Abhängigkeiten (von denen einige abhängig von den Build-Parametern variieren), und ich verwende eine $ (eval) - und Zählermethode ähnlich der oben genannten (in meinem Fall wird der Zähler verwendet, um sicherzustellen, dass wir nicht irgendwie in ein Endlos geraten Schleife und auch als Diagnose, um zu melden, wie viel Iteration erforderlich war).
Etwas anderes, das nichts wert ist, obwohl es für das Q: $ (eval ...) des OP nicht von Bedeutung ist, bietet eine Methode, um die interne Abscheu von make gegenüber Zirkelverweisen zu umgehen. Dies ist alles gut und in Ordnung, wenn eine Variable ein Makrotyp ist (initialisiert mit =) gegen eine sofortige Zuordnung (initialisiert mit: =). Es gibt Zeiten, in denen Sie eine Variable innerhalb ihrer eigenen Zuweisung verwenden möchten, und mit $ (eval ...) können Sie dies tun. Hierbei ist zu beachten, dass zum Zeitpunkt der Ausführung der Auswertung die Variable aufgelöst wird und der aufgelöste Teil nicht mehr als Makro behandelt wird. Wenn Sie wissen, was Sie tun, und Sie versuchen, eine Variable auf der rechten Seite einer Zuweisung für sich selbst zu verwenden, möchten Sie dies im Allgemeinen trotzdem tun.
Happy make'ing.
quelle
Konfigurieren Sie für die plattformübergreifende Unterstützung das Befehlstrennzeichen (zum Ausführen mehrerer Befehle in derselben Zeile).
Wenn Sie MinGW beispielsweise auf einer Windows-Plattform verwenden, lautet das Befehlstrennzeichen
&
:Dadurch werden die verketteten Befehle in einer Zeile ausgeführt:
Wie an anderer Stelle erwähnt, auf einer * nix-Plattform verwenden
CMDSEP = ;
.quelle
Dies ist keine reine Antwort auf die Frage, sondern eine intelligente Methode, um solche Probleme zu umgehen:
Anstatt eine komplexe Datei zu schreiben, delegieren Sie die Steuerung einfach an beispielsweise ein Bash-Skript wie: makefile
und script.sh sieht aus wie:
quelle
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var here SSA_CORE0_MAINEXEC ist eine Umgebungsvariable, die bereits festgelegt ist. Daher möchte ich, dass dieser Wert mit der Variablen var1 ausgewertet oder gedruckt wird. Ich habe es wie oben gezeigt versucht, aber es funktioniert nicht. Bitte helfen Sie.bash
und somit die Funktionen verwenden. Die Schleife ist eines der Merkmale, für die dies demonstriert werden kann.Vielleicht können Sie verwenden:
quelle
Sie können
set -e
als Präfix für die for-Schleife verwenden. Beispiel:make
wird sofort mit einem Exit-Code beendet<> 0
.quelle
Obwohl das GNUmake-Tabellen-Toolkit eine echte
while
Schleife hat (was auch immer dies in der GNUmake-Programmierung mit zwei oder drei Ausführungsphasen bedeutet), gibt es eine einfache Lösung mit, wenn eine iterative Liste benötigt wirdinterval
. Zum Spaß konvertieren wir die Zahlen auch in Hex:Ausgabe:
quelle
Eine einfache, Shell / Plattform-unabhängige, reine Makrolösung ist ...
quelle
quelle