2014-07-11 31 views
2

我試圖將我的整個項目轉換爲單個Makefile,但如果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模塊。這是我的主人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.tools使用從Makefile.var基礎上,WORKING_DIR價值導出的變量。那麼,這實際上並不工作,因爲make所做的兩階段讀數。變量WORKING_DIR將僅採用最後一次已知的分配,並且ALL_OBJS對於所有規則都是相同的值,無論它們位於何處。這意味着只有最後定義的模塊實際上具有正確的規則。

有沒有一種方法可以訪問常見的BIN, OBJ, SRC, ...變量到每個模塊,而不僅僅是使用新的前綴c/ping一遍又一遍?也就是說,我可以將變量定義範圍限定在Makefile部分,然後在保留舊規則的同時更改它?我有一種瘙癢的感覺,這是不可能的,但如果我錯過了一些很好的技巧,這將很好地包裹起來,這將是非常好的。否則,這個全局Makefile的東西並不是真的可行(有一些常用變量的TONS用於從WORKING_DIR派生值,這些變量的範圍是先前的遞歸構造)。

+0

不要在規則的主體中重複使用'$ ALL_OBJS'。用「所有先決條件」'$ ^'代替自動變量,我相信這些規則將以您期望的方式開始工作。 (這也是一個通用的「良好生成文件」的經驗法則。)爲'OBJ' /'DEP'/etc解決這個問題。在規則體中使用更復雜(但只是一點點)。 –

+0

這是一個很好的觀點,現在我已經改變了它。它稍微減少了問題,但它仍然不會改變在每個模塊之前定義所有這些額外的東西的需要。爲了知道某些東西依賴於哪些對象,我必須找到它的來源,這意味着我必須找到它的src目錄,這意味着我需要工作目錄。其中每一個都是每個模塊的新變量,前綴不同。 – Suedocode

回答

0

當一個變量被評估時,它的值在那個時候使用了。大多數變量是遞歸擴展的,因此在評估中被推遲到「最終」位置使用。

最終位置(並且在處理中發生時)取決於變量的用途而不同。

規則體中使用的變量(如CFLAGS)不會被計算,直到規則體運行並且因此會在分析階段看到分配的最後一個值。

make環境中使用的變量本身更容易處理。所有你需要做的就是創建簡單的擴展(並因此立即評估)引用公共變量並在特定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的例子:「make context中使用的變量本身......」 – Suedocode

+0

我不確定這是否解決了整個問題,雖然這對我將來會遇到的問題是有用的信息。問題不在於爲一個通用構建規則定義特定於規則的變量。我希望能夠聲明一組通用變量,這些變量的值取決於一個「DIR」變量。這樣,每個特定的模塊只需重新定義一個變量即可獲得一整套其他有用的變量。您的解決方案似乎仍然會重現每個規則的所有冗餘變量。 – Suedocode

+0

這取決於。如果您可以立即使用全局名稱空間變量,並且以後不需要它們,那麼您的單個變量將會工作(因爲它們將立即根據當前變量值進行定義),只需在每次需要時包含變量設置makefile即可。 –