O seguinte será feito se, como eu suponho pelo seu uso ./a.out, você estiver em uma plataforma do tipo UNIX.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Teste da seguinte maneira:
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
produz:
1
2
3
4
Para intervalos maiores, use:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
Isso gera de 1 a 10 inclusive, basta alterar a whilecondição de término de 10 para 1000 para um intervalo muito maior, conforme indicado no seu comentário.
qwert é apenas um nome de destino que dificilmente será um arquivo real. Regras de makefile precisam de um destino. Quanto ao erro de sintaxe, você está perdendo algumas coisas - consulte a atualização.
paxdiablo
2
Como você está assumindo que seu shell reconhece ((...)), por que não usar o mais simples para ((i = 0; i <WHATEVER; ++ i)); Faz ...; feito ?
Idelic
1
Observe que o seqcomando que gera uma sequência de números existe na maioria dos sistemas unix (todos?), Para que você possa escrever for number in ``seq 1 1000``; do echo $$number; done(Coloque um único bastão em cada lado do comando seq, e não dois, não sei como formatar isso corretamente usando a sintaxe do stackoverflow)
Suzanne Dupéron 23/09
3
Obrigado, estava faltando o $$ duplo para fazer referência à variável de loop for.
Leif Gruenwoldt 4/10/2013
1
@ Jonz: o caractere de continuação de linha é porque makenormalmente trata cada linha como uma coisa a ser executada em um sub-shell separado . Sem continuação, ele tentaria executar um subshell com just (por exemplo) for number in 1 2 3 4 ; do, sem o restante do loop. Com isso, ele se torna efetivamente uma única linha do formulário while something ; do something ; done, que é uma declaração completa. A $$pergunta é respondida aqui: stackoverflow.com/questions/26564825/... , com o código aparentemente extraído dessa resposta muito :-)
paxdiablo
265
Se você estiver usando o GNU make, você pode tentar
Esta resposta é IMHO melhor, porque não requer o uso de nenhum shell, é puro makefile (mesmo que seja específico do GNU).
Jocelyn delalande
7
o ponto e vírgula é crucial caso contrário, apenas a primeira iteração irá executar
Jeremy Leipzig
7
Esta solução oculta o código de saída de ./a.out 1. ./a.out 2será executado independentemente.
precisa saber é o seguinte
1
@ Alexander: você poderia elaborar a que limitação você está se referindo?
Idelic
1
@ Idelic, sim. Para o seguinte makefile e shellscript, o shellscript funciona (passa o argumento para ls), enquanto o Makefile fornece um erro: make: execvp: / bin / sh: Lista de argumentos muito longa Makefile: ix.io/d5L Shellscript: ix.io / d5M Esse é um problema na função foreach que encontrei no trabalho, quando uma lista incomumente longa de nomes de arquivos (com caminhos longos também) era passada para um comando. Tivemos que encontrar uma solução alternativa.
22414 Alexander
107
A principal razão para usar make IMHO é a-j bandeira. make -j5irá executar 5 comandos de shell de uma só vez. Isso é bom se você tiver 4 CPUs, e um bom teste de qualquer makefile.
para o mesmo efeito (sim, é o mesmo que a formulação anterior no que diz respeito ao make , apenas um pouco mais compacto).
Um pouco mais de parametrização para que você possa especificar um limite na linha de comando (tedioso, pois makenão possui boas macros aritméticas, por isso vou trapacear aqui e usar $(shell ...))
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Você executa isso com make -j5 LAST=550, com o LASTpadrão 1000.
Esta é definitivamente a melhor resposta, pelo motivo que o bobbogo mencionou ( -j ).
dbn
Algum motivo específico para usar sufixos .PHONY? Eles são necessários para alguma coisa?
Seb
6
@seb: Sem .PHONY: all, o make procurará um arquivo chamado all. Se esse arquivo existir, verifique se o arquivo foi modificado pela última vez, e o makefile quase certamente não fará o que você pretendia. A .PHONYdeclaração diz ao make que allé um alvo simbólico. A Make considerará, portanto, a allmeta sempre desatualizada. Perfeito. Veja o manual.
@JoeS gnu.org/software/make/manual/make.html#Static-Pattern (acho que você quis dizer o que é o segundo * dois pontos * ). Não os confunda com as Regras de Padrão Desagradáveis (IMHO) . As regras de padrões estáticos são realmente úteis sempre que a lista de destinos pode ser correspondida por um dos padrões nodosos de make (o mesmo se aplica às dependências). Aqui eu uso um apenas para a comodidade de que qualquer que seja o que corresponde %à regra está disponível como $*na receita.
22414 bobbogo
22
Sei que a pergunta tem vários anos, mas este post ainda pode ser útil para alguém, pois demonstra uma abordagem diferente da anterior, e não depende de operações do shell nem da necessidade de o desenvolvedor extrair um código codificado sequência de valores numéricos.
a macro embutida $ (eval ....) é sua amiga. Ou pode ser pelo menos.
Esse é um exemplo simplista. Ele não será escalável para valores grandes - funciona, mas como a sequência ITERATE_COUNT aumenta em 2 caracteres (espaço e ponto) para cada iteração, à medida que você aumenta os milhares, leva progressivamente mais tempo para contar as palavras. Como está escrito, ele não trata de iteração aninhada (você precisaria de uma função de iteração separada e de um contador para fazer isso). Isso é puramente gnu make, sem necessidade de shell (embora obviamente o OP esteja procurando executar um programa a cada vez - aqui, estou apenas exibindo uma mensagem). O if dentro de ITERATE tem como objetivo capturar o valor 0, porque $ (word ...) ocorrerá um erro caso contrário.
Observe que a cadeia crescente para servir como contador é empregada porque o $ (words ...) builtin pode fornecer uma contagem arábica, mas essa marca não suporta operações matemáticas (você não pode atribuir 1 + 1 a algo e obter 2, a menos que você esteja invocando algo do shell para fazer isso por você ou usando uma operação macro igualmente complicada). Isso funciona muito bem para um contador INCREMENTAL, no entanto, não tão bem para um DECREMENT.
Eu não uso isso sozinho, mas recentemente precisei escrever uma função recursiva para avaliar as dependências da biblioteca em um ambiente de compilação multi-binária e com várias bibliotecas, onde você precisa saber para trazer OUTRAS bibliotecas quando incluir alguma biblioteca que em si tem outras dependências (algumas das quais variam dependendo dos parâmetros de compilação), e eu uso um método $ (eval) e counter semelhante ao descrito acima (no meu caso, o contador é usado para garantir que de alguma forma não entremos em um interminável loop e também como um diagnóstico para relatar a quantidade de iteração necessária).
Outra coisa que não vale nada, embora não seja significativa para o Q: $ do OP (eval ...), fornece um método para contornar a aversão interna do make a referências circulares, o que é bom e bom de aplicar quando uma variável é do tipo macro (inicializada com =) versus uma atribuição imediata (inicializada com: =). Há momentos em que você deseja usar uma variável dentro de sua própria atribuição, e $ (eval ...) permitirá que você faça isso. O importante a considerar aqui é que, no momento em que você executa a avaliação, a variável é resolvida e a parte resolvida não é mais tratada como uma macro. Se você sabe o que está fazendo e está tentando usar uma variável no RHS de uma tarefa para si mesma, geralmente é isso que você deseja que aconteça.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Fiquei paralisado enquanto escrevia um Makefile. Eu tenho o seguinte código: set_var: @ NUM = 0; while [[$$ NUM <1]]; faça eco "estou aqui"; \ echo $$ NUM despejo $$ {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 é uma variável de ambiente que já está configurada. Portanto, desejo que esse valor seja avaliado ou impresso usando a variável var1. Eu tentei como mostrado acima, mas não está funcionando. por favor ajude.
XYZ_Linux 17/01
2
Essa é realmente uma solução fácil, mas impede que você use a boa opção "make -j 4" para que os processos sejam executados em paralelo.
TabeaKischka
1
@TabeaKischka: de fato. Não era o caminho " recomendado ", mas é mais importante se você precisar de alguns recursos que não são oferecidos por um Makefile, e então poderá recorrer a uma implementação bashe, assim, usá-los. O loop é um dos recursos pelos quais isso pode ser demonstrado.
Embora o kit de ferramentas da tabela GNUmake possua um whileloop verdadeiro (o que quer que isso signifique na programação do GNUmake com suas duas ou três fases de execução), se o necessário é uma lista iterativa, existe uma solução simples interval. Por diversão, também convertemos os números em hexadecimal:
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.
Respostas:
O seguinte será feito se, como eu suponho pelo seu uso
./a.out
, você estiver em uma plataforma do tipo UNIX.Teste da seguinte maneira:
produz:
Para intervalos maiores, use:
Isso gera de 1 a 10 inclusive, basta alterar a
while
condição de término de 10 para 1000 para um intervalo muito maior, conforme indicado no seu comentário.Loops aninhados podem ser feitos assim:
produzindo:
fonte
seq
comando que gera uma sequência de números existe na maioria dos sistemas unix (todos?), Para que você possa escreverfor number in ``seq 1 1000``; do echo $$number; done
(Coloque um único bastão em cada lado do comando seq, e não dois, não sei como formatar isso corretamente usando a sintaxe do stackoverflow)make
normalmente trata cada linha como uma coisa a ser executada em um sub-shell separado . Sem continuação, ele tentaria executar um subshell com just (por exemplo)for number in 1 2 3 4 ; do
, sem o restante do loop. Com isso, ele se torna efetivamente uma única linha do formuláriowhile something ; do something ; done
, que é uma declaração completa. A$$
pergunta é respondida aqui: stackoverflow.com/questions/26564825/... , com o código aparentemente extraído dessa resposta muito :-)Se você estiver usando o GNU make, você pode tentar
que irá gerar e executar
fonte
./a.out 1
../a.out 2
será executado independentemente.A principal razão para usar make IMHO é a
-j
bandeira.make -j5
irá executar 5 comandos de shell de uma só vez. Isso é bom se você tiver 4 CPUs, e um bom teste de qualquer makefile.Basicamente, você quer ver algo como:
Isso é
-j
amigável (um bom sinal). Você consegue identificar a placa da caldeira? Poderíamos escrever:para o mesmo efeito (sim, é o mesmo que a formulação anterior no que diz respeito ao make , apenas um pouco mais compacto).
Um pouco mais de parametrização para que você possa especificar um limite na linha de comando (tedioso, pois
make
não possui boas macros aritméticas, por isso vou trapacear aqui e usar$(shell ...)
)Você executa isso com
make -j5 LAST=550
, com oLAST
padrão 1000.fonte
.PHONY: all
, o make procurará um arquivo chamadoall
. Se esse arquivo existir, verifique se o arquivo foi modificado pela última vez, e o makefile quase certamente não fará o que você pretendia. A.PHONY
declaração diz ao make queall
é um alvo simbólico. A Make considerará, portanto, aall
meta sempre desatualizada. Perfeito. Veja o manual.%
à regra está disponível como$*
na receita.Sei que a pergunta tem vários anos, mas este post ainda pode ser útil para alguém, pois demonstra uma abordagem diferente da anterior, e não depende de operações do shell nem da necessidade de o desenvolvedor extrair um código codificado sequência de valores numéricos.
a macro embutida $ (eval ....) é sua amiga. Ou pode ser pelo menos.
Esse é um exemplo simplista. Ele não será escalável para valores grandes - funciona, mas como a sequência ITERATE_COUNT aumenta em 2 caracteres (espaço e ponto) para cada iteração, à medida que você aumenta os milhares, leva progressivamente mais tempo para contar as palavras. Como está escrito, ele não trata de iteração aninhada (você precisaria de uma função de iteração separada e de um contador para fazer isso). Isso é puramente gnu make, sem necessidade de shell (embora obviamente o OP esteja procurando executar um programa a cada vez - aqui, estou apenas exibindo uma mensagem). O if dentro de ITERATE tem como objetivo capturar o valor 0, porque $ (word ...) ocorrerá um erro caso contrário.
Observe que a cadeia crescente para servir como contador é empregada porque o $ (words ...) builtin pode fornecer uma contagem arábica, mas essa marca não suporta operações matemáticas (você não pode atribuir 1 + 1 a algo e obter 2, a menos que você esteja invocando algo do shell para fazer isso por você ou usando uma operação macro igualmente complicada). Isso funciona muito bem para um contador INCREMENTAL, no entanto, não tão bem para um DECREMENT.
Eu não uso isso sozinho, mas recentemente precisei escrever uma função recursiva para avaliar as dependências da biblioteca em um ambiente de compilação multi-binária e com várias bibliotecas, onde você precisa saber para trazer OUTRAS bibliotecas quando incluir alguma biblioteca que em si tem outras dependências (algumas das quais variam dependendo dos parâmetros de compilação), e eu uso um método $ (eval) e counter semelhante ao descrito acima (no meu caso, o contador é usado para garantir que de alguma forma não entremos em um interminável loop e também como um diagnóstico para relatar a quantidade de iteração necessária).
Outra coisa que não vale nada, embora não seja significativa para o Q: $ do OP (eval ...), fornece um método para contornar a aversão interna do make a referências circulares, o que é bom e bom de aplicar quando uma variável é do tipo macro (inicializada com =) versus uma atribuição imediata (inicializada com: =). Há momentos em que você deseja usar uma variável dentro de sua própria atribuição, e $ (eval ...) permitirá que você faça isso. O importante a considerar aqui é que, no momento em que você executa a avaliação, a variável é resolvida e a parte resolvida não é mais tratada como uma macro. Se você sabe o que está fazendo e está tentando usar uma variável no RHS de uma tarefa para si mesma, geralmente é isso que você deseja que aconteça.
Feliz fazendo.
fonte
Para suporte a várias plataformas, configure o separador de comandos (para executar vários comandos na mesma linha).
Se você estiver usando o MinGW em uma plataforma Windows, por exemplo, o separador de comandos é
&
:Isso executa os comandos concatenados em uma linha:
Como mencionado em outro lugar, em uma plataforma * nix, use
CMDSEP = ;
.fonte
Esta não é realmente uma resposta pura para a pergunta, mas uma maneira inteligente de solucionar esses problemas:
em vez de escrever um arquivo complexo, simplesmente delegue o controle para, por exemplo, um script bash como: makefile
e script.sh se parece com:
fonte
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var here SSA_CORE0_MAINEXEC é uma variável de ambiente que já está configurada. Portanto, desejo que esse valor seja avaliado ou impresso usando a variável var1. Eu tentei como mostrado acima, mas não está funcionando. por favor ajude.bash
e, assim, usá-los. O loop é um dos recursos pelos quais isso pode ser demonstrado.Talvez você possa usar:
fonte
Você pode usar
set -e
como um prefixo para o loop for. Exemplo:make
sairá imediatamente com um código de saída<> 0
.fonte
Embora o kit de ferramentas da tabela GNUmake possua um
while
loop verdadeiro (o que quer que isso signifique na programação do GNUmake com suas duas ou três fases de execução), se o necessário é uma lista iterativa, existe uma solução simplesinterval
. Por diversão, também convertemos os números em hexadecimal:Resultado:
fonte
Uma solução macro pura, simples e independente de shell / plataforma é ...
fonte
fonte