GNU make: Como chamar $ (wildcard) dentro de $ (eval)
Pergunta
Eu estou tentando criar um modelo de construção genérico para o meu Makefiles, tipo como eles discutem na eval documentação .
Eu não consigo obter a função de curinga para trabalhar dentro de um eval. O código básico Estou tendo problemas com a aparência como esta.
SRC_DIR = ./src/
PROG_NAME = test
define PROGRAM_template
$(1)_SRC_DIR = $(join $(SRC_DIR), $(1)/)
$(1)_SRC_FILES = $(wildcard $$($(1)_SRC_DIR)*.c)
endef
$(eval $(call PROGRAM_template, $(PROG_NAME)))
all:
@echo $(test_SRC_DIR)
@echo $(test_SRC_FILES)
@echo $(wildcard $(wildcard $(test_SRC_DIR)*.c)
Quando eu executar make com isso, a saída é
./src/test
[correct list of all .c files in ./src/test/]
Basicamente, a chamada curinga dentro PROGRAM_template não está sendo eval'd como eu espera. A chamada resulta em uma lista vazia.
A chamada juntar está sendo eval'd corretamente embora.
Então, o que estou fazendo de errado? Meu palpite é que
$$($(1)_SRC_DIR)
não é correto, mas eu não consigo descobrir o caminho certo para fazê-lo.
Editar Uma vez que isso foi resolvido, não demorou muito para me bater outro problema com eval. Eu postei isso como uma nova questão em Solução para o GNU Make 3,80 eval bug
Solução
Você precisa dupla fuga praticamente todas as funções e variáveis ??quando você usa eval
. Na maioria dos casos, as únicas coisas que não necessidade de estar com duplo escape são argumentos de função (porque a função call
será totalmente expandi-las). Neste caso, você tecnicamente não precisa join
duplo-escape ou SRC_DIR
quer, mas vai simplificar a sua vida se você simplesmente sempre duas vezes escapar de todas as variáveis ??e funções ao usar eval
.
A razão que você precisa os escapes duplos é que a expansão acontece duas vezes ao usar eval
. A função eval
si realiza expansão, e, em seguida, a expansão é feita novamente quando o bloco é finalmente analisada como makefile sintaxe (isto é, quando ela é realmente avaliada).
A forma como você tem isso por escrito, wildcard
é chamado no $( test_SRC_DIR)*.c
literal string. Se você quiser, você pode ver isso por si mesmo, substituindo wildcard
com info
na sua versão e ver o que acontece.
Você precisa adiar a verdade invocando wildcard
até a segunda expansão, de modo que o argumento é o resultado da expansão da $(test_SRC_DIR)
.
Tente isto:
SRC_DIR = ./src/
PROG_NAME = test
define PROGRAM_template
$(1)_SRC_DIR = $$(join $$(SRC_DIR),$(1)/)
$(1)_SRC_FILES = $$(wildcard $$($(1)_SRC_DIR)*.c)
endef
$(eval $(call PROGRAM_template,$(PROG_NAME)))
all:
@echo $(test_SRC_DIR)
@echo $(test_SRC_FILES)
@echo $(wildcard $(test_SRC_DIR)*.c)
Editar : Depois de postar isso, eu pensei que eu iria testá-lo melhor para se certificar de que ele realmente funciona. Ao fazê-lo, descobri um outro problema. Você deve evitar colocar espaços entre a vírgula e argumento ao chamar funções. Isso faz com que um caractere de espaço literal para ser anexado ao argumento que é passado para a função e leva a resultados indesejados. Eu removi os espaços após as vírgulas nas chamadas de função na minha versão (enquanto isso não é um problema para a chamada para join
, tirei o espaço lá também só porque ele é um bom hábito de entrar).