2015-03-02 95 views
1

我不知道有什麼方法可以在GNU Make中定義編程目標。這怎麼可能?如何以編程方式在GNU Make中定義目標?

有時候可以走開with alternate methods。然而,在Makefiles中定義編程目標的能力對編寫和組織複雜的生產規則非常重要,其中make。的複雜的生產規則的例子是在FreeBSD中的構建系統或在生成文件庫如BSD Owl

殼腳本和Makefiles之間的main differences發現是:

  • 在生成文件時,程序的狀態是由命令行和文件系統給出,因此可以在作業中斷後重新開始工作。當然,這需要正確編寫Makefiles,但即使這很困難,也比使用shell腳本實現類似效果要容易得多。

  • 在Makefile中,用建議來裝飾過程或使用鉤子來裝飾過程是很荒唐的,而在shell腳本中這實際上是不可能的。

例如,一個非常簡單的和有用的模式如下:

build: pre-build 
build: do-build 
build: post-build 

這呈現的build目標作爲三個目標包含實際指令do-build和兩個其它,它們是複合材料,一個掛鉤,在do-build之前和之後執行。此模式是由爲BSD作,這亦允許的目標編程定義寫入許多構建系統使用的,這樣一方面可以在分批寫:

.for _target in configure build test install 
.if !target(${_target}) 
${_target}: pre-${_target} 
${_target}: do-${_target} 
${_target}: post-${_target} 
.endif 
.endfor 

.if/.endif塊引入的條件使用戶能夠使用其自己定義任何${_target}

那個GNU Make片段的翻譯是什麼?

+0

需要注意的是,在GNU中,你不需要**在目標先決條件之間得到一個有序保證(儘管沒有'-j'我認爲假設你通常是安全的),所以你的「鉤子「不一定做你想做的事。 – 2015-03-02 16:53:59

+0

@EtanReisner當然,但這與問題沒有直接關係,我忽略了這一點,以保持簡單。例如,在BSD Make中,有人說''。ORDER:預編譯do-build post-build'來執行所提及目標的串行處理。 – 2015-03-02 16:55:41

+0

使用或不使用'-j',make將始終以相同的順序走先決條件列表。只是''j''''''''''''''''''''''''''''''''''''''''''''''''''''不會等待以前的(非相關的)先決條件完成,然後再開始新的先決條件沒有'-j' make _does_保證按順序構建。 – MadScientist 2015-03-02 16:57:18

回答

2

FWIW這裏是

.for _target in configure build test install 
.if !target(${_target}) 
${_target}: pre-${_target} 
${_target}: do-${_target} 
${_target}: post-${_target} 
.endif 
.endfor 

基本上相當於化妝語法,你想使看到這樣的片斷:

build: pre-build 
build: do-build 
build: post-build 

,類似的還有configuretestinstall。這表明與eval某處一個循環:

define makerule = 
    $1: pre-$1 
    $1: do-$1 
    $1: post-$1 
endef 

targets := configure build test install 

$(foreach _,${targets},$(eval $(call makerule,$_))) 

(以玩這個,改變evalinfo)。小心那些關閉!

FWIW,這裏的foreach的擴展:

  • 使擴展將遍歷
    • ${targets}變得configurebuildtestinstall
    • 我們有$(foreach _,configure build test install,$(eval $(call makerule,$_)))
    • 列表
  • _設置爲第一個值,configure
  • 使擴展$(eval $(call makerule,configure))
  • 爲了評估eval使擴展$(call makerule,configure)
    • 它通過設置1configure,擴大${makerule}產生3行文本的做到這一點:
      configure: pre-configure
      configure: do-configure
      configure: post-configure
  • $(eval)上班,閱讀本書爲使語法
  • 注意,$(eval)的擴張是空的!其所有工作都是作爲副作用完成的。 清洗,起泡,沖洗,重複。

請注意:我已經與所有其他評論者同意:你的模式是化妝。如果你的makefile不是-j安全,那麼它是(缺少依賴關係)。

+0

謝謝你的有用答案!正如我在其他一些評論中指出的那樣,我很清楚並行性問題,並將其從我的問題中省略,因爲我只對程序方面感興趣。但初學者閱讀你的平行橫幅是很好的! :d – 2015-03-09 22:59:43

2

如果您想要支持並行構建,首先此結構無效;如果您使用-j選項調用make,它將同時運行所有三項先決條件規則,因爲儘管所有這些規則必須在build之前完成,但它們都不依賴於對方,因此沒有訂購定義(也就是說, t說必須在do-build可以運行之前完成)。

其次,GNU make有一些programmatically defining rules的設施。目前,GNU make目前沒有能力搜索已經定義的目標,因此與.if !target(...)沒有直接的類比。

但是,您可以使用.VARIABLES變量搜索變量是否已定義。所以一個解決方法是定義一個變量,如果你想要自己的目標,然後讓你的規則生成器檢查。

+0

謝謝@MadScientist,這是一個有用的答案,尤其是解決方法。定義多行宏的能力似乎特別重要。 – 2015-03-02 17:04:16