2011-02-10 60 views
1

我有例如。的源文件的列表分配給一個變量內,生成文件,並想 在構建時弄清楚,是否有兩次列出的條目可能麻煩構建過程及其結果:檢索包含在make變量中的列出元素的多餘條目

實施例:

ListofSource = ./a/hello.c ./b/sys.c ./c/input.c ./d/hello.c 

怎麼可能來分析/過濾ListofSource檢索列表

DuplicateSources = ./a/hello.c ./d/hello.c 

功能$(排序列表)排序列表,並刪除多餘的條目,我需要相反的行爲。 是否存在可應用的任何make功能?

回答

0

如果你癡迷的Makefile的整潔,你可以要求該列表是有序和做類似:

ifneq ($(LIST),$(sort $(LIST))) 
$(error $$(LIST) contains duplicates) 
endif 
+0

當$ {LIST}沒有排序但沒有重複時失敗。我建議你需要比較'$(words ...)'的輸出:'ifneq($(words $ {LIST}),$(words $(sort $ {LIST})))...'。 (哦,和你的測試是錯誤的方式。) – bobbogo

+0

@bobbogo:你說錯了,但你可能要求列表按照排序順序「你沒有看到? '$(words)'的使用並不是一個可怕的想法,但是你不用'$ {}'來展開'make'中的變量。 –

+1

哦,你是的!我通常爲函數保留'$()',爲用戶變量保留'$ {}'(perl methinks太多)。提高可讀性恕我直言。你的措詞是對的。只要列表需要排序,但仍然保留重複,這本身就是一個問題! – bobbogo

0

使用$(shell),例如

DuplicateSources = $(shell perl -e '++$c{$_} for @ARGV; print join(" ",grep{$c{$_}>1} sort keys %c),"\n"' $(ListofSource)) 

應該工作。

+0

如果您打算使用'$(shell)',請使用':='而不是'='來強制立即擴展。每次引用'$(DuplicateSources)'時,您都不想調用perl。 –

+0

好點,我想過但我不想解釋區別:) – reinierpost

0

$(shell...)不建議您在製作時全部使用。

list := a/1 b/2 c/3 a/1 
duplicates := $(foreach v,$(sort ${list}),$(if $(filter-out 1,$(words $(filter $v,${list}))),$v)) 

(當然這可以清理一下。)這樣的表達式最好從內部讀到外面。

  • $v被依次設爲每個列表項目。因爲我們使用$(sort...)
  • $(filter $v,${list})返回所有與$v相匹配的項目。通常會有一個返回值,但在本例中,當$va/1時,我們得到兩個(相同)值。
  • 然後我們計算前面的單詞。通常$(words...)將返回1,或者在重複的情況下返回更高的數字。
  • 我們沒有興趣時$(words...)返回1,所以我們$(filter-out...)這些情況。
  • 剩下的東西是重複的!所以在這種情況下,我們使用$(if...)返回$v

還有其他的方式使用$(eval...)它給你真正的編程機會。

相關問題