你如何獲得makefile中的目標列表?



Answers

在Bash下(至少),這可以通過tab完成自動完成:

make(space)(tab)(tab)
Question

我已經使用了一些rake(一個Ruby make程序),並且它有一個選項來獲得所有可用目標的列表,例如

> rake --tasks
rake db:charset      # retrieve the charset for your data...
rake db:collation    # retrieve the collation for your da...
rake db:create       # Creates the databases defined in y...
rake db:drop         # Drops the database for your curren...
...

但在GNU make中似乎沒有這樣做的選擇。

顯然,代碼幾乎就在那裡,截至2007年 - http://www.mail-archive.com/help-make@gnu.org/msg06434.html

無論如何,我從makefile中提取目標的方法很少,你可以將它包含在makefile中。

list:
    @grep '^[^#[:space:]].*:' Makefile

它會給你一個定義目標的列表。 這只是一個開始 - 例如,它不會過濾掉依賴關係。

> make list
list:
copy:
run:
plot:
turnin:



這個對我很有幫助,因為我希望通過make目標來看到構建目標(及其依賴關係)。 我知道,制定目標不能以“。”開頭。 字符。 我不知道支持哪些語言,所以我使用egrep的括號表達式。

cat Makefile | egrep "^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$"



如果您安裝了bash _make_target_extract_script ,完成腳本將定義一個函數_make_target_extract_script 。 這個函數是為了創建一個sed腳本,它可以用來獲取列表中的目標。

像這樣使用它:

# Make sure bash completion is enabled
source /etc/bash_completion 

# List targets from Makefile
sed -nrf <(_make_target_extract_script --) Makefile



這裡提供了很多可行的解決方案,但正如我所說的,“如果值得做一次,那麼值得再做一次。” 我確實使用了(選項卡)(選項卡)的提示,但正如一些人指出的那樣,您可能沒有完成支持,或者如果您有很多包含文件,您可能需要一種更簡單的方法來知道定義目標的位置。

我沒有測試下面的子作品...我認為這是行不通的。 正如我們所知,遞歸被認為是有害的。

.PHONY: list ls
ls list :
    @# search all include files for targets.
    @# ... excluding special targets, and output dynamic rule definitions unresolved.
    @for inc in $(MAKEFILE_LIST); do \
    echo ' =' $$inc '= '; \
    grep -Eo '^[^\.#[:blank:]]+.*:.*' $$inc | grep -v ':=' | \
    cut -f 1 | sort | sed 's/.*/  &/' | sed -n 's/:.*$$//p' | \
    tr $$ \\\ | tr $(open_paren) % | tr $(close_paren) % \
; done

# to get around escaping limitations:
open_paren := \(
close_paren := \)

我喜歡的原因是:

  • 通過包含文件列出目標。
  • 輸出原始動態目標定義(用模替換可變定界符)
  • 在一個新行上輸出每個目標
  • 似乎更清楚(主觀意見)

說明:

  • 在MAKEFILE_LIST中的foreach文件
  • 輸出文件的名稱
  • 包含冒號的grep行,不縮進,不包含註釋,並且不以句點開頭
  • 排除立即賦值表達式(:=)
  • 剪切,排序,縮進和裁剪規則依賴關係(冒號後)
  • munge可變分隔符以防止擴展

示例輸出:

 = Makefile = 
  includes
  ls list
 = util/kiss/snapshots.mk = 
  rotate-db-snapshots
  rotate-file-snapshots
  snap-db
  snap-files
  snapshot
 = util/kiss/main.mk = 
  dirs
  install
   %MK_DIR_PREFIX%env-config.php
   %MK_DIR_PREFIX%../srdb



@ nobar的回答有助於展示如何使用製表符完成來列出makefile的目標

  • 這對默認情況下提供此功能平台非常有用(例如, Debian,Fedora )。

  • 在其他平台上(例如Ubuntu ),您必須明確加載此功能,正如@ hek2mgl的答案所暗示的那樣 :

    • . /etc/bash_completion . /etc/bash_completion會安裝多個製表符完成功能,其中包括make的一個
    • 或者,要安裝make製表符完成:
      • . /usr/share/bash-completion/completions/make
  • 對於根本不提供這種功能的平台 ,例如OSX ,您可以獲得以下命令 (可從here )來實現它:
_complete_make() { COMPREPLY=($(compgen -W "$(make -pRrq : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($1 !~ "^[#.]") {print $1}}' | egrep -v '^[^[:alnum:]]' | sort | xargs)" -- "${COMP_WORDS[$COMP_CWORD]}")); }
complete -F _complete_make make
  • 注意:這不像Linux發行版附帶的製表符完成功能那樣複雜:最明顯的是,它始終以當前目錄中的makefile為目標 ,即使命令行使用-f <file>定位不同的生成-f <file>



Related