我遇到了難以定義非遞歸製造系統的通用規則。使用一個變量來定義一個遞歸擴展變量,其名稱是從一個簡單的擴展變量中計算出來的
背景
對於進一步的閱讀,而不是我複製了太多的現有材料,見this earlier question,覆蓋地面相當不錯,和之前構建這個系統的時候幫助了我。我想要定義系統組件之間的依賴關係 - 例如,組件A依賴於組件B--然後離開make系統以確保B構建過程的任何產品在構建過程需要構建之前就已經被構建,因爲它的粒度有點浪費(可能會構建一些不需要的中間件),但對於我的用例來說,它在易用性和構建性能之間達到了一個舒適的平衡點。
系統必須處理的一個難題是makefile加載的順序無法控制 - 事實上,這應該不重要。但是,正因爲如此,在早期加載的makefile中定義的組件可能依賴於尚未讀取的makefile中定義的組件。
要允許通用模式應用於所有組件定義生成文件,每個組件都使用如下變量:$(component_name)_SRC
。這是非遞歸(但遞歸包含)make系統的常見解決方案。
有關GNU make的不同類型變量的信息,請參閱the manual。總之:簡單擴展變量(SEV)在讀取makefile時展開,表現出類似命令式編程語言的行爲;遞歸擴展變量(REV)在make的第二階段中被擴展,在所有makefile被讀取之後。
的問題
試圖把依賴項組件列表進入這些組件代表文件的列表時,具體的問題出現。
我已經將我的代碼提煉成了這個可運行的例子,它留下了很多真實系統的細節。我認爲這足以證明這個問題而不失其實質。
rules.mk:
$(c)_src := $(src)
$(c)_dependencies := $(dependencies)
### This is the interesting line:
$(c)_dependencies_src := $(foreach dep, $($(c)_dependencies), $($(dep)_src))
$(c) : $($(c)_src) $($(c)_dependencies_src)
@echo $^
的Makefile:
.PHONY: foo_a.txt foo_b.txt bar_a.txt hoge_a.txt
### Bar
c := bar
src := bar_a.txt
dependencies :=
include rules.mk
### Foo
c := foo
src := foo_a.txt foo_b.txt
dependencies := bar hoge
include rules.mk
### Hoge
c := hoge
src := hoge_a.txt
dependencies := bar
include rules.mk
這些將運行給:
$ make foo
foo_a.txt foo_b.txt bar_a.txt
$
hoge_a.txt不包括在輸出中,因爲在時間foo_dependencies
被定義爲SEV,hoge_src
尚不存在。
所有的makefiles被讀取後的擴展是REVs應該能夠解決的問題,我之前嘗試將$(c)_dependencies_src
定義爲REV,但這不起作用,因爲$(c)
然後在替換時擴展,而不是定義時間,所以它不再保持正確的價值。
如果有人想知道爲什麼我不使用特定於目標的變量,我擔心變量應用於手冊中描述的目標的所有先決條件將導致規則之間不同組件的不需要的交互。
我想知道:
- 有沒有這個具體問題的解決方案? (也就是說有一種簡單的方法可以讓這條線達到我想要的效果嗎?)
- 有沒有更像一個更典型的建造這種製造系統的方法? (即單個構建實例,從多個構建文件加載組件並定義這些組件之間的依賴關係)。
- 如果存在多個解決方案,它們之間的權衡是什麼?
最後的評論:正如我寫了我的問題,我已經開始意識到,可能有一個解決方案可能使用eval來構建REV定義,但是因爲我無法在任何地方找到此問題否則,爲了未來的搜索者,我認爲值得問這個問題,另外我想聽聽更多有經驗的用戶對這個或任何其他方法的想法。
爲什麼在設置'$(c)_dependencies_src'時你使用':='而不是'='?如果你在這裏使用'=',它會解決你的問題。 – MadScientist
個人而言,我永遠不會創建一個使用「全局」變量的系統,例如分配'c:= foo',然後包括規則文件,然後分配'c:= bar'幷包含規則文件。我會這樣做:'targets + = foo',然後'foo_c:= foo','foo_src:= foo.x'等等,然後'targets + = bar','bar_c:= bar','bar_src := bar.x'等。這樣可以避免設置相同的變量名稱並確保在重置之前使用它們。 – MadScientist
您是否嘗試過使用我發佈的示例?它至少不適用於我,正如我所說:「... REVs應該能夠解決,我以前嘗試將$(c)_dependencies_src定義爲REV ...」 –