Tenho o seguinte exemplo de Makefile:
BUILD = build
PATH_POT3 = src/pot/pot3/
MPIFC = mpiifort
FFLAGS = -O3
MOL_LIST = $(shell find $(PATH_POT3) -mindepth 1 -maxdepth 1 -type d)
$(foreach MOL,$(MOL_LIST), \
$(eval LIST_MOL := $(shell find $(MOL) -name "*.f90")) \
$(info Fortran files: $(LIST_MOL)) \
$(foreach SRC,$(LIST_MOL), \
$(eval OBJ := $(BUILD)/$(notdir $(SRC:.f90=.o))) \
$(OBJ): $(SRC) ; \
$(info Compiling: $(SRC)) \
$(info Output: $(OBJ)) \
$(MPIFC) $(FFLAGS) -c $(SRC) -o $(OBJ) \
) \
)
all: $(foreach MOL,$(MOL_LIST),\
$(foreach SRC,$(shell find $(MOL) -name "*.f90"),\
$(BUILD)/$(notdir $(SRC:.f90=.o))\
)\
)
Aqui, eu gostaria de compilar o conteúdo (recursivo) de cada PATH_POT3
subdiretório de forma sequencial (um subdiretório após o outro). Infelizmente, essa construção não fornece o resultado desejado, pois compila apenas o primeiro arquivo-objeto da lista, ignorando todos os outros. O Makefile imprime as seguintes informações para o meu caso de teste:
Fortran files: src/pot/pot3/ar3/pot_ar3.f90 src/pot/pot3/ar3/ar43/pot_ar43.f90
Compiling: mpiifort -O3 -c src/pot/pot3/ar3/pot_ar3.f90 -o build/pot_ar3.o
Output: build/pot_ar3.o
Compiling: mpiifort -O3 -c src/pot/pot3/ar3/ar43/pot_ar43.f90 -o build/pot_ar43.o
Output: build/pot_ar43.o
Fortran files: src/pot/pot3/ar33/pot_ar33.f90 src/pot/pot3/ar33/pot_ar333.f90 src/pot/pot3/ar33/ar53/pot_ar53.f90
Compiling: mpiifort -O3 -c src/pot/pot3/ar33/pot_ar33.f90 -o build/pot_ar33.o
Output: build/pot_ar33.o
Compiling: mpiifort -O3 -c src/pot/pot3/ar33/pot_ar333.f90 -o build/pot_ar333.o
Output: build/pot_ar333.o
Compiling: mpiifort -O3 -c src/pot/pot3/ar33/ar53/pot_ar53.f90 -o build/pot_ar53.o
Output: build/pot_ar53.o
make: 'build/pot_ar3.o' is up to date.
Tudo parece estar configurado corretamente, mas a compilação é executada somente para build/pot_ar3.o
.
Como devo alterar este arquivo para obter o comportamento necessário?
O problema está na forma como você está tentando criar definições de regras dentro do
foreach
loop. Suas instruções info mostram que tudo está sendo detectado corretamente, mas apenas o primeiro arquivo de objeto está sendo compilado. Isso acontece porque o Make não processa regras definidas dinamicamente dentro dos loops da maneira que você espera.Aqui está uma solução funcional:
A chave aqui é usar
eval
para criar regras Make adequadas a partir damake-depend
função. Sua abordagem original imprimia os comandos durante a fase de análise, mas não configurava corretamente as regras em si.Isso funciona encontrando todos os arquivos de origem antecipadamente e criando uma regra apropriada para cada arquivo usando
eval
amake-depend
função. O|
símbolo garante que o diretório de compilação exista antes do início da compilação.Espero que isso funcione para você.
** Editar **
Foi isso que discutimos no chat: