चूंकि यह यूनिक्स के लिए है, इसलिए एक्जीक्यूटिव के पास कोई एक्सटेंशन नहीं है।
ध्यान देने वाली एक बात यह है कि root-config
एक उपयोगिता है जो सही संकलन और लिंकिंग झंडे प्रदान करती है; और जड़ के खिलाफ अनुप्रयोगों के निर्माण के लिए सही पुस्तकालयों। यह इस दस्तावेज़ के लिए मूल श्रोताओं से संबंधित एक विवरण है।
मेक मी बेबी
या यू फर्स्ट टाइम यू गेट फॉर गॉट मेड
मेक की एक परिचयात्मक चर्चा, और सरल मेकफाइल कैसे लिखना है
क्या है मेक? और मैं क्यों परवाह करूं?
मेक नामक टूल एक बिल्ड डिपेंडेंसी मैनेजर है। यही है, यह जानने का ख्याल रखता है कि आपके सॉफ़्टवेयर प्रोजेक्ट को स्रोत फ़ाइलों, ऑब्जेक्ट फ़ाइलों, पुस्तकालयों, हेडर, आदि, आदि के संग्रह से किस क्रम में निष्पादित करने की आवश्यकता है ।--- जिनमें से कुछ बदल गए होंगे। हाल ही में --- और उन्हें कार्यक्रम के एक सही अप-टू-डेट संस्करण में बदल दिया।
वास्तव में, आप अन्य चीजों के लिए भी मेक का उपयोग कर सकते हैं, लेकिन मैं इसके बारे में बात नहीं करने जा रहा हूं।
एक तुच्छ मेकफाइल
मान लीजिए कि आपके पास एक निर्देशिका है: tool
tool.cc
tool.o
support.cc
support.hh
और support.o
जो निर्भर करता है root
और कहलाने वाले प्रोग्राम में संकलित किया जाता है tool
, और मान लीजिए कि आप स्रोत फ़ाइलों पर हैकिंग कर रहे हैं (जिसका मतलब है कि मौजूदा tool
तारीख से बाहर है) और चाहते हैं कार्यक्रम को संकलित करें।
यह अपने आप करने के लिए आप कर सकते हैं
यदि या तो चेक support.cc
या support.hh
से अधिक नया support.o
है, और यदि ऐसा है तो तरह एक आदेश चला
g++ -g -c -pthread -I/sw/include/root support.cc
यदि या तो चेक support.hh
या tool.cc
की तुलना में नए हैं tool.o
, और यदि हां की तरह एक आदेश चला
g++ -g -c -pthread -I/sw/include/root tool.cc
जाँच करें कि tool.o
क्या नया है tool
, और यदि ऐसा है तो जैसे कमांड चलाते हैं
g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
ओह! क्या झंझट है! याद करने के लिए बहुत कुछ है और गलतियाँ करने के कई मौके हैं। (BTW-- यहाँ प्रदर्शित कमांड लाइनों के विवरण हमारे सॉफ्टवेयर वातावरण पर निर्भर करते हैं। ये लोग मेरे कंप्यूटर पर काम करते हैं।)
बेशक, आप हर बार सभी तीन कमांड चला सकते हैं। यह काम करेगा, लेकिन यह सॉफ्टवेयर के एक बड़े टुकड़े (जैसे DOGS जो मेरे मैकबुक पर जमीन से संकलित होने में 15 मिनट से अधिक समय लेता है) के लिए अच्छी तरह से पैमाने पर नहीं है।
इसके बजाय आप makefile
इस तरह नामक एक फ़ाइल लिख सकते हैं :
tool: tool.o support.o
g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
tool.o: tool.cc support.hh
g++ -g -c -pthread -I/sw/include/root tool.cc
support.o: support.hh support.cc
g++ -g -c -pthread -I/sw/include/root support.cc
और make
कमांड लाइन पर टाइप करें । जो ऊपर दिखाए गए तीन चरणों को स्वचालित रूप से प्रदर्शित करेगा।
यहाँ की अनइंस्टाल्ड लाइन्स में "टारगेट: डिपेंडेंसीज़" फॉर्म होता है और यह बताएं कि संबंधित कमांड्स (इंडेंटेड लाइन्स) को रन किया जाना चाहिए, यदि कोई भी डिपेंडेंसी टारगेट की तुलना में नई हो। यही है, विभिन्न फ़ाइलों में परिवर्तन को समायोजित करने के लिए निर्भरता रेखाओं के तर्क का वर्णन किया जाना चाहिए। यदि support.cc
परिवर्तन है कि इसका मतलब है कि support.o
पुनर्निर्माण किया जाना चाहिए, लेकिन tool.o
अकेले छोड़ दिया जा सकता है। जब support.o
परिवर्तन tool
का पुनर्निर्माण किया जाना चाहिए।
प्रत्येक निर्भरता रेखा से जुड़ी कमांड को एक टैब के साथ सेट किया गया है (नीचे देखें) लक्ष्य को संशोधित करना चाहिए (या कम से कम इसे संशोधन समय को अपडेट करने के लिए स्पर्श करें)।
चर, नियमों में निर्मित, और अन्य उपहार
इस बिंदु पर, हमारा मेकफाइल बस उस काम को याद कर रहा है जिसे करने की आवश्यकता है, लेकिन हमें अभी भी यह पता लगाना था कि प्रत्येक और प्रत्येक आवश्यक कमांड को उसकी संपूर्णता में टाइप करें। इसका उस तरह से होना जरूरी नहीं है: मेक वेरिएबल्स, टेक्स्ट मैनिपुलेशन फंक्शंस और बिलकुल इन बिल्ट रूल्स वाली एक शक्तिशाली भाषा है जो हमारे लिए यह बहुत आसान बना सकती है।
चर करें
मेक वैरिएबल एक्सेस करने का सिंटैक्स है $(VAR)
।
एक चर बनाने के लिए वाक्यविन्यास है: VAR = A text value of some kind
(या VAR := A different text value but ignore this for the moment
)।
आप हमारे मेकफाइल के इस उन्नत संस्करण जैसे नियमों में चर का उपयोग कर सकते हैं:
CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
-Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
-lm -ldl
tool: tool.o support.o
g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
जो थोड़ा अधिक पठनीय है, लेकिन फिर भी बहुत टाइपिंग की आवश्यकता है
कार्य करें
GNU मे सिस्टम पर फाइलसिस्टम या अन्य कमांड्स से जानकारी हासिल करने के लिए कई प्रकार के कार्य करता है। इस मामले में हम में रुचि रखने वाले कर रहे हैं $(shell ...)
जो तर्क (रों) के उत्पादन के लिए विस्तारित, और $(subst opat,npat,text)
जो की सभी आवृत्तियों की जगह opat
के साथ npat
पाठ में।
इसका लाभ उठाकर हमें:
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
tool: $(OBJS)
g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
जो टाइप करना आसान है और बहुत अधिक पठनीय है।
नोटिस जो
- हम अभी भी प्रत्येक ऑब्जेक्ट फ़ाइल और अंतिम निष्पादन योग्य के लिए निर्भरता स्पष्ट रूप से बता रहे हैं
- हमें दोनों स्रोत फ़ाइलों के लिए संकलन नियम को स्पष्ट रूप से लिखना होगा
लागू और पैटर्न नियम
हम आम तौर पर उम्मीद करेंगे कि सभी सी ++ स्रोत फ़ाइलों को उसी तरह से व्यवहार किया जाना चाहिए, और मेक इसे राज्य करने के तीन तरीके प्रदान करता है:
- प्रत्यय नियम (जीएनयू में अप्रचलित माना जाता है, लेकिन पीछे की संगतता के लिए रखा गया है)
- निहित नियम
- पैटर्न नियम
अंतर्निहित नियम बनाए गए हैं, और कुछ पर नीचे चर्चा की जाएगी। पैटर्न नियमों को एक रूप में निर्दिष्ट किया जाता है
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
जिसका मतलब है कि ऑब्जेक्ट फाइलें सी स्रोत फाइलों से दिखाई गई कमांड को चलाकर उत्पन्न की जाती हैं, जहां "स्वचालित" चर $<
पहले निर्भरता के नाम पर फैलता है।
बिल्ट-इन रूल्स
मेक इन बिल्ट इन रूल्स की एक पूरी मेज़बानी है जिसका मतलब है कि बहुत बार, एक प्रोजेक्ट को बहुत ही साधारण मेकफाइल द्वारा संकलित किया जा सकता है।
C स्रोत फ़ाइलों के लिए नियम में निर्मित GNU मेक अप एक प्रदर्शनी है। इसी तरह हम C ++ सोर्स फाइल्स से ऑब्जेक्ट फाइल बनाते हैं जैसे रूल $(CXX) -c $(CPPFLAGS) $(CFLAGS)
।
सिंगल ऑब्जेक्ट फाइल्स का उपयोग करके लिंक किया गया है $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
, लेकिन यह हमारे मामले में काम नहीं करेगा, क्योंकि हम कई ऑब्जेक्ट फाइल्स को लिंक करना चाहते हैं।
अंतर्निहित नियम द्वारा प्रयुक्त चर
अंतर्निहित नियम मानक चर का एक सेट का उपयोग करते हैं जो आपको सभी नियमों को फिर से लिखने के बिना स्थानीय पर्यावरण जानकारी (जैसे रूट को खोजने के लिए फ़ाइलें शामिल करने) को निर्दिष्ट करने की अनुमति देता है। हमारे लिए सबसे दिलचस्प होने की संभावना है:
CC
- सी संकलक का उपयोग करने के लिए
CXX
- उपयोग करने के लिए C ++ कंपाइलर
LD
- उपयोग करने के लिए लिंकर
CFLAGS
- सी स्रोत फ़ाइलों के लिए संकलन ध्वज
CXXFLAGS
- सी ++ स्रोत फ़ाइलों के लिए संकलन झंडे
CPPFLAGS
- सी-प्रीप्रोसेसर के लिए झंडे (आमतौर पर कमांड लाइन पर परिभाषित फ़ाइल पथ और प्रतीक शामिल हैं), C और C ++ द्वारा उपयोग किए गए
LDFLAGS
- लिंकर झंडे
LDLIBS
- लिंक करने के लिए पुस्तकालय
एक बेसिक मेकफाइल
अंतर्निहित नियमों का लाभ उठाकर हम अपने मेकफाइल को सरल बना सकते हैं:
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
support.o: support.hh support.cc
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) tool
हमने कई मानक लक्ष्य भी जोड़े हैं जो विशेष क्रियाएं करते हैं (जैसे स्रोत निर्देशिका की सफाई)।
ध्यान दें कि जब मेक को एक तर्क के बिना लागू किया जाता है, तो यह फ़ाइल में पाए जाने वाले पहले लक्ष्य का उपयोग करता है (इस मामले में सभी), लेकिन आप लक्ष्य को भी नाम दे सकते हैं जो कि make clean
इस मामले में ऑब्जेक्ट फ़ाइलों को हटा देता है।
हमारे पास अभी भी सभी निर्भरताएं हार्ड-कोडेड हैं।
कुछ रहस्यमय सुधार
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
$(RM) ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) *~ .depend
include .depend
नोटिस जो
- स्रोत फ़ाइलों के लिए अब कोई निर्भरता रेखाएँ नहीं हैं!?!
- कुछ अजीब जादू से संबंधित है। निर्भरता और निर्भरता
- यदि आप करते हैं
make
तो ls -A
आपको एक फ़ाइल दिखाई देती है, .depend
जिसमें ऐसी चीज़ें होती हैं जो निर्भरता रेखाएँ बनाती हैं
अन्य पढ़ना
जानिए कीड़े और ऐतिहासिक नोट
मेक के लिए इनपुट भाषा व्हाट्सएप संवेदनशील है। विशेष रूप से, निर्भरता के बाद की कार्रवाई लाइनें एक टैब से शुरू होनी चाहिए । लेकिन रिक्त स्थान की एक श्रृंखला समान दिख सकती है (और वास्तव में संपादक हैं जो चुपचाप टैब को रिक्त स्थान या इसके विपरीत में बदल देंगे), जिसके परिणामस्वरूप एक मेक फ़ाइल बनती है जो सही दिखती है और फिर भी काम नहीं करती है। इसकी पहचान पहले बग के रूप में की गई थी, लेकिन ( कहानी आगे बढ़ती है ) यह तय नहीं था, क्योंकि पहले से ही 10 उपयोगकर्ता थे।
(यह मैंने भौतिकी स्नातक छात्रों के लिए लिखे एक विकि पोस्ट से कॉपी किया था।)