Se o seu trecho de código é adequadamente representativo, parece que você está digitando comandos Bash diretamente no seu Makefile e esperando que o Make os execute com o Bash. Não é assim que funciona. A sintaxe de um Makefile é totalmente diferente. Dentro de uma receita, você pode digitar comandos Bash; Cada linha separada em uma receita será executada em uma sub-shell separada. Então você precisa de pelo menos duas mudanças:
- Seus comandos do shell precisam estar em um destino.
- O
declare
precisa ser executado no mesmo shell que o loop; caso contrário vocêdeclare
em uma instância de Bash, saia dessa e execute o loop em uma instância separada que não sabe nada sobre a perda dedeclare
.
Aqui está uma refatoração simples do seu Makefile com essas alterações.
SHELL=/bin/bash # This is the standard compliant method
.PHONY: all
all:
declare -A PROVS=( ["NL"]=10 ["PE"]=11 ["NS"]=12 ["NB"]=13 \
["QC"]=24 ["ON"]=35 ["MB"]=46 ["SK"]=47 ["AB"]=48 \
["BC"]=59 ["YK"]=60 ["NT"]=61 ["NU"]=62 )\
; for key in "$${!PROVS[@]}" ; do \
touch "foo_$${key}_$${PROVS[$${key}]}" ; \
done
Demo: link
A convenção @
para executar um comando aplica-se silenciosamente a toda a linha de comando. Portanto, você pode colocá-lo antes de declare
acima e, nesse caso, ele será retirado antes que toda a linha de comando seja enviada para o Bash. Em qualquer outro lugar, ele não será removido ou entendido, e obviamente causará um erro de sintaxe Bash no shell chamado.
(A obsessão com as regras @
é um antipadrão de qualquer maneira. Execute com make -s
se você não quiser ver a saída; encerrar make
só tornará mais difícil depurar suas regras.)