मेकफाइल प्रतीक $ @ और $ <का क्या अर्थ है?


416
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
    $(CC) $(CFLAGS) $< -o $@

क्या करें $@और क्या करें $<?


5
उपरोक्त लिंक टूटा हुआ है, यहाँ एक और है: gnu.org/software/make/manual/html_node/Automatic-Variables.html
asciz

1
नमस्ते क्या यह ".cpp.o:" एक लक्ष्य के रूप में मतलब है? (पूर्व अंतिम पंक्ति?)।
छद्म नाम_127

3
".Cpp.o:" का अर्थ है ".cpp" (ऑब्जेक्ट फ़ाइलें) का निर्माण ".cpp" (स्रोत फ़ाइलें)
jaguzu

1
मुझे लगता है कि यह ध्यान दिया जाना चाहिए कि निम्नलिखित लिंक पर एक ट्यूटोरियल है जिसमें से मुझे विश्वास है कि मोहित ने अपनी पोस्ट में मेकफाइल प्राप्त किया है। mrbook.org/blog/tutorials/make
DeepDeadpool

Microsoft इसे फ़ाइलनाम मैक्रोज़ (NMAKE के लिए) कहता है, जो स्वचालित चर (MAKE के लिए) की तुलना में स्पष्ट है । शैक्षिक उद्देश्यों के लिए दोनों पक्षों को देखना उपयोगी है।
इवानजिन्हो

जवाबों:


502

$@फ़ाइल का नाम जनरेट किया जा रहा है, और $<पहली शर्त (आमतौर पर स्रोत फ़ाइल)। आप GNU मेक मैनुअल में इन सभी विशेष चरों की सूची पा सकते हैं ।

उदाहरण के लिए, निम्नलिखित घोषणा पर विचार करें:

all: library.cpp main.cpp

इस मामले में:

  • $@ का मूल्यांकन करता है all
  • $< का मूल्यांकन करता है library.cpp
  • $^ का मूल्यांकन करता है library.cpp main.cpp

16
यह ध्यान देने योग्य है कि $@जरूरी नहीं कि यह एक फाइल होने के कारण खत्म हो जाए, यह एक .PHONYलक्ष्य का नाम भी हो सकता है।
एपीमेरा

क्या मैं इसे कमांडलाइन विकल्पों में जोड़ सकता हूं: $@sविधानसभा-आउटपुट जैसे name.os उत्पन्न करने के लिए?
हुसैन तुगरुल ब्यूकुकिक

4
जब पहली निर्भरता एक सूची का प्रतिनिधित्व करने वाला चर है, तो सावधान रहें, $ <का मूल्यांकन इसके विस्तार के बाद किया जाता है। इसलिए जब LIST = lib1.cpp lib2.cpp, और सभी: $ {LIST} main.cpp, $ <का मूल्यांकन केवल lib1.cpp पर किया जाता है। कुछ साल पहले, मैंने कुछ समय बिताया था कि इस व्यवहार के कारण होने वाले परिणाम में क्या खुशी है।
किम

सामान्य रूप से @ @ लक्ष्य नाम को संदर्भित करता है जो बाईं ओर है:
दीपक किरण

78

$@और $<कहा जाता है स्वत: चर । चर $@फ़ाइल का नाम (यानी लक्ष्य) बनाया गया है और $<आउटपुट फ़ाइल बनाने के लिए आवश्यक पहली शर्त का प्रतिनिधित्व करता है।
उदाहरण के लिए:

hello.o: hello.c hello.h
         gcc -c $< -o $@

यहाँ, hello.oआउटपुट फ़ाइल है। यह वही है जो $@विस्तार करता है। पहले निर्भरता है hello.c। यही $<विस्तार है।

-cझंडा उत्पन्न .oफ़ाइल; man gccअधिक विस्तृत विवरण के लिए देखें । -oआउटपुट फ़ाइल बनाने के लिए निर्दिष्ट करता है।

अधिक जानकारी के लिए, आप लिनक्स मेकफाइल्स के बारे में इस लेख को पढ़ सकते हैं ।

इसके अलावा, आप GNU makeमैनुअल की जांच कर सकते हैं । इससे मेकफाइल्स बनाना और उन्हें डीबग करना आसान हो जाएगा।

यदि आप यह कमांड चलाते हैं, तो यह मेकफाइल डेटाबेस को आउटपुट करेगा:

make -p 

1
आपके उत्तर की तरह लगता $<है hello.c hello.h(दोनों) का विस्तार होगा । कृपया स्पष्ट करें।
डॉ। बीको जूल

हां, इसमें नमस्ते और हैलो दोनों शामिल होंगे।
निपुण

19
$<सिर्फ पहली वस्तु है। सभी को शामिल करने के लिए, का उपयोग करें $^
डॉ। बीको जूल

1
डॉ। बीको सही है। लेखक को अपना उत्तर संशोधित करना चाहिए।
पीटी हुआनह

67

जीएनयू मेक के साथ प्रबंध परियोजनाओं से , तीसरा संस्करण, पी। 16 (यह GNU फ्री डॉक्यूमेंटेशन लाइसेंस के तहत है ):

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

सात "मूल" स्वचालित चर हैं:

  • $@: लक्ष्य का प्रतिनिधित्व करने वाला फ़ाइल नाम।

  • $%: एक संग्रह सदस्य विनिर्देशन का फ़ाइल नाम तत्व।

  • $<: पहली शर्त का फ़ाइल नाम।

  • $?: सभी पूर्वापेक्षाओं के नाम जो लक्ष्य से नए हैं, रिक्त स्थान द्वारा अलग किए गए हैं।

  • $^: रिक्त स्थान द्वारा अलग किए गए सभी पूर्वापेक्षाओं के फ़ाइलनाम। इस सूची में डुप्लिकेट फ़ाइलनामों को हटा दिया गया है, क्योंकि अधिकांश उपयोग जैसे संकलन, कॉपी करना, आदि, डुप्लिकेट वांछित नहीं हैं।

  • $+: इसके समान $^, यह रिक्त स्थान द्वारा अलग किए गए सभी पूर्वापेक्षाओं के नाम हैं, सिवाय इसके कि $+डुप्लिकेट शामिल हैं। यह चर विशिष्ट स्थितियों के लिए बनाया गया था जैसे कि लिंकर्स के लिए तर्क जहां डुप्लिकेट मानों का अर्थ है।

  • $*: लक्ष्य फ़ाइल नाम का तना। एक स्टेम आमतौर पर अपने प्रत्यय के बिना एक फ़ाइल नाम है। पैटर्न नियमों के बाहर इसका उपयोग हतोत्साहित किया जाता है।

इसके अतिरिक्त, उपरोक्त प्रत्येक चर में अन्य परिवर्तनों के साथ संगतता के लिए दो संस्करण हैं। एक संस्करण केवल मान के निर्देशिका भाग को लौटाता है। यह प्रतीक करने के लिए एक 'डी' जोड़कर इंगित किया जाता है $(@D), $(<D)आदि अन्य संस्करण रिटर्न मूल्य का केवल फ़ाइल भाग। यह एक "एफ" प्रतीक को, जोड़कर इंगित किया जाता है $(@F), $(<F)आदि ध्यान दें कि इन संस्करण के नाम से ज्यादा एक वर्ण लंबा और इतना कर रहे हैं कोष्ठक में सीमित होने चाहिए। जीएनयू मेक डायर और नोटिर फ़ंक्शन के साथ अधिक पठनीय विकल्प प्रदान करता है।


37

$@और $<विशेष मैक्रो नहीं है।

कहाँ पे:

$@ लक्ष्य का फ़ाइल नाम है।

$< पहली निर्भरता का नाम है।


19

Makefile बनाता helloहै, तो में से किसी एक निष्पादन योग्य main.cpp, hello.cpp, factorial.cppबदल दिया है। उस विनिर्देश को प्राप्त करने के लिए सबसे छोटा संभव मेकफाइल हो सकता है:

hello: main.cpp hello.cpp factorial.cpp
    g++ -o hello main.cpp hello.cpp factorial.cpp
  • प्रो: पढ़ने के लिए बहुत आसान है
  • con: रखरखाव दुःस्वप्न, C ++ निर्भरता का दोहराव
  • con: दक्षता समस्या, हम सभी C ++ को फिर से जोड़ते हैं, भले ही केवल एक ही बदला गया हो

उपरोक्त सुधार के लिए, हम केवल उन C ++ फ़ाइलों को संकलित करते हैं जिन्हें संपादित किया गया था। फिर, हम केवल परिणामी ऑब्जेक्ट फ़ाइलों को एक साथ लिंक करते हैं।

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

main.o: main.cpp
    g++ -c main.cpp

hello.o: hello.cpp
    g++ -c hello.cpp

factorial.o: factorial.cpp
    g++ -c factorial.cpp
  • प्रो: दक्षता मुद्दे को हल करता है
  • con: नया रखरखाव दुःस्वप्न, वस्तु फाइलों के नियमों पर संभावित टाइपो

इस पर सुधार करने के लिए, हम सभी ऑब्जेक्ट फ़ाइल नियमों को एक नियम से बदल सकते हैं .cpp.o:

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

.cpp.o:
    g++ -c $< -o $@
  • समर्थक: वापस करने के लिए कुछ आसान बनाने के लिए, एक छोटा सा मेफाइल होने के लिए

यहां .cpp.oनियम यह बताता है कि निर्माण कैसे करना anyfile.oहै anyfile.cpp

  • $< इस मामले में पहली निर्भरता के लिए मैच, anyfile.cpp
  • $@लक्ष्य से मेल खाता है, इस मामले में, anyfile.o

Makefile में मौजूद अन्य परिवर्तन हैं:

  • G ++ से किसी C ++ कंपाइलर में कंपाइलर को बदलना आसान हो जाता है।
  • संकलक विकल्पों को बदलना आसान बनाता है।
  • लिंकर विकल्पों को बदलना आसान बनाता है।
  • C ++ स्रोत फ़ाइलों और आउटपुट को बदलना आसान बनाता है।
  • एक डिफ़ॉल्ट नियम 'ऑल' जोड़ा गया जो आपके आवेदन के निर्माण के प्रयास से पहले आपकी सभी स्रोत फ़ाइलों को सुनिश्चित करने के लिए त्वरित जाँच के रूप में कार्य करता है।

1

यदि आप स्रोतों को संकलित करना चाहते हैं तो अलग-अलग निर्देशिकाओं में वस्तुओं को प्राप्त करना चाहते हैं:

आपको करने की जरूरत है :

gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...

लेकिन अधिकांश मैक्रोज़ के साथ परिणाम सभी वस्तुओं के सभी स्रोतों द्वारा पीछा किया जाएगा, जैसे:

gcc -c -o <all OBJ path> <all SRC path>

इसलिए यह कुछ भी संकलित नहीं करेगा ^ ^ और आप अपनी वस्तुओं की फाइलों को एक अलग डायर में नहीं डाल पाएंगे :(

समाधान इन विशेष मैक्रो का उपयोग करना है

$@ $<

यह SRC (src / file.c) में प्रत्येक .c फ़ाइल के लिए .o फ़ाइल (obj / file.o) उत्पन्न करेगा।

$(OBJ):$(SRC)
   gcc -c -o $@ $< $(HEADERS) $(FLAGS)

इसका मतलब :

    $@ = $(OBJ)
    $< = $(SRC)

लेकिन एसआरसी की सभी लाइनों के बाद OBJ की सभी लाइनों की लाइनें INSTEAD


मुझे आश्चर्य है, आप "यू" के बजाय "यू" लिखकर उस समय की सभी राशि के साथ क्या करते हैं?
इवानजिन्हो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.