Bir makefile içindeki hedeflerin listesini nasıl alırsınız?


203

Biraz komisyon kullandım (Ruby yapma programı) ve mevcut tüm hedeflerin bir listesini alma seçeneği var, örn.

> 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...
...

fakat bunu GNU markasında yapma seçeneği yok gibi görünüyor.

Görünüşe göre kod 2007 için neredeyse orada - http://www.mail-archive.com/help-make@gnu.org/msg06434.html .

Her neyse, bir makefile dahil edebileceğiniz bir makefile hedefleri çıkarmak için küçük bir kesmek yaptım.

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

Size tanımlanmış hedeflerin bir listesini verecektir. Bu sadece bir başlangıç ​​- örneğin bağımlılıkları filtrelemiyor.

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

2
Çabuk ilginç cevaplar okumak, ama şimdiye kadar kendim için ben, düz basit tutmayı tercih ve (benim .bashrc olarak) bir takma ad kullanarak taşınabilir: alias makefile-targets='grep "^[^#[:space:]].*:" Makefile' Çoğu zaman sadece şimdiki makefile incelemek gerekir ve bash tamamlama genişletildiği takma adım.
RockyRoad


4
Çok önemsiz grep : Makefilemi :?
cibercitizen1

Yanıtlar:


133

Bu, @ nobar'ın büyük yaklaşımını aşağıdaki gibi geliştirmeye yönelik bir girişimdir :

  • hedef adları ayıklamak için daha sağlam bir komut kullanır, bu da yanlış pozitifleri umarım önler (ve gereksiz olanı ortadan kaldırır sh -c)
  • geçerli dizindeki kalıcı dosyayı hedef almaz ; ile açıkça belirtilen markalara saygı duyar-f <file>
  • gizli hedefleri hariç tutar - kural olarak, bunlar adı ne bir harfle ne de bir rakamla başlar
  • markaları bir ilgisi tek düzmece hedefi
  • @çalıştırmadan önce yankılanmasını önlemek için komutun önüne ekler

İlginçtir ki, GNU makesadece bir makefile içinde tanımlanan hedeflerin adlarını listeleme özelliğine sahip değildir. -pSeçeneği tüm hedefleri içeren çıktı üretir, ancak diğer pek çok bilgi onları gömer.

GNU'nun tüm hedef adlarını alfabetik sırayla listeleyen makebir hedef uygulaması için aşağıdaki kuralı bir makeile yerleştirin list- ie: asoke asmake list :

.PHONY: list
list:
    @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'

Önemli : Bunu yapıştırırken , son satırın tam olarak 1 gerçek sekme karakteriyle girintili olduğundan emin olun . (boşluk yok değil iş) .

O Not sıralama beri hedeflerin ortaya çıkan liste, en iyi seçenektir değil hedefler makefile görünme sırası olduğunu bir yardımcı sıralamayı üretmez sıralama değil korunmuş.
Ayrıca, birden fazla hedef içeren bir kuralın alt hedefler değişmez çıkış vardır ayrı ayrı nedeniyle genellikle sıralama için ve dolayısıyla, irade değil birbirlerine yanında görünür; örneğin başlayan bir kural a z:olacak değil hedeflere sahip ave zlistelenen yanyana ek hedefler varsa, çıktıda.

Kuralın açıklaması :

  • .PHONY: list
    • Hedef listesine düzmece hedefi, yani beyan tek değil bir atıfta dosyanın bu nedenle onun tarifi çağrılan olmalıdır ki, kayıtsız şartsız
  • $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

    • makeMakefile türetilmiş veritabanını yazdırmak ve ayrıştırmak için tekrar çağırır :
      • -p veritabanını yazdırır
      • -Rr yerleşik kuralların ve değişkenlerin dahil edilmesini bastırır
      • -qyalnızca bir hedefin güncel durumunu test eder (hiçbir şey yeniden yapmadan), ancak her durumda reçete komutlarının yürütülmesini engellemez; dolayısıyla:
      • -f $(lastword $(MAKEFILE_LIST))örtük veya açık bir şekilde hedeflenip hedeflenmediğine bakılmaksızın, aynı dosya dosyasının orijinal çağrıdaki gibi hedeflenmesini sağlar -f ....
        Uyarı : Bu, marka dosyanız includedirektif içeriyorsa bozulur; bunu ele almak için değişkenleri herhangi bir direktiften THIS_FILE := $(lastword $(MAKEFILE_LIST)) önce tanımlayın includeve -f $(THIS_FILE)bunun yerine kullanın.
      • :Bir olduğu kasten geçersiz hedef anlamına gelir hiçbir komutlar yürütülmesini sağlamak ; 2>/dev/nullortaya çıkan hata mesajını bastırır. Not: Bu -pyine de veritabanı baskı dayanmaktadır, GNU make 3.82 olduğu gibi. Ne yazık ki, GNU yapmak teklifler doğrudan seçeneği sadece olmadan, veritabanı yazdırmak da varsayılan (veya verilen) görevi yürütülürken; belirli bir Makefile'yi hedeflemeniz gerekmiyorsa make -p -f/dev/null, mansayfada önerildiği gibi kullanabilirsiniz .
  • -v RS=

    • Bu, girdiyi bitişik boş olmayan satırların bloklarına ayıran awk bir deyimdir.
  • /^# File/,/^# Finished Make data base/
    • Çıktıdaki tüm hedefleri içeren satır aralıklarıyla eşleşir (GNU make 3.82'den doğrudur) - ayrıştırmayı bu aralıkla sınırlayarak, diğer çıktı bölümlerinden yanlış pozitiflerle uğraşmanıza gerek yoktur.
  • if ($$1 !~ "^[#.]")
    • Blokları seçici olarak yok sayar:
      • # ... blokları ile başlayan hedef olmayanları yok sayar # Not a target:
      • . ... özel hedefleri yok sayar
    • Diğer tüm blokların her biri, yalnızca açıkça tanımlanmış bir hedefin adını içeren bir satırla başlamalı ve bunu :
  • egrep -v -e '^[^[:alnum:]]' -e '^$@$$' istenmeyen hedefleri çıktıdan kaldırır:
    • '^[^[:alnum:]]'... konvansiyona göre ne bir harfle ne de bir rakamla başlayan hedefler olan gizli hedefleri içermez .
    • '^$@$$'... listhedefin kendisini hariç tutar

make listDaha sonra koşmak , her biri kendi satırında olan tüm hedefleri yazdırır; xargsbunun yerine boşlukla ayrılmış bir liste oluşturmak için kanal oluşturabilirsiniz.


Bu harika bir cevap, ancak her görev için nasıl açıklama alabilirim? Şu anda görev tanımının üstünde bir yorum olarak saklıyorum. Listeye olduğu gibi eklemenin mümkün olup olmadığından emin değil rake --tasksmisiniz?
Piotr Kuczynski

1
@PiotrKuczynski: İlginç bir soru, ama bunu yeni bir soru olarak göndermenizi öneririm (referans için bunu işaret ederek).
mklement0

"Ne yazık ki, GNU yapmak sadece veritabanı yazdırmak için doğrudan bir seçenek sunuyor." Bir -nseçenek var.
Bulletmagnet

@Bulletmagnet: -nSeçeneğin amacı "Yürütülecek komutları yazdırmak ..." - başka bir deyişle: kuru çalıştırma özelliği. Ayrıca alıntı kelimenin yatık yazı eksik değil o sadece : make -pkendisi tarafından yapar veritabanını yazdırmak ama kaçınılmaz da varsayılan görevi çalıştırır ; kılavuzda bundan make -p -f/dev/nullkaçınmak için hantal önerilmektedir .
mklement0

1
Herhangi bir .PHONY hedefini de listeleyecek, bu yüzden sahip olmadığınızdan emin olun.PHONY: *
tekumara

189

Bash altında (en azından), sekme tamamlandığında otomatik olarak yapılabilir:

make spacetabtab


1
Test edildi: bash - sürüm = 4.2.45 (1) -çalışma. make --version = 3.81.
Brent Bradburn

54
+1, ancak bunun bir bash özelliği olmadığını , ancak platformunuza bağlı olduğunu unutmayın . Platformlar üç kategoriye ayrılır: bu tamamlamanın varsayılan olarak yüklendiği (örn. Debian 7, Fedora 20), isteğe bağlı olarak yükleyebileceğiniz (ör. Ubuntu 14, ile . /etc/bash_completion) ve hiç desteklemeyenler (örn. OSX 10.9)
mklement0

8
OS X 10.10'da çalışır (bash ile değil, zsh ile).
Florian Oswald

4
Büyük ipucu ama aynı zamanda bash-completionpakete ihtiyacı var . Fedora, RHEL, Gentoo, vb bulundu.
NoelProf

4
Bu programlı olarak oluşturulan hedef AFAICT ile çalışmaz, örneğin$(RUN_TARGETS): run-%: ...
Matthias

32

Bu açıkçası pek çok durumda işe yaramaz, ancak MakefileCMake tarafından yaratıldıysa çalıştırabilirsiniz make help.

$ make help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... install
etc

Bunu elde etmek için CMakeList'inizde açma seçeneğiniz var mı? CMake tarafından oluşturulan bir makefile aldım ve sözde yardım hedefim yok
Xavier T.

Hayır! En azından yeni bir CMake ile OSX'de (aslında gece kullanıyorum ama bunu yazdığımda inanıyorum 3.3 kullanıyordum), sadece koş touch CMakeLists.txt && cmake . && make helpve çalışmalı. Sadece eski bir cmake kullandığınızı veya Unix Makefiles jeneratörünü kullanmadığınızı tahmin edebilirim?
Timmmm

Windows'ta unix üreteci ile CMake 3.6.2 kullanıyorum. Bir açıklama aramak için etrafı kazacağım çünkü kullanışlı görünüyor.
Xavier

26

Bu iki yanıtı birleştirdim: https://stackoverflow.com/a/9524878/86967 ve https://stackoverflow.com/a/7390874/86967 ve bunun bir makefile içinden kullanılabilmesi için bazı çıkışlar yaptım.

.PHONY: no_targets__ list
no_targets__:
list:
    sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | sort"

.

$ make -s list
build
clean
default
distclean
doc
fresh
install
list
makefile ## this is kind of extraneous, but whatever...
run

10
Ayrıca (son zamanlarda) Bash altındaki sekme tamamlamanın kullanılabilir hedefleri listeleyeceğini keşfettim.
Brent Bradburn

1
Harika bir yaklaşım için +1, ancak birkaç iyileştirme yapılabilir: (a) açıkça belirtmek sh -c "…"gereksizdir, çünkü makevarsayılan olarak reçete komutlarını çağırmak için bunu kullanır; (b) kullandığınız komut çok basittir, yanlış pozitiflere neden olur (not ettiğiniz gibi); (c) komutun önüne önek eklerseniz @, çalıştırmadan önce stdout'a tekrarlanmayacak ve çağırmada kullanım gereğini ortadan kaldıracaktır -s.
mklement0

1
ekleyebileceğiniz çok daha basit bir hedef yapın: list: cat Makefile | grep "^ [Az]" | awk '{print $$ 1}' | sed "s /: // g | sort"
thamster

2
Cat / sed yaklaşımı birkaç seviyede başarısız olur. Değişkenleri genişletmez ve diğer dosyaları dahil etmenin sonucu olan hedefleri listeleyemez.
Troy Daniels

1
@ mklement0: make -smakefile komutlarında önek kullanmak yerine (Bash takma adı aracılığıyla) kullanmayı tercih ederim @. @Özellikle echokomutlar için bir önek olarak (komutun görüntülenmesinin gereksiz olacağı) yararlı olabilecek bazı durumlar vardır , ancak genel olarak kullanmaktan hoşlanmam. Ben (tarafından gerektiğinde Böylece ben "tarifler" görebilirsiniz değildir kullanarak -s), ancak tipik olarak. İlgili belgeler şöyledir : GNU Manuel Yap, 5.2 Tarif Yankısı .
Brent Bradburn

14

Yüklü olarak bash tamamlamanız varsa make, tamamlama komut dosyası bir işlev tanımlar _make_target_extract_script. Bu işlev, sedhedefleri bir liste olarak elde etmek için kullanılabilecek bir komut dosyası oluşturmak içindir .

Şöyle kullanın:

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

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

3
Yararlı, ancak tüm platformların komut dosyası /etc/bash_completionve / veya işlevi olmadığını unutmayın _make_target_extract_script- Ubuntu> 12'de gibi görünüyorsunuz. /usr/share/bash-completion/completions/makeBunun yerine, hedefiniz Fedora 20 gibi ek platformlarda çalışacaktır. bu dosya değil, işlev (ör. Debian 7 ve Ubuntu 12); OSX gibi diğer platformlar için sekme tamamlama özelliği yoktur make. Belki de gerçek fonksiyon tanımını yayınlamak faydalı olabilir.
mklement0

1
Yorumun için teşekkürler. Bu çok takdir ediliyor. Evet, bunu Ubuntu
14.04'te

11

Mklement0'ın işaret ettiği gibi , tüm Makefile hedeflerini listeleme özelliği GNU- make'de eksiktir ve yanıtı ve diğerleri bunu yapmanın yollarını sağlar.

Bununla birlikte, orijinal gönderi , görev geçişi, komisyondaki tüm görevleri listelemekten biraz farklı bir şey yapan komisyondan da bahseder . Komisyon, size yalnızca ilişkili açıklamaları olan görevlerin bir listesini verecektir. Açıklamaları olmayan görevler listelenmeyecektir . Bu, yazara hem özelleştirilmiş yardım açıklamaları sunma hem de belirli hedefler için yardımı atlama yeteneği verir.

Her hedef için açıklama sağladığınız komisyonun davranışını taklit etmek istiyorsanız, bunu yapmak için basit bir teknik vardır: Listelenmesini istediğiniz her hedef için açıklamaları gömün.

Açıklamayı hedefin yanına veya sık sık yaptığım gibi, hedefin yukarısında bir PHONY belirtiminin yanına koyabilirsiniz:

.PHONY: target1 # Target 1 help text
target1: deps
    [... target 1 build commands]

.PHONY: target2 # Target 2 help text
target2:
    [... target 2 build commands]

...                                                                                                         

.PHONY: help # Generate list of targets with descriptions                                                                
help:                                                                                                                    
    @grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 \2/' | expand -t20

Hangisi verecek

$ make help
target1             Target 1 help text
target2             Target 2 help text

...
help                Generate list of targets with descriptions

Bu özette ve burada da kısa bir kod örneği bulabilirsiniz .

Yine, bu bir Makefile'deki tüm hedefleri listeleme problemini çözmez. Örneğin, büyük olasılıkla oluşturulmuş veya başka birinin yazdığı büyük bir Makefile'niz varsa ve hedeflerini kazmadan listelemenin hızlı bir yolunu istiyorsanız, bu yardımcı olmaz.

Bununla birlikte, bir Makefile yazıyorsanız ve yardım metnini tutarlı ve kendi kendini belgeleyen bir şekilde oluşturmanın bir yolunu istiyorsanız, bu teknik yararlı olabilir.


Bu harika bir teknik - güzel ve basit ama aynı zamanda açıklamalar da veriyor!
Brian Burns

Harika bir teknik. echoKomutu komut açıklaması olarak kullanmak için biraz değiştirdim ( stackoverflow.com/a/52059487/814145 ).
Penghe Geng

@PengheGeng Mesaj için teşekkürler. Ben @echo "Target 1"bir "açıklama yankı komutu" değil, sadece bir yer tutucu olduğunu netleştirmek istiyorum . Oluşturulan yardım metni @echo's'den gelmiyor . Gerçek bir Makefile'de, bunların echoyerine bir build komutu ya da bir başkası geçer. Bunu daha açık hale getirmek için yayını düzenleyeceğim.
jsp

5

Buna en sevdiğim cevap Chris Down tarafından Unix & Linux Stack Exchange'de yayınlandı. Alıntı yapacağım.

İçin bash tamamlama modülü makelistesini şu şekilde alır:

make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'

Disk belleği olmadan yeni satırla sınırlandırılmış hedefler listesini yazdırır.

Kullanıcı Brainstonesort -u yinelenen girişleri kaldırmak için borulama önerir :

make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}' | sort -u

Kaynak: Yapılmakta olan tüm hedefler nasıl listelenir? (Unix ve Linux SE)


4

@ nobar'ın yanıtı , bir makefile'ın hedeflerini listelemek için sekme tamamlamanın nasıl kullanılacağını yararlı bir şekilde gösterir .

  • Bu , varsayılan olarak bu işlevselliği sağlayan platformlar için harika çalışır (örn. Debian, Fedora ).

  • Diğer platformlarda (örn. Ubuntu ) , @ hek2mgl'nin cevabının ima ettiği gibi bu işlevi açıkça yüklemelisiniz :

    • . /etc/bash_completion aşağıdakiler de dahil olmak üzere birkaç sekme tamamlama işlevi yükler make
    • Alternatif olarak, aşağıdakiler için yalnızca sekme tamamlamayı yüklemek için make:
      • . /usr/share/bash-completion/completions/make
  • İçin hiç bu işlevselliği sunmuyor platformları gibi OSX yapabilirsiniz aşağıdaki komutları kaynak (gelen adapated burada ) uygulamak:
_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
  • Not: Bu, Linux dağıtımlarıyla birlikte gelen sekme tamamlama işlevselliği kadar karmaşık değildir: en önemlisi, komut satırı farklı bir makefile hedefliyor olsa bile , her zaman geçerli dizindeki makefile'ı hedefler -f <file>.

4

Bir hedef yapmayı tanımlamak için kolay bir sözdizimine odaklanmak ve temiz bir çıktı elde etmek için bu yaklaşımı seçtim:

help:
    @grep -B1 -E "^[a-zA-Z0-9_-]+\:([^\=]|$$)" Makefile \
     | grep -v -- -- \
     | sed 'N;s/\n/###/' \
     | sed -n 's/^#: \(.*\)###\(.*\):.*/\2###\1/p' \
     | column -t  -s '###'


#: Starts the container stack
up: a b
  command

#: Pulls in new container images
pull: c d 
    another command

make-target-not-shown:

# this does not count as a description, so leaving
# your implementation comments alone, e.g TODOs
also-not-shown:

Yukarıdakilere bir Makefile olarak davranmak ve onu çalıştırmak size şöyle bir şey verir:

> make help
up          Starts the container stack
pull        Pulls in new container images

Komut zinciri için açıklama:


Çok güzel bir çözüm. Ben şimdi birkaç yıldır bu kullandık .: awk -F ':|##' '/^[^\t].+:.*##/ { printf "\033[36mmake %-28s\033[0m -%s\n", $$1, $$NF }' $(MAKEFILE_LIST) | sort ile ##hedef olarak aynı satırda açıklamanın önüne. Ancak çözümünüzün okunabilirlikten önce izin verdiğini düşünüyorum.
thoroc

grep: parentheses not balancedOSX 10.15 makinemdeki ilk iki satırlık raporlardan oluşan bir marka.
Malcolm Crum

@Crummy özür dilerim, hatam. Gösterdiğiniz için teşekkürler. Onu düzeltti. make değişken isimlerini başlatması gerekmeyen dolar işaretlerinden kaçmayı gerektirir.
Richard Kiefer

Dikkat edin, StackOverflow yukarıdaki kod bölümlerini görüntülerken sekmeleri boşluklara dönüştürür, ancak Makefiles sekmeler gerektirir. Gönderiyi düzenleyebilir ve sonra bölümleri kopyalayabilirsiniz, böylece sekmeler korunur.
Richard Kiefer

2

Burada birçok uygulanabilir çözüm var, ama dediğim gibi, "bir kez yapmaya değerse, tekrar yapmaya değer." (Sekme) (sekme) kullanmak için öneriyi oyladım, ancak bazılarının belirttiği gibi, tamamlama desteğiniz olmayabilir veya çok sayıda dosya içeriğiniz varsa, bir hedefin nerede tanımlandığını daha kolay bir şekilde bilmek isteyebilirsiniz.

Aşağıdakileri alt markalarla test etmedim ... Bence işe yaramaz. Bildiğimiz gibi, özyinelemeli zararlı olarak kabul edilir.

.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 := \)

Hangi gibi çünkü:

  • hedefleri dahil etme dosyasına göre listeler.
  • ham dinamik hedef tanımları çıkar (değişken sınırlayıcıları modulo ile değiştirir)
  • her hedefi yeni bir satırda çıktılar
  • daha net görünüyor (öznel görüş)

Açıklama:

  • MAKEFILE_LIST içindeki foreach dosyası
  • dosyanın adını çıkar
  • girintisiz, yorum içermeyen ve nokta ile başlamayan iki nokta üst üste içeren grep satırları
  • anında atama ifadelerini hariç tut (: =)
  • kural bağımlılıklarını kesme, sıralama, girintileme ve doğrama (iki nokta üst üste işaretinden sonra)
  • genişlemeyi önlemek için munge değişken sınırlayıcılar

Örnek Çıktı:

 = 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

1

Bu benim için yararlı oldu çünkü ben yapmak hedef tarafından gerekli (ve onların bağımlılıkları) yapı hedefleri görmek istedim. Hedefler koymanın "." İle başlayamayacağını biliyorum. karakter. Hangi dillerin desteklendiğini bilmiyorum, bu yüzden egrep'in parantez ifadeleriyle gittim.

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

1

Bu temiz olmaktan uzak, ama benim için işi yaptı.

make -p 2&>/dev/null | grep -A 100000 "# Files" | grep -v "^$" | grep -v "^\(\s\|#\|\.\)" | grep -v "Makefile:" | cut -d ":" -f 1

Ben make -piç veritabanı dökümü kullanın , hendek stderr, grep -A 100000çıkış alt tutmak için hızlı ve kirli kullanın. Sonra çıktıyı bir çift ile temizliyorum grep -vve sonunda cutiki nokta üst üste olanları, yani hedefleri almak için kullanıyorum.

Bu, çoğu Makefile'imdeki yardımcı senaryolarım için yeterli.

EDIT: grep -v Makefilebu bir iç kural


1

Bu, jsp'nin çok yararlı cevabında yapılan bir değişikliktir ( https://stackoverflow.com/a/45843594/814145 ). Sadece bir hedef listesi değil, aynı zamanda onların tanımlarını da alma fikrini seviyorum. jsp Makefile, açıklamayı hedefin açıklama yankı komutunda sık sık tekrarlanacağım yorum olarak koyar. Bunun yerine, her hedef için echo komutunun açıklamasını çıkarıyorum.

Örnek Makefile:

.PHONY: all
all: build
        : "same as 'make build'"

.PHONY: build
build:
        @echo "Build the project"

.PHONY: clean
clean:
        @echo "Clean the project"

.PHONY: help
help:
        @echo -n "Common make targets"
        @echo ":"
        @cat Makefile | sed -n '/^\.PHONY: / h; /\(^\t@*echo\|^\t:\)/ {H; x; /PHONY/ s/.PHONY: \(.*\)\n.*"\(.*\)"/    make \1\t\2/p; d; x}'| sort -k2,2 |expand -t 20

Çıktı make help:

$ make help
Common make targets:
    make all        same as 'make build'
    make build      Build the project
    make clean      Clean the project
    make help       Common make targets

Notlar:

  • Aynı jsp 'ın cevabı, sadece PHONY hedefleri listelenmiş olabilir ihtiva edebilir veya may dava için değil iş
  • Ayrıca, yalnızca tarifin ilk komutu olarak echoveya :komutuna sahip PHONY hedeflerini listeler . :"hiçbir şey yapma" anlamına gelir. Burada, allyukarıdaki hedef gibi ekoya ihtiyaç duyulmayan hedefler için kullanıyorum .
  • helpHedefin make helpçıktıya ":" eklemesi için ek bir hile vardır .

1

Bash Betiği İçin

İşte bunu yapmanın çok basit bir yolu bash- yukarıdaki @ cibercitizen1'in yorumuna dayanarak :

grep : Makefile | awk -F: '/^[^.]/ {print $1;}'

Ayrıca, Bash tamamlama modülünün bunu nasıl yaptığını söyleyen @ Marc.2377'nin daha yetkili cevabına da bakın make.


0

Yine başka bir ek cevap.

terminalde sadece cat ve awk kullanarak MacOSX'te test edildi

cat Makefile | awk '!/SHELL/ && /^[A-z]/ {print $1}' | awk '{print substr($0, 1, length($0)-1)}'

make dosyasının çıktısı aşağıdaki gibi olacaktır:

target1

target2

target3

Makefile'de, aynı ifade olmalı, değişkenlerden $ değişken yerine $$ değişkenini kullanarak kaçtığınızdan emin olmalısınız.

açıklama

cat - içeriği tükürür

| - boru çıkışı bir sonraki awk'a ayrıştırır

awk - "kabuk" hariç ve yalnızca "Az" satırlarını kabul ederek normal ifadeyi çalıştırır ve ardından 1 TL'lik ilk sütunu yazdırır

awk - yine de ":" son karakterini listeden kaldırır

bu kaba bir çıktı ve sadece AWK ile daha korkak şeyler yapabilirsiniz. Sed'den kaçınmaya çalışın, BSD varyantlarında olduğu kadar tutarlı değildir, yani bazıları * nix üzerinde çalışır, ancak MacOSX gibi BSD'lerde başarısız olur.

Daha

Bunu yapmak için bir dosyaya (değişikliklerle birlikte) , " sekme sekmesi " yaptığınızda varsayılan bash-tamamlama klasörüne /usr/local/etc/bash-completion.d/ yani bir dosyaya ekleyebilmeniz gerekir . hedefleri tek satırlı komut dosyasına dayanır.


cat yerine make -qp komutunu da kullanabilirsiniz. böylece make -qp | awk '/: / &&! /: = / && / ^ [Az] / &&! / PATH / &&! / DISPLAY / &&! / TERM_SESSION / &&! / USER_TEXT_ENCODING / &&! / Makefile / {print substr ($ 0, 1 , uzunluk (0 $) -1) | "sort -u"} '
Jimmy MG Lim

0

Genellikle yaparım:

grep install_targets Makefile

Böyle bir şeyle geri gelecekti:

install_targets = install-xxx1 install-xxx2 ... etc

Umarım bu yardımcı olur


0

AWK nefret edenler ve basitlik için bu mekanizma benim için işe yarıyor:

help:
  make -qpRr $(lastword $(MAKEFILE_LIST)) | egrep -v '(^(\.|:|#|\s|$)|=)' | cut -d: -f1

(bir Makefile dışında kullanmak için, $(lastword ...)onu Makefile yolu ile kaldırın veya değiştirin).

"İlginç" kural adlarınız varsa bu çözüm çalışmaz, ancak çoğu basit kurulum için iyi çalışır. make -qpTabanlı bir çözümün ana dezavantajı ( burada diğer cevaplarda olduğu gibi), Makefile işlevleri kullanarak değişken değerleri tanımlarsa - bunlar ne olursa olsun yürütülecek -qve eğer kullanılırsa $(shell ...)kabuk komutu hala çağrılacak ve yan etkileri olacak . Benim kurulumda genellikle kabuk fonksiyonlarının yan etkileri standart hataya istenmeyen çıktıdır, bu yüzden 2>/dev/nullmake komutundan sonra eklerim .


-4

önceki cevabın neden bu kadar karmaşık olduğundan emin değilim:

list:
    cat Makefile | grep "^[A-z]" | awk '{print $$1}' | sed "s/://g" 

8
Önceki cevabı o cevap kapsayacak DEĞİLDİR tüm senaryolar için geçerlidir, çünkü böylece, karmaşık: aracılığıyla tanımlanan hedeflerin (a) içerme değişkenleri (örneğin $(SHELLS): ...), (b) bir rakam ile başlamak hedefleri, (c) dahil olmayan değişken tanımların dahil edilmesi , (d) makeaçık bir makefile yolu ile belirtilmişse uygun makefile'ı hedeflemek . (a) kritik eksikliktir: doğru dosyayı güvenilir bir şekilde hedeflemiş olsanız bile , değişken genişlemenin olmaması nedeniyle ham dosyayı ayrıştırma genel durumda çalışmayacaktır.
mklement0

6
Komut aşağıdakilere basitleştirilmiş olabilir - ama: bir kenara, karmaşık yeniden ana nokta, sağlam yeterli değil olmasıdır : awk -F: '/^[A-z]/ {print $$1}' Makefile. Son olarak, büyük ölçüde akademik bir nokta: [A-z]yerine kullanmak [:alpha:]gibi yabancı bir karakterle başlayan hedefleri kaçıracağınız anlamına gelir á.
mklement0

@ mklement0 ilk awk komutunuz güzel çalışıyor ve şimdiye kadarki en basit olanı olsa da, [: alpha:] kullanmak bir nedenden dolayı onu kırıyor gibi görünüyor - bir test dosyasındaki bazı hedefleri kaçırıyor.
Brian Burns

@ bburns.km: Benim hatam: Dediğim gerekirdi [[:alpha:]]yerine [:alpha:]( [:alpha:]harflerin yerel ayara duyarlı setini temsil içeride bir karakter sınıfı ( [...]), dolayısıyla etkili ihtiyacını çift [[ / ' ]].
mklement0

4
Bu cevap neden bu kadar karmaşık? Bu kısa snippet'te birkaç işe yaramaz günah toplamayı başarıyorsunuz . awk -F: '/^[A-Za-z]/ { print $$1 }' Makefiletek bir işlem ve umarım daha doğru bir düzenli ifade kullanır (yine de önceki yorumlarda belirtildiği gibi alt çizgileri, sayıları vb. olan hedefleriniz olabilir).
Üçlü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.