문제

내 응용 프로그램 메인 디렉토리에는 "lib"디렉토리가 있으며, 여기에는 임의의 하위 디렉토리가 포함되어 있으며 각각 고유 한 Makefile이 있습니다.

메인 디렉토리에 단일 MakeFile을 원합니다. 각 하위 디렉토리의 MakeFile을 호출합니다. 서브 디르를 수동으로 나열하면 이것이 가능하다는 것을 알고 있지만 자동으로 수행하고 싶습니다.

나는 다음과 같은 것을 생각하고 있었지만 분명히 작동하지 않습니다. 또한 깨끗하고 테스트 등을 가지고 있습니다. 대상이 있으므로 %는 전혀 좋은 생각이 아닙니다.

LIBS=lib/*

all: $(LIBS)

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

모든 도움이 감사합니다!

도움이 되었습니까?

해결책

다음은 GNU와 함께 작동합니다 make:

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

디렉토리 이외의 것이있을 수 있습니다 lib, 당신은 대안 적으로 사용할 수 있습니다 :

LIBS=$(shell find lib -type d)

여러 대상 문제를 해결하려면 각 디렉토리에 대한 특수 대상을 구축 한 다음 하위 구축을 위해 접두사를 벗겨 낼 수 있습니다.

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

다른 팁

쉘 명령을 사용하지 않고 GMAKE 명령 만 사용하여 하위 다이렉터를 나열하는 방법도 있습니다.

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

여기에는 모든 하위 디렉토리에 후행이 나열됩니다 '/'. 제거하려면 대체 패턴을 사용할 수 있습니다.

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

그런 다음 실제로 각 하위 디렉토리에서 makefiles를 실행하는 규칙을 만들려면 존재하지 않는 디렉토리의 가짜 목표 인 작은 트릭을 사용할 수 있습니다. 이 경우 예제는 어떤 설명보다 더 많은 설명을 할 것이라고 생각합니다.

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

기본적으로 대상 'all' 모든 하위 디렉터를 전제 조건으로 나열합니다. 예를 들어, if LIB_DIRS 포함 lib/folder1 lib/folder2 그러면 확장은 다음과 같습니다.

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

그런 다음 규칙을 실행하기 위해 '만들기' 'all', 각 전제 조건을 기존 목표와 일치 시키려고합니다. 이 경우 대상은 다음과 같습니다 'make-rule/%:', 사용하는 '$*' 이후에 문자열을 추출합니다 'make-rule/' 레시피에서 논쟁으로 사용합니다. 예를 들어, 첫 번째 전제 조건은 다음과 같이 일치하고 확장됩니다.

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

알려지지 않은 수의 하위 디렉터에서 다른 대상을 모두 호출하려면 어떻게해야합니까?

다음 makefile은 매크로를 사용하므로 여러 하위 디렉토리가 명령 줄에서 각각의 대상을 적용 할 수 있도록 전달 더미 타겟을 만듭니다.

# 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))))

도움이 되었기를 바랍니다. Paralelism을 다룰 때 정말 도움이됩니다. -J12 Makefiles를 가진 나무에서 모든 것을 청소하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top