2014-07-11 4 views
2

this 종이 인 경우 재귀 메이크 파일 질문이있을 때마다 내 검색 결과가 모두 엉망으로 보이는 경우 전체 프로젝트를 명령 행에서 단일 Makefile로 변환하려고합니다. 그러나, 나는 어떻게 근본적인 문제에 부딪쳐서 내가 어떻게 대처할 지 확신 할 수 없다. 모든 Makefile 모듈에 공통적이지만 동일하지 않은 변수를 정의하고 싶습니다. 이렇게하려면 내가 먼저 Makefile.var 파일을 만든 :범위가 지정된 변수를 사용하는 글로벌 Makefile

# ============================================================================ 
# Common aliases for local dirs 
# ============================================================================ 
# Every make module must define WORKING_DIR := 
BIN = $(WORKING_DIR)/bin 
OBJ = $(WORKING_DIR)/obj 
SRC = $(WORKING_DIR)/src 
DEP = $(WORKING_DIR)/obj 
INC = $(WORKING_DIR)/include 
INCLUDES = -I$(INC) 

ALL_SRCS = $(wildcard $(SRC)/*.C) 
ALL_INCS = $(wildcard $(INC)/*.h) 
ALL_OBJS = $(subst $(SRC),$(OBJ),$(ALL_SRCS:%.C=%.o)) 
ALL_DEPS = $(subst $(SRC),$(DEP),$(ALL_SRCS:%.C=%.d)) 

이 먼저 마스터 파일에 포함 된 Makefile.var 파일에 있습니다. 그 후에, 후속 메이크 파일 모듈이 포함됩니다. 여기 내 주인은 Makefile :

include MakeModules/Makefile.var 
include MakeModules/Makefile.tools 

clean: $(CLEAN_LIST) 

all: $(MAKE_LIST) 

마지막으로 다음은 모듈의 모습입니다. 쉽게 동일한 모듈을 두 번 복사하여 붙여 넣을 것이고 두 번째 인스턴스의 이름을 조정할 것입니다. 이 Makefile.tools입니다 :

# ============================================================================ 
# queuing (QUE) 
# ============================================================================ 
WORKING_DIR := $(TOP)/tools/queuing 
QUE_TARGET := libqueue.so 

-include $(DEP)/*.d 

$(QUE_TARGET): $(ALL_OBJS) 
    $(CPP) $(CFLAGS) -shared -o [email protected] $(ALL_OBJS) 

que-clean: 
    -rm -f $(OBJ)/*.o $(DEP)/*.d 

CLEAN_LIST += que-clean 
MAKE_LIST += $(QUE_TARGET) 

# ============================================================================ 
# queuing2 (QUE2) 
# ============================================================================ 
WORKING_DIR := $(TOP)/tools/queuing2 
QUE2_TARGET := libqueue2.so 

-include $(DEP)/*.d 

$(QUE2_TARGET): $(ALL_OBJS) 
    $(CPP) $(CFLAGS) -shared -o [email protected] $(ALL_OBJS) 

que2-clean: 
    -rm -f $(OBJ)/*.o $(DEP)/*.d 

CLEAN_LIST += que2-clean 
MAKE_LIST += $(QUE2_TARGET) 

당신이 볼 수 있듯이이 Makefile.toolsWORKING_DIR의 값에 따라 Makefile.var에서 파생 변수를 사용합니다. 음, make이하는 2 단계 읽기 때문에 실제로 작동하지 않습니다. WORKING_DIR 변수는 마지막으로 알려진 할당에만 적용되며 ALL_OBJS은 위치에 관계없이 모든 규칙에 대해 동일한 값을 갖습니다. 이는 마지막으로 정의 된 모듈에만 실제로 올바른 규칙이 있음을 의미합니다.

새로운 접두어로 C/Ping을 반복하지 않고도 각 모듈에 공통된 BIN, OBJ, SRC, ... 변수에 대한 액세스 권한을 부여 할 수 있습니까? 즉, 변수 정의를 Makefile 섹션에 적용한 다음 이전 규칙을 유지하면서 나중에 변경할 수 있습니까? 이것이 가능하지 않다는 느낌이 들지만, 이것을 멋지게 마무리 할 멋진 트릭을 놓치면 정말 좋을 것입니다. 그렇지 않으면,이 전역 Makefile 일은 실제로 가능하지 않습니다 (이전에 재귀 적 make에 의해 범위가 지정된 WORKING_DIR에서 파생 된 공통 변수 톤이 있습니다).

+0

규칙 본문에서'$ ALL_OBJS'의 사용을 반복하지 마십시오. 대신에 "all prerequisites"'$ ^'에 대한 자동 변수를 사용하면 이러한 규칙이 예상대로 작동하기 시작할 것입니다. (이것은 또한 일반적인 "좋은 makefile"규칙입니다.)'OBJ' /'DEP'/etc에 대해 이것을 수정합니다. 규칙 본문에 사용되는 내용은 더 복잡합니다 (그러나 조금만). –

+0

그건 좋은 지적이고, 지금은 그렇게하도록 변경했습니다. 문제를 약간 줄이지 만, 각 모듈 전에 모든 추가 사항을 정의 할 필요성을 여전히 변경하지 않습니다. 무엇이 어떤 객체에 의존 하는지를 알기 위해서는 소스를 찾아야한다. src 디렉토리라는 것을 발견해야한다. 이것은 작업 디렉토리가 필요함을 의미한다. 이들 각각은 서로 다른 접두사를 가진 각 모듈에 대한 새로운 변수입니다. – Suedocode

답변

0

변수가 평가 될 때 해당 시간에 이 사용됩니다. 대부분의 make 변수는 재귀 적으로 확장되므로 "최종"위치에서 사용될 때까지 평가에서 지연됩니다.

여기서 최종 위치는 (및 처리 중에 발생하는 경우) 변수의 목적에 따라 다릅니다.

규칙 본문에 사용 된 변수 (예 : CFLAGS)는 규칙 본문이 실행될 때까지 평가되지 않으므로 구문 분석 단계에서 할당 된 마지막 값을 보게됩니다.

컨텍스트 자체에서 사용되는 변수는 처리하기가 더 쉽습니다. 공통 변수를 참조하고 특정 makefile에있는 변수를 사용하는 확장 된 (따라서 즉시 평가 된) 변수를 작성하기 만하면됩니다. (덧붙여, 당신은 방금 깨달은 것입니다. 이것은 규칙 몸체 변수 문제에 대한 해결책입니다. 적어도 자신이 쓰는 규칙이 아니라 일반적인 패턴 규칙이 아닙니다.)

일반 패턴 규칙에 대해 이것을 해석하면 다음과 같습니다. 글로벌 변수를 섀도우하게하는 타겟 특유의 단순히 확장 된 변수가 필요합니다.

나는 단지 자세한 설명을 할 수 없으므로 여기에 몇 가지 이슈와 내가 언급 한 수정 사항 중 하나 (패턴 규칙/대상 별 변수 중 하나)를 보여주는 예제 makefile이 있습니다.이것이 의미가 있는지보십시오. 이치에 맞지 않는 것에 대해 질문하고 내가 시간을 할 때 설명/대답하려고 노력할 것입니다. 반복

all: $(addsuffix -tgt,main second third) 

W_D := main 
ALLOBJS = $(addprefix main-,one two three) 
OBJ = main-obj 
DEP = main-dep 
M_TGT := main-tgt 
$(M_TGT): OBJ := $(OBJ) 
$(M_TGT): DEP := $(DEP) 
$(M_TGT): $(ALLOBJS) 

W_D := second 
ALLOBJS = $(addprefix second-,one two three) 
OBJ = second-obj 
DEP = second-dep 
S_TGT := second-tgt 
$(S_TGT): $(ALLOBJS) 

W_D := third 
ALLOBJS = $(addprefix third-,one two three) 
OBJ = third-obj 
DEP = third-dep 
T_TGT := third-tgt 
$(R_TGT): $(ALLOBJS) 

%: 
     @echo Making '[email protected]' $(if $^,from '$^') 
     @echo 'OBJ=$(OBJ)' 
     @echo 'DEP=$(DEP)' 

은 다음과 같습니다

$ more inc.mk Makefile | cat 
:::::::::::::: 
inc.mk 
:::::::::::::: 
FOO:=$(PREFIX)_bar 
$(PREFIX)_OBJS=wildcard $(PREFIX)/* 
:::::::::::::: 
Makefile 
:::::::::::::: 
PREFIX=one 
include inc.mk 
$(info FOO:$(FOO)) 
$(info $$(PREFIX)_OBJS:$($(PREFIX)_OBJS)) 
rule_one: PREFIX:=$(PREFIX) 

PREFIX=two 
include inc.mk 
$(info FOO:$(FOO)) 
$(info $$(PREFIX)_OBJS:$($(PREFIX)_OBJS)) 
rule_two: PREFIX:=$(PREFIX) 

PREFIX=three 
include inc.mk 
$(info FOO:$(FOO)) 
$(info $$(PREFIX)_OBJS:$($(PREFIX)_OBJS)) 
rule_three: PREFIX:=$(PREFIX) 

all: rule_one rule_two rule_three 

%: 
     @echo '# Making [email protected]' 
     @echo FOO:$(FOO) 
     @echo PREFIX_OBJS:$($(PREFIX)_OBJS) 

$ make 
FOO:one_bar 
$(PREFIX)_OBJS:wildcard one/* 
FOO:two_bar 
$(PREFIX)_OBJS:wildcard two/* 
FOO:three_bar 
$(PREFIX)_OBJS:wildcard three/* 
# Making rule_one 
FOO:three_bar 
PREFIX_OBJS:wildcard one/* 
# Making rule_two 
FOO:three_bar 
PREFIX_OBJS:wildcard two/* 
# Making rule_three 
FOO:three_bar 
PREFIX_OBJS:wildcard three/* 
# Making all 
FOO:three_bar 
PREFIX_OBJS:wildcard three/* 

당신 수보다 더 영리하고 할 필요 피하기 위해 대상별 변수 할당을 대상 이름을 사용하고 생성 포함 된 파일에 통조림 레시피를 정의 그 부분을 수동으로 원할 경우.

+0

# 4의 예를 들어 줄 수 있겠습니까? "컨텍스트 자체에서 사용되는 변수 ..." – Suedocode

+0

이것이 앞으로의 문제에 대한 유용한 정보 임에도 불구하고 이것이 전체 문제를 해결할 수 있을지 확신하지 못합니다. 이 문제는 하나의 일반 빌드 규칙에 대한 규칙 별 변수를 정의하지 않습니다. 값이 하나의'DIR' 변수에 의존하는 공통 변수 세트를 선언 할 수 있기를 원합니다. 이 방법으로, 각각의 특정 모듈은 하나의 변수 만 재정 의하여 다른 유용한 변수를 얻을 수 있습니다. 귀하의 솔루션은 여전히 ​​각 규칙에 대한 모든 중복 변수를 재현하는 것으로 보입니다. – Suedocode

+0

다릅니다. 즉시 전역 네임 스페이스 변수를 사용할 수 있고 나중에 필요하지 않으면 단일 변수가 필요할 때마다 makefile 변수 설정을 포함하기 만하면 (현재 변수 값을 기반으로 즉시 정의되기 때문에) 단일 변수가 작동합니다. –

관련 문제