आप एक बदलाव में लक्ष्यों की सूची कैसे प्राप्त कर सकते हैं?


202

मैंने रेक बिट (रूबी मेक प्रोग्राम) का उपयोग किया है, और इसमें सभी उपलब्ध लक्ष्यों की सूची प्राप्त करने का विकल्प है, जैसे

> 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 मेक में ऐसा करने का कोई विकल्प नहीं है।

जाहिरा तौर पर कोड इसके लिए लगभग वहाँ है, जैसा कि 2007 - http://www.mail-archive.com/help-make@gnu.org/msg06434.html

वैसे भी, मैंने मेकफाइल से टारगेट निकालने के लिए बहुत कम हैक किया है, जिसे आप मेकफाइल में शामिल कर सकते हैं।

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

यह आपको परिभाषित लक्ष्यों की एक सूची देगा। यह सिर्फ एक शुरुआत है - उदाहरण के लिए, यह निर्भरता को फ़िल्टर नहीं करता है।

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

2
मैं जल्दी से उत्तर पढ़ता हूं, जो दिलचस्प हैं, लेकिन अब तक मैं खुद के लिए इसे एक सादे (सरल रूप में) (अपने .bashrc में) का उपयोग करके इसे सादे, सरल और पोर्टेबल रखना पसंद करता हूं: alias makefile-targets='grep "^[^#[:space:]].*:" Makefile' सबसे अधिक बार मुझे केवल वर्तमान मेकफाइल की जांच करने की आवश्यकता होती है, और समाप्ति को पूरा करता है मेरा उपनाम
रॉकीरॉड


4
क्या यह बहुत तुच्छ है grep : Makefile?
cibercitizen1

जवाबों:


130

यह @ nobar के महान दृष्टिकोण पर सुधार करने का एक प्रयास है:

  • लक्ष्य नामों को निकालने के लिए अधिक मजबूत कमांड का उपयोग करता है, जो उम्मीद करता है कि किसी भी गलत सकारात्मकता को रोकता है (और अनावश्यक के साथ दूर भी करता है sh -c)
  • वर्तमान डायरेक्टरी में मेकफाइल को हमेशा लक्षित नहीं करता है ; स्पष्ट रूप से निर्दिष्ट मेकफाइल्स का सम्मान करता है-f <file>
  • छिपे हुए लक्ष्यों को छोड़ देता है - सम्मेलन द्वारा, ये ऐसे लक्ष्य हैं जिनका नाम न तो अक्षर से शुरू होता है और न ही अंक से
  • एक एकल लक्ष्य लक्ष्य के साथ करता है
  • @निष्पादन से पहले इसे प्रतिध्वनित होने से रोकने के लिए कमांड को उपसर्ग करता है

उत्सुकता से, GNU makeमें एक बदलाव में परिभाषित लक्ष्यों के नाम सूचीबद्ध करने के लिए कोई सुविधा नहीं है। -pविकल्प उत्पादन है कि सभी लक्ष्यों में शामिल हैं पैदा करता है, लेकिन उन्हें अन्य जानकारी का एक बहुत में कहीं दबा देता है।

GNU के makeलिए एक बदलाव को निम्नलिखित नियम में रखें ताकि एक लक्ष्य का नाम दिया जा सके, listजिसमें सभी वर्णों के नामों को वर्णमाला क्रम में सूचीबद्ध किया गया हो - जैसे: आह्वानmake 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 '^$@$$'

महत्वपूर्ण : इसे चिपकाने पर, सुनिश्चित करें कि अंतिम पंक्ति ठीक 1 वास्तविक टैब चार द्वारा प्रेरित है। (रिक्त स्थान काम नहीं करते हैं)

ध्यान दें कि लक्ष्य की परिणामी सूची को क्रमबद्ध करना सबसे अच्छा विकल्प है, क्योंकि छँटाई नहीं करने से उस क्रम में मददगार उत्पादन नहीं होता है जिस क्रम में मेकफाइल में दिखाई देने वाले लक्ष्य संरक्षित नहीं होते हैं।
इसके अलावा, कई लक्ष्यों वाले एक नियम के उप-लक्ष्य अलग-अलग आउटपुट होते हैं और इसलिए, छंटाई के कारण, आमतौर पर एक दूसरे के बगल में दिखाई नहीं देते हैं; उदाहरण के लिए, शुरू होने वाले नियम में लक्ष्य नहींa z: होंगे और आउटपुट में एक-दूसरे के बगल में सूचीबद्ध होंगे , अगर अतिरिक्त लक्ष्य हैं।az

नियम की व्याख्या :

  • PHONY: list
    • टारगेट लिस्ट को फॉनी टारगेट घोषित करता है, अर्थात, किसी फाइल का जिक्र नहीं करता है , जिसके लिए उसका नुस्खा बिना शर्त रखा जाना चाहिए।
  • $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

    • मेकफाइल makeसे प्राप्त डेटाबेस को प्रिंट और पार्स करने के लिए फिर से आमंत्रित करता है:
      • -p डेटाबेस प्रिंट करता है
      • -Rr निर्मित नियमों और चर को शामिल करना
      • -qकेवल लक्ष्य-अप-तिथि-स्थिति का परीक्षण करता है (कुछ भी याद किए बिना), लेकिन वह स्वयं सभी मामलों में नुस्खा आदेशों के निष्पादन को नहीं रोकता है; अत:
      • -f $(lastword $(MAKEFILE_LIST))यह सुनिश्चित करता है कि एक ही मेकफाइल को मूल आह्वान के रूप में लक्षित किया गया है, भले ही यह स्पष्ट रूप से या स्पष्ट रूप से लक्षित किया गया हो -f ...
        कैविएट : यह टूट जाएगा यदि आपके मेकफाइल में includeनिर्देश हैं; इसे संबोधित करने के लिए, किसी भी निर्देश THIS_FILE := $(lastword $(MAKEFILE_LIST)) से पहले चर को परिभाषित includeकरें और -f $(THIS_FILE)इसके बजाय उपयोग करें ।
      • :एक है जानबूझ कर अवैध लक्ष्य है कि करने के लिए है यह सुनिश्चित करें कि कोई आदेशों क्रियान्वित कर रहे हैं ; 2>/dev/nullपरिणामी त्रुटि संदेश को दबा देता है। नोट: यह -pफिर भी डेटाबेस को प्रिंट करने पर निर्भर करता है , जो कि GNU मेक 3.82 जैसा है। दुःख की बात करने के लिए जीएनयू कर प्रस्तावों कोई सीधा विकल्प सिर्फ डेटाबेस प्रिंट, बिना भी डिफ़ॉल्ट (या दिए गए) कार्य को क्रियान्वित करने; यदि आपको किसी विशिष्ट मेकफाइल को लक्षित करने की आवश्यकता नहीं है, तो आप पृष्ठ make -p -f/dev/nullमें अनुशंसित अनुसार उपयोग कर सकते हैं man
  • -v RS=

    • यह एक अजीब मुहावरा है जो इनपुट को सन्निहित गैर-रिक्त लाइनों के ब्लॉक में तोड़ता है।
  • /^# File/,/^# Finished Make data base/
    • आउटपुट में उन पंक्तियों की श्रेणी से मेल खाती है, जिनमें सभी लक्ष्य शामिल हैं (GNU 3.82 जैसा सही है) - इस सीमा तक पार्सिंग को सीमित करके, अन्य आउटपुट खंडों से झूठी सकारात्मकता से निपटने की कोई आवश्यकता नहीं है।
  • if ($$1 !~ "^[#.]")
    • चुनिंदा ब्लॉकों को अनदेखा करता है:
      • # ... गैर-लक्ष्यों को नजरअंदाज करता है, जिनके ब्लॉक शुरू होते हैं # Not a target:
      • . ... विशेष लक्ष्यों को नजरअंदाज करता है
    • अन्य सभी ब्लॉकों को प्रत्येक पंक्ति के साथ शुरू करना चाहिए जिसमें केवल स्पष्ट रूप से परिभाषित लक्ष्य का नाम होता है :
  • egrep -v -e '^[^[:alnum:]]' -e '^$@$$' आउटपुट से अवांछित लक्ष्य निकालता है:
    • '^[^[:alnum:]]'... छिपे हुए लक्ष्यों को बाहर करता है, जो - सम्मेलन द्वारा - ऐसे लक्ष्य हैं जो न तो एक अक्षर से शुरू होते हैं और न ही एक अंक से।
    • '^$@$$'... listलक्ष्य को छोड़कर

रनिंग make listतब सभी लक्ष्यों को प्रिंट करता है, प्रत्येक अपनी लाइन पर; आप xargsइसके बजाय एक अंतरिक्ष-पृथक सूची बनाने के लिए पाइप कर सकते हैं ।


यह एक महान जवाब है, हालांकि, मुझे प्रत्येक कार्य के लिए विवरण कैसे मिलेगा? वर्तमान में, मैं इसे कार्य परिभाषा के ऊपर एक टिप्पणी के रूप में संग्रहीत कर रहा हूं। सुनिश्चित नहीं है कि यदि संभव हो तो इसे सूची में उसी तरह से शामिल करना चाहिए जैसा rake --tasksवह करता है?
पायोत्र कुक्ज़िंस्की

1
@PiotrKuczynski: दिलचस्प सवाल है, लेकिन मेरा सुझाव है कि आप इसे एक नए प्रश्न के रूप में पोस्ट करें (संदर्भ के लिए इसे इंगित करते हुए)।
mklement0

"अफसोस की बात है कि जीएनयू केवल डेटाबेस प्रिंट करने के लिए कोई प्रत्यक्ष विकल्प नहीं देता है।" एक -nविकल्प है।
बुलेटमैग्नेट

@Bulletmagnet: -nविकल्प का उद्देश्य "उन कमांड को प्रिंट करना है, जिन्हें निष्पादित किया जाएगा ..." - दूसरे शब्दों में: एक ड्राई-रन सुविधा। इसके अलावा कि आपके उद्धरण शब्द के italicization याद आ रही है कि नहीं बस : make -pअपने आप में करता है डेटाबेस प्रिंट, लेकिन हमेशा भी डिफ़ॉल्ट कार्य चलाता है ; मैनुअल क्लंकी make -p -f/dev/nullसे बचने की सलाह देता है।
mklement0

1
किसी भी .PHONY लक्ष्यों को भी सूचीबद्ध करेगा, इसलिए सुनिश्चित करें कि आपके पास नहीं है.PHONY: *
Tekumara

189

बैश (कम से कम) के तहत, यह टैब पूर्णता के साथ स्वचालित रूप से किया जा सकता है:

make spacetabtab


1
परीक्षण किया गया: bash --version = 4.2.45 (1) -release। Make --version = 3.81।
नोबार

53
+1, लेकिन ध्यान दें कि यह बैश फीचर नहीं है , बल्कि आपके प्लेटफॉर्म पर निर्भर करता है । प्लेटफ़ॉर्म तीन श्रेणियों में आते हैं: वे जहाँ यह पूरा होना डिफ़ॉल्ट रूप से स्थापित होता है (उदाहरण के लिए, डेबियन 7, फेडोरा 20), वे जहाँ आप इसे वैकल्पिक रूप से स्थापित कर सकते हैं (जैसे, Ubuntu 14, साथ . /etc/bash_completion), और वे जो इसका समर्थन नहीं करते हैं। (उदाहरण के लिए, OSX 10.9)
mklement0

8
यह OS X 10.10 पर काम करता है (बैश के साथ नहीं बल्कि zsh के साथ)।
फ्लोरियन ओसवाल्ड

4
शानदार टिप लेकिन bash-completionपैकेज की भी जरूरत है। फेडोरा, RHEL, Gentoo, ect में मिला।
नोएलप्रोफ

4
यह प्रोग्रामेटिक रूप से बनाए गए लक्ष्य AFAICT, जैसे$(RUN_TARGETS): run-%: ...
Matthias

31

यह स्पष्ट रूप से कई मामलों में काम नहीं करेगा, लेकिन यदि आपका Makefileसीएमके द्वारा बनाया गया था तो आप चला सकते हैं 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

क्या आपके पास अपने CMakeList को चालू करने का कोई विकल्प है? मुझे सीएमके द्वारा एक मेकफाइल मिला और मेरे पास छद्म सहायता लक्ष्य उपलब्ध नहीं है
जेवियर टी।

नहीं। OSX पर कम से कम हाल के सीएमके के साथ (मैं वास्तव में नाइटलाइफ़ का उपयोग कर रहा हूं लेकिन मेरा मानना ​​है कि जब मैंने लिखा था कि मैं 3.3 का उपयोग कर रहा था), बस चलाएं touch CMakeLists.txt && cmake . && make helpऔर यह काम करना चाहिए। मैं केवल अनुमान लगा सकता हूं कि आप एक प्राचीन cmake का उपयोग कर रहे हैं, या यूनिक्स मेकफाइल्स जनरेटर का उपयोग नहीं कर रहे हैं?
टिम्मम

मैं विंडोज पर यूनिक्स जनरेटर के साथ सीएमके 3.6.2 का उपयोग कर रहा हूं। मैं एक स्पष्टीकरण के लिए चारों ओर खुदाई करूँगा क्योंकि यह आसान लगता है।
ज़ेवियर टी।

26

मैंने इन दो उत्तरों को जोड़ दिया: https://stackoverflow.com/a/9524878/86967 और https://stackoverflow.com/a/7390874/86967 और कुछ बचने के लिए ऐसा किया ताकि इसे मेकफाइल के अंदर से इस्तेमाल किया जा सके।

.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
मैंने भी (हाल ही में) खोजा है कि बैश के तहत टैब पूरा होने पर उपलब्ध लक्ष्य सूचीबद्ध होंगे।
नोबार

1
एक महान दृष्टिकोण के लिए +1, लेकिन कुछ सुधार किए जा सकते हैं: (ए) स्पष्ट रूप से निर्दिष्ट sh -c "…"करना अनावश्यक है, क्योंकि यह वही है makeजो डिफ़ॉल्ट रूप से नुस्खा कमांडों को लागू करने के लिए उपयोग करता है; (बी) आपके द्वारा उपयोग की जाने वाली कमांड बहुत सरल है, जिसके परिणामस्वरूप झूठी सकारात्मकता (जैसा कि आप ध्यान दें); (c) यदि आप कमांड को उपसर्ग करते हैं @, तो इसे क्रियान्वयन से पहले उपयोग करने की आवश्यकता को मानते हुए, निष्पादन से पहले स्टडआउट के लिए प्रतिध्वनित नहीं किया जाएगा -s
mklement0

1
वहाँ एक बहुत आसान लक्ष्य आप जोड़ सकते हैं: सूची: बिल्ली Makefile | grep "^ [Az]" | awk '{प्रिंट $ $ 1}' | sed "s /: // g | सॉर्ट"
thamster

2
बिल्ली / पालक का दृष्टिकोण कई स्तरों पर विफल रहता है। यह चर का विस्तार नहीं करता है, और उन लक्ष्यों को सूचीबद्ध करने में भी विफल रहता है जो अन्य फ़ाइलों को शामिल करने का परिणाम हैं।
ट्रॉय डेनियल

1
@ mklement0: मैं मेकफाइल make -sमें उपसर्ग कमांड के बजाय (बैश उर्फ ​​के माध्यम से) उपयोग करना पसंद करता हूं @। ऐसे कुछ मामले @हैं जो उपयोगी हो सकते हैं, विशेष रूप से echoकमांड्स के लिए उपसर्ग के रूप में (जहां कमांड का प्रदर्शन निरर्थक होगा), लेकिन सामान्य तौर पर मैं इसका उपयोग करना पसंद नहीं करता। इस तरह, मैं "व्यंजनों" को देख सकता हूं जब मुझे ज़रूरत होती है ( उपयोग करके -s), लेकिन आम तौर पर नहीं। यहां संबंधित दस्तावेज हैं: जीएनयू मेक मैनुअल, 5.2 नुस्खा गूंज
14

14

यदि आपके पास makeस्थापित करने के लिए बैश पूरा हो गया है, तो पूर्ण स्क्रिप्ट एक फ़ंक्शन को परिभाषित करेगा _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

3
सहायक, लेकिन ध्यान दें कि सभी प्लेटफार्मों में स्क्रिप्ट /etc/bash_completionऔर / या फ़ंक्शन नहीं है _make_target_extract_script- आप उबंटू पर लगते हैं> 12. यदि आप /usr/share/bash-completion/completions/makeइसके बजाय लक्ष्य करते हैं, तो आपका दृष्टिकोण अतिरिक्त प्लेटफार्मों पर काम करेगा, जैसे कि फेडोरा 20। पुराने (पुराने) प्लेटफॉर्म हैं यह फ़ाइल, लेकिन फ़ंक्शन नहीं (उदाहरण के लिए, डेबियन 7 और उबंटू 12); अन्य प्लेटफ़ॉर्म, जैसे कि OSX, makeसभी के लिए टैब पूरा करने के साथ नहीं आते हैं । शायद वास्तविक फ़ंक्शन परिभाषा पोस्ट करना सहायक होगा।
mklement0

1
आपके कमेंट के लिए धन्यवाद। यह बहुत सराहना की है। हां, मैंने इसका परीक्षण Ubuntu 14.04
hek2mgl

11

जैसा कि mklement0 बताता है , सभी Makefile लक्ष्यों को सूचीबद्ध करने के लिए एक सुविधा से गायब है, और उनका जवाब और अन्य ऐसा करने के तरीके प्रदान करते हैं।

हालांकि, मूल पोस्ट में रेक का भी उल्लेख किया गया है , जिसके कार्य स्विच रेकफाइल में सभी कार्यों को सूचीबद्ध करने की तुलना में कुछ अलग करते हैं। रेक आपको केवल उन कार्यों की एक सूची देगा, जिनसे संबंधित विवरण हैं। बिना विवरण के कार्य सूचीबद्ध नहीं होंगे । यह लेखक को अनुकूलित सहायता विवरण प्रदान करने की क्षमता देता है और कुछ लक्ष्यों के लिए मदद भी छोड़ देता है।

यदि आप रेक के व्यवहार का अनुकरण करना चाहते हैं, जहां आप प्रत्येक लक्ष्य के लिए विवरण प्रदान करते हैं , तो ऐसा करने के लिए एक सरल तकनीक है: सूचीबद्ध किए गए प्रत्येक लक्ष्य के लिए टिप्पणियों में विवरण एम्बेड करें।

आप या तो विवरण को लक्ष्य के बगल में रख सकते हैं या, जैसा कि मैं अक्सर करता हूं, लक्ष्य से ऊपर एक PHONY विनिर्देश के बगल में, इस तरह:

.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

जिससे उपज होगी

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

...
help                Generate list of targets with descriptions

आप इस जिस्ट में और यहां भी एक छोटा कोड उदाहरण पा सकते हैं।

फिर, यह मेकफाइल में सभी लक्ष्यों को सूचीबद्ध करने की समस्या को हल नहीं करता है। उदाहरण के लिए, यदि आपके पास एक बड़ा मेकफाइल है जो शायद उत्पन्न हुआ था या जिसे किसी और ने लिखा था, और आप इसके माध्यम से अपने लक्ष्यों को बिना खोदने के लिए त्वरित तरीका चाहते हैं, तो यह मदद नहीं करेगा।

हालाँकि, यदि आप एक मेकफाइल लिख रहे हैं, और आप एक सुसंगत, स्व-दस्तावेजीकरण में मदद पाठ उत्पन्न करने का एक तरीका चाहते हैं, तो यह तकनीक उपयोगी हो सकती है।


यह एक बढ़िया तकनीक है - अच्छी और सरल लेकिन वर्णन भी देती है!
ब्रायन बर्न्स

बढ़िया तकनीक। मैंने echoकमांड विवरण ( stackoverflow.com/a/52059487/814145 ) के रूप में कमांड का उपयोग करने के लिए इसे थोड़ा संशोधित किया ।
पेंघे गेंग

@PengheGeng पोस्ट के लिए धन्यवाद। मैं स्पष्ट करना चाहता हूं कि @echo "Target 1"यह केवल एक प्लेसहोल्डर है और "विवरण इको कमांड" नहीं है। उत्पन्न सहायता पाठ @echo's से नहीं आ रहा है । एक वास्तविक मेकफाइल में, इनका echoनिर्माण बिल्ड कमांड या कुछ-कुछ द्वारा किया जाएगा। मैं इसे और अधिक स्पष्ट करने के लिए पोस्ट संपादित करूंगा।
jsp

4

@ नोबार का उत्तर मदद करता है कि एक मेफाइल के लक्ष्यों को सूचीबद्ध करने के लिए टैब समापन का उपयोग कैसे करें

  • यह उन प्लेटफार्मों के लिए बहुत अच्छा काम करता है जो डिफ़ॉल्ट रूप से यह कार्यक्षमता प्रदान करते हैं (जैसे, डेबियन, फेडोरा )।

  • अन्य प्लेटफ़ॉर्म पर (जैसे, उबंटू ) आपको स्पष्ट रूप से इस कार्यक्षमता को लोड करना होगा , जैसा कि @ hek2mgl के उत्तर द्वारा दिया गया है :

    • . /etc/bash_completion एक के लिए एक सहित कई टैब-पूर्ण कार्यों को स्थापित करता है make
    • वैकल्पिक रूप से, केवल टैब पूर्णता स्थापित करने के लिए make:
      • . /usr/share/bash-completion/completions/make
  • उन प्लेटफ़ॉर्म के लिए, जो इस कार्यक्षमता को प्रस्तुत नहीं करते हैं , जैसे कि OSX , आप इसे लागू करने के लिए निम्नलिखित कमांड ( यहाँ से प्रचलित ) कर सकते हैं:
_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
  • नोट: यह लिनक्स वितरण के साथ आने वाले टैब-पूर्ण कार्यक्षमता के रूप में परिष्कृत नहीं है: सबसे विशेष रूप से, यह वर्तमान निर्देशिका में मेकफाइल को लक्षित करता है , भले ही कमांड लाइन एक अलग मेकफाइल के साथ लक्षित हो -f <file>

4

इस पर मेरा पसंदीदा उत्तर यूनिक्स एंड लिनक्स स्टैक एक्सचेंज में क्रिस डाउन द्वारा पोस्ट किया गया था । मैं बोली।

यह इस तरह से makeअपनी सूची प्राप्त करने के लिए बैश पूरा करने वाला मॉड्यूल है :

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

यह पेजिंग के बिना लक्ष्य की एक नई-सीमांकित सूची को प्रिंट करता है।

उपयोगकर्ता ब्रेनस्टोनsort -u डुप्लिकेट प्रविष्टियों को हटाने के लिए पाइपिंग का सुझाव देता है :

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

स्रोत: कैसे बनाने के लिए सभी लक्ष्यों को सूचीबद्ध करें? (यूनिक्स और लिनक्स एसई)


4

एक लक्ष्य लक्ष्य का वर्णन करने के लिए एक आसान वाक्यविन्यास पर ध्यान केंद्रित करना, और एक स्वच्छ आउटपुट होना, मैंने इस दृष्टिकोण को चुना:

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:

इसलिए ऊपर दिए गए को मेकफाइल मानकर उसे चलाने से आपको कुछ ऐसा मिलता है

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

आदेशों की श्रृंखला के लिए स्पष्टीकरण:


बहुत अच्छा समाधान है। मैं अब कुछ वर्षों के लिए इस का इस्तेमाल किया है .: awk -F ':|##' '/^[^\t].+:.*##/ { printf "\033[36mmake %-28s\033[0m -%s\n", $$1, $$NF }' $(MAKEFILE_LIST) | sort साथ ##लक्ष्य के रूप में एक ही लाइन पर टिप्पणी करने से पहले। लेकिन मुझे लगता है कि पठनीयता से पहले आपका समाधान अनुमति देता है।
वक्ष

एक मेकफाइल में grep: parentheses not balancedमेरी OSX 10.15 मशीन पर पहले दो लाइनों की रिपोर्ट शामिल थी।
मैल्कम क्रॉम

@ क्रैमी सॉरी, मेरी गलती है। इस पर ध्यान दिलाने के लिए धन्यवाद। ठीक कर दिया। डॉलर के संकेतों से बचने की आवश्यकता है जो चर नाम शुरू करने के लिए नहीं हैं।
रिचर्ड कीफर

बाहर देखें, StackOverflow टैब को रिक्त स्थान में परिवर्तित करता है जब ऊपर दिए गए कोड सेक्शन को प्रदर्शित करते हैं, लेकिन Makefiles को टैब की आवश्यकता होती है। आप पोस्ट को संपादित कर सकते हैं और फिर अनुभागों को कॉपी कर सकते हैं, इसलिए टैब को बनाए रखा जाता है।
रिचर्ड कीफर

2

यहाँ काम के बहुत सारे समाधान हैं, लेकिन जैसा कि मैंने कहा, "अगर यह एक बार करने लायक है, तो यह फिर से करने के लायक है।" मैंने उपयोग करने के लिए टैब (टैब) (टैब) का उपयोग किया है, लेकिन जैसा कि कुछ ने उल्लेख किया है, आपके पास पूर्ण समर्थन नहीं हो सकता है, या, यदि आपके पास कई फाइलें शामिल हैं, तो आप यह जानने का एक आसान तरीका चाह सकते हैं कि कोई लक्ष्य कहां परिभाषित किया गया है।

मैंने उप-निर्माण के साथ नीचे का परीक्षण नहीं किया है ... मुझे लगता है कि यह काम नहीं करेगा। जैसा कि हम जानते हैं, पुनरावर्ती हानिकारक माना जाता है।

.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 लाइनें, जो इंडेंट नहीं हैं, टिप्पणियां नहीं हैं, और एक अवधि के साथ शुरू नहीं होती हैं
  • तत्काल असाइनमेंट एक्सप्रेशंस को बाहर करें: (=)
  • कट, सॉर्ट, इंडेंट, और नियम-निर्भरता को काटें (बृहदान्त्र के बाद)
  • विस्तार को रोकने के लिए परिवर्तनशील परिसीमन को मून करें

नमूना आउटपुट:

 = 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

यह मेरे लिए मददगार था क्योंकि मैं निर्माण लक्ष्य (और उनकी निर्भरता) को लक्ष्य बनाकर देखना चाहता था। मुझे पता है कि लक्ष्य बनाना "" से शुरू नहीं हो सकता। चरित्र। मुझे नहीं पता कि भाषाओं का समर्थन क्या है, इसलिए मैं एग्रेप के ब्रैकेट के भावों के साथ गया।

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

1

यह साफ है, लेकिन मेरे लिए काम किया है।

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

मैं make -pआंतरिक डेटाबेस को खोदता हूं , खाई को बढ़ाता हूं , grep -A 100000आउटपुट के निचले हिस्से को रखने के लिए एक त्वरित और गंदे का उपयोग करता हूं । फिर मैं कुछ के साथ आउटपुट को साफ करता हूं grep -v, और अंत cutमें कॉलन से पहले जो लक्ष्य है, उसे प्राप्त करने के लिए उपयोग करता हूं ।

यह मेरे अधिकांश मेकफाइल्स पर मेरी सहायक लिपियों के लिए पर्याप्त है।

संपादित करें: grep -v Makefileएक आंतरिक नियम है


1

यह jsp के बहुत सहायक उत्तर ( https://stackoverflow.com/a/45843594/814145 ) के लिए एक संशोधन है । मुझे न केवल लक्ष्यों की एक सूची प्राप्त करने का विचार पसंद है, बल्कि उनके विवरण भी हैं। जेएसपी मेकफाइल विवरण को टिप्पणी के रूप में रखता है, जो मैंने पाया कि अक्सर लक्ष्य विवरण गूंज कमांड में दोहराया जाएगा। इसलिए इसके बजाय, मैं प्रत्येक लक्ष्य के लिए गूंज कमांड से विवरण निकालता हूं।

उदाहरण मेकफाइल:

.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

का आउटपुट 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

टिप्पणियाँ:

  • समान रूप से jsp के जवाब है, केवल जाली लक्ष्य, सूचीबद्ध किया जा सकता है जो कर सकते हैं या हो सकता है आपके मामले के लिए काम करते नहीं
  • इसके अलावा, यह केवल उन PHONY लक्ष्यों को सूचीबद्ध करता है जिनके पास नुस्खा के पहले कमांड के रूप में echoया :कमांड है। :का अर्थ है "कुछ नहीं करना"। मैं इसे यहाँ उन लक्ष्यों के लिए उपयोग करता हूँ जो किसी भी प्रतिध्वनि की आवश्यकता नहीं है, जैसे किall ऊपर दिए गए लक्ष्य।
  • आउटपुट helpमें ":" जोड़ने के लिए लक्ष्य के लिए एक अतिरिक्त चाल है make help

0

फिर भी ऊपर एक और अतिरिक्त जवाब।

केवल बिल्ली का उपयोग करके और टर्मिनल पर जागने पर मैकओएसएक्स पर परीक्षण किया गया

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

नीचे की तरह मेक फाइल का आउटपुट होगा:

target1

target2

target3

मेकफाइल में, यह एक ही कथन होना चाहिए, सुनिश्चित करें कि आप $ चर के बजाय $ $ चर का उपयोग करके चर से बच जाते हैं।

व्याख्या

बिल्ली - सामग्री बाहर थूकता है

| - पाइप पार्स उत्पादन अगले awk के लिए

awk - "शेल" को छोड़कर रेगेक्स चलाता है और केवल "एज़" लाइनों को स्वीकार करता है और फिर $ 1 पहला कॉलम प्रिंट करता है

awk - फिर भी सूची से अंतिम वर्ण ":" को हटा देता है

यह एक मोटा आउटपुट है और आप केवल AWK के साथ अधिक फंकी सामान कर सकते हैं। सेड से बचने की कोशिश करें क्योंकि इसकी बीएसडीएस वेरिएंट में संगत नहीं है अर्थात कुछ काम * निक्स पर होते हैं लेकिन बीएसडी पर मैकओएसएक्स की तरह विफल होते हैं।

अधिक

आप में सक्षम इस के लिए एक फाइल करने के लिए (संशोधनों के साथ) ऐड होना चाहिए मेकअप , /usr/local/etc/bash-completion.d/ अर्थ फ़ोल्डर डिफ़ॉल्ट बैश: पूर्ण करने के लिए जब आप "मेक टैब टैब " .. यह पूरा हो जाएगा एक लाइनर स्क्रिप्ट के आधार पर लक्ष्य।


आप बिल्ली के बजाय मेकअप का उपयोग भी कर सकते हैं। तो यह मेक-बीपी बन जाएगा | awk '/: / &&! /: = / && / ^ [Az] / &&! / PAT / / && / / DISPLAY / &&! / TERM_SESSION / &&! / USER_TEXT /ENCODING / &&! / Makefile / {प्रिंट पदार्थ ($ 0, 1)। , लंबाई ($ 0) -1) | "सॉर्ट -यू"} '
जिमी एमजी लिम

0

मैं आमतौर पर करता हूं:

grep install_targets Makefile

यह कुछ इस तरह से वापस आएगा:

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

आशा है कि ये आपकी मदद करेगा


0

एक बैश स्क्रिप्ट के लिए

यह करने के लिए एक बहुत ही सरल तरीका है bash- ऊपर @ cibercitizen1 द्वारा टिप्पणी के आधार पर :

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

@ Marc.2377 द्वारा अधिक आधिकारिक उत्तर भी देखें , जो यह भी कहता है कि इसके लिए बैश समापन मॉड्यूल कैसे makeहै।


-4

निश्चित नहीं कि पिछला उत्तर इतना जटिल क्यों था:

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

8
पिछले जवाब हां, तो जटिल है क्योंकि यह सभी परिस्थितियों में आपको अपने जवाब को कवर नहीं करता शामिल हैं: (क) के माध्यम से लक्ष्य निर्धारित के शामिल किए जाने चर (जैसे, $(SHELLS): ...), (ख) लक्ष्य है कि अंक के साथ शुरू करते हैं, (ग) के शामिल किए जाने गैर चर परिभाषाओं का समावेश , (डी) makeएक स्पष्ट मेकफाइल पथ के साथ निर्दिष्ट किए जाने पर उचित मेकाइल को लक्षित करना । (ए) महत्वपूर्ण कमी है: भले ही आपने सही मेकफाइल को लक्षित किया हो, चर विस्तार की कमी के कारण कच्ची फ़ाइल को पार्स करना सामान्य मामले में काम नहीं करेगा।
22

6
एक अलग रूप में के रूप में, फिर से जटिल: अपने आदेश निम्न के सरल किया जा सकता है - लेकिन मुख्य मुद्दा यह है कि यह मजबूत पर्याप्त नहीं है है : awk -F: '/^[A-z]/ {print $$1}' Makefile। अंत में, एक बड़े पैमाने पर शैक्षिक बिंदु: का उपयोग कर [A-z]के बजाय [:alpha:]का मतलब है कि आप लक्ष्य है कि इस तरह के रूप में एक विदेशी अक्षर से आरंभ होने को खो देंगे á
mklement0

@ mklement0 आपका पहला awk कमांड अच्छी तरह से काम करता है, और अब तक का सबसे सरल है, हालांकि [: अल्फ़ा:] का उपयोग करना किसी कारण से इसे तोड़ना लगता है - यह एक परीक्षण फ़ाइल में कुछ लक्ष्यों को याद करता है।
ब्रायन बर्न्स

@ bburns.km: मेरा बुरा: मुझे इसके [[:alpha:]]बजाय कहना चाहिए था [:alpha:]( चरित्र वर्ग के अंदर[:alpha:] अक्षरों के स्थानीय-जागरूक सेट का प्रतिनिधित्व करता है ) ( इसलिए, डबल / के लिए प्रभावी आवश्यकता ।[...] [[]]
mklement0

4
यह जवाब इतना जटिल क्यों है ? आप इस छोटे से स्निपेट में कई बेकार पापों को इकट्ठा करने का प्रबंधन करते हैं । awk -F: '/^[A-Za-z]/ { print $$1 }' Makefileएक ही प्रक्रिया का उपयोग करता है और उम्मीद है कि एक अधिक सही नियमित अभिव्यक्ति (हालांकि आप निश्चित रूप से अंडरस्कोर, संख्या आदि के साथ लक्ष्य कर सकते हैं, साथ ही साथ पूर्व टिप्पणियों में भी उल्लेख किया गया है)।
ट्रिपल जू 15:16
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.