Pergunta

Eu tenho um diretório "lib" no diretório principal dos meus aplicativos, que contém um número arbitrário de subdiretos, cada um com seu próprio makefile.

Eu gostaria de ter um único makefile no diretório principal, que chama o makefile de cada subdiretório. Sei que isso é possível se eu listar manualmente os subdirs, mas gostaria de fazê -lo automaticamente.

Eu estava pensando em algo como o seguinte, mas obviamente não funciona. Observe que eu também tenho alvos limpos, de teste, etc., então % provavelmente não é uma boa ideia.

LIBS=lib/*

all: $(LIBS)

%:
  (cd $@; $(MAKE))

Qualquer ajuda é apreciada!

Foi útil?

Solução

O seguinte funcionará com GNU make:

LIBS=$(wildcard lib/*)
all: $(LIBS)
.PHONY: force
$(LIBS): force
  cd $@ && pwd

Se houver algo diferente de diretórios em lib, você pode usar alternativamente:

LIBS=$(shell find lib -type d)

Para resolver o problema de vários alvos, você pode criar metas especiais para cada diretório e retirar o prefixo para a sub-construção:

LIBS=$(wildcard lib/*)
clean_LIBS=$(addprefix clean_,$(LIBS))
all: $(LIBS)
clean: $(clean_LIBS)
.PHONY: force
$(LIBS): force
  echo make -C $@
$(clean_LIBS): force
  echo make -C $(patsubst clean_%,%,$@) clean

Outras dicas

Há também uma maneira de listar apenas os subdiretos com comandos GMake, sem usar comandos do shell:

test:
  @echo $(filter %/, $(wildcard lib/*/))

Isso listará todos os subdiretos com a direita '/'. Para removê -lo, você pode usar o padrão substituto:

subdirs = $(filter %/, $(wildcard lib/*/))
test:
  @echo $(subdirs:%/=%)

Em seguida, para criar regras que executam o Makefiles em cada subdiretório, você pode usar um pequeno truque-um alvo falso em um diretório inexistente. Eu acho que neste caso um exemplo dirá mais do que qualquer explicação:

FULL_DIRS =$(filter %/, $(wildcard lib/*/))
LIB_DIRS  =$(FULL_DIRS:%/=%)
DIRS_CMD  =$(foreach subdir, $(LIB_DIRS), make-rule/$(subdir))

make-rule/%:
  cd $* && $(MAKE)

all: DIRS_CMD

Basicamente, alvo 'all' Liste todos os subdiretos como pré-requisitos. Por exemplo, se LIB_DIRS contido lib/folder1 lib/folder2 Então a expansão ficaria assim:

all: make-rule/lib/folder1 make-rule/lib/folder2

Então 'Make', para executar a regra 'all', tenta combinar cada pré -requisito com um alvo existente. Nesse caso, o alvo é 'make-rule/%:', que usa '$*' Para extrair a corda depois 'make-rule/' e o usa como argumento na receita. Por exemplo, o primeiro pré -requisito seria correspondido e expandido assim:

make-rule/lib/folder1:
  cd lib/folder1 && $(MAKE)

E se você quiser chamar alvos diferentes de todos em um número desconhecido de subdiretos?

O seguinte Makefile usa macros, portanto, crie um alvo dummy de encaminhamento para várias subdiretas para aplicar o alvo especificado da linha de comando a cada um deles:

# all direct directories of this dir. uses "-printf" to get rid of the "./"
DIRS=$(shell find . -maxdepth 1 -mindepth 1 -type d -not -name ".*" -printf '%P\n')
# "all" target is there by default, same logic as via the macro
all: $(DIRS)

$(DIRS):
    $(MAKE) -C $@
.PHONY: $(DIRS)

# if explcit targets where given: use them in the macro down below. each target will be delivered to each subdirectory contained in $(DIRS).
EXTRA_TARGETS=$(MAKECMDGOALS)

define RECURSIVE_MAKE_WITH_TARGET
# create new variable, with the name of the target as prefix. it holds all
# subdirectories with the target as suffix
$(1)_DIRS=$$(addprefix $(1)_,$$(DIRS))

# create new target with the variable holding all the subdirectories+suffix as
# prerequisite
$(1): $$($1_DIRS)

# use list to create target to fullfill prerequisite. the rule is to call
# recursive make into the subdir with the target
$$($(1)_DIRS):
      $$(MAKE) -C $$(patsubst $(1)_%,%,$$@) $(1)

# and make all targets .PHONY
.PHONY: $$($(1)_DIRS)
endef

# evaluate the macro for all given list of targets
$(foreach t,$(EXTRA_TARGETS),$(eval $(call RECURSIVE_MAKE_WITH_TARGET,$(t))))

Espero que isto ajude. Realmente útil ao lidar com o paralelismo: faça -j12 limpar tudo em uma árvore com osfiles com esses alvos ... como sempre: brincar com make é perigoso, diferentes níveis de programação estão muito próximos,-)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top