परिचय

C प्रोग्रामिंग में, एक कार्यक्रम अक्सर कई स्रोत फ़ाइलों और हेडर फ़ाइलों को संगठन, पुन: प्रयोज्यता और संकलन गति में सुधार करने के लिए विभाजित किया जाता है। हालांकि, यह मॉड्यूलरिटी एक चुनौती का परिचय देती है: जब एक हेडर फ़ाइल में परिवर्तन होता है, तो प्रत्येक स्रोत फ़ाइल में शामिल होना चाहिए। ऐसा करने से मैन्युअल रूप से त्रुटि-प्रवण और समय लेने वाली त्रुटि होती है। मेकफ़ाइल्स स्वचालित रूप से make] द्वारा संचालित एक ऐसे तरीके से काम करने वाली संरचना को उत्पन्न करते हैं, जो इस समस्या को एन्कोडिंग निर्भरता द्वारा हल करते हैं और निर्माण प्रक्रिया को स्वचालित करते हैं।

क्या Makefiles हैं?

A Makefile एक सादे पाठ फ़ाइल है जो एक परियोजना के निर्माण के लिए नियमों का एक सेट को परिभाषित करती है। make उपयोगिता इन नियमों को पढ़ती है, फ़ाइल टाइमटाम्प्स की जांच करती है, और परियोजना को तारीख तक लाने के लिए आवश्यक केवल आदेशों को निष्पादित करती है। मूल विचार सरल है: प्रत्येक नियम में एक target](fLT]}.

मेकफ़ाइल्स 1970 के दशक से यूनिक्स का हिस्सा रहा है, और GNU मेक लिनक्स और मैकओएस पर वास्तविक मानक है। वाक्य रचना संक्षिप्त है लेकिन सूक्ष्म हो सकता है; निर्भरता सही हो रही है प्राथमिक कौशल एक C डेवलपर की जरूरत है।

समझ निर्भरता

एक सी परियोजना में निर्भरता ] फ़ाइलों तक सीमित नहीं है। प्रत्येक स्रोत फ़ाइल में एक या अधिक हेडर फाइलें (जैसे, शामिल हैं। यदि कोई हेडर संशोधित है, तो सभी फ़ाइलें जिसमें शामिल हैं, इसे पुनः संकलित किया जाना चाहिए। इसी तरह, ऑब्जेक्ट फाइलें उनके अनुरूप फ़ाइलों पर निर्भर करती हैं, और अंतिम निष्पादन योग्य सभी ऑब्जेक्ट फ़ाइलों पर निर्भर करती हैं।

स्पष्ट बनाम दोष निर्भरता

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

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

एक मेकफ़ाइल की बुनियादी संरचना

एक ठेठ मेकफ़ाइल में चर परिभाषाएं, नियम और phony लक्ष्य शामिल हैं। यहाँ एक परियोजना के लिए एक न्यूनतम लेकिन कार्यात्मक उदाहरण है, जिसमें और :

CC = gcc
CFLAGS = -Wall -Wextra -O2

main: main.o utils.o
 $(CC) $(CFLAGS) -o main main.o utils.o

main.o: main.c
 $(CC) $(CFLAGS) -c main.c

utils.o: utils.c
 $(CC) $(CFLAGS) -c utils.c

clean:
 rm -f main main.o utils.o

इस मेकफ़ाइल में चार लक्ष्य हैं: (निष्पादकीय), दो ऑब्जेक्ट फाइलें, और एक phony लक्ष्य ]. The निर्भरता लाइनों के बाद कॉलोन बता make जो फ़ाइलों को देखने के लिए पहले लक्ष्य का पुनर्निर्माण करने के लिए.

Phony Targets

जैसे लक्ष्य, ]]]]Make] को फ़ाइल नामों से भ्रमित करने से रोकने के लिए, उन्हें ]phony]] के रूप में घोषित किया जाना चाहिए:

.PHONY: clean all

इसके बिना, अगर एक फ़ाइल अस्तित्व में है, make] इसे अद्यतन करने के लिए और नुस्खा छोड़ देंगे।

प्रभावी ढंग से निर्भरता का प्रबंधन करना

ऊपर मैनुअल मेकफ़ाइल में एक गंभीर दोष है: पर की निर्भरता सही है, लेकिन हेडर के बारे में क्या? यदि में परिवर्तन, (जिसमें शामिल हैं) को फिर से बनाया जाना चाहिए, फिर भी नियम यह केवल ]] पर निर्भर करता है। यह तय है कि कम्पाइलर वास्तविक निर्भरता सूची का उत्पादन करने की अनुमति है।

जीसीसी के साथ स्वचालित निर्भरता जनरेशन

GCC (और Clang) ]]]] झंडे के परिवार का उपयोग करके निर्भरता की जानकारी उत्पन्न कर सकता है। अधिकांश परियोजनाओं के लिए सबसे व्यावहारिक संयोजन है :

  • ] ]] - संकलन के दौरान एक निर्भरता फ़ाइल ([FLT: 21]]) लिखती है, केवल उपयोगकर्ता परिभाषित हेडर (सिस्टम हेडर नहीं) की सूची।
  • ]]]]]]]]]]]] - निर्भरता फ़ाइल के नाम को निर्दिष्ट करता है।
  • ]]]]]]]]]]]]]] - प्रत्येक शीर्षलेख के लिए फोनी लक्ष्य जोड़ती है, जब एक शीर्षलेख हटा दिया जाता है तो त्रुटियों को रोकने।

यहां एक मेकफ़ाइल में स्वचालित निर्भरता ट्रैकिंग को कैसे शामिल किया गया है:

CC = gcc
CFLAGS = -Wall -Wextra -O2 -MMD -MP
SRCDIR = src
OBJDIR = obj
SRCS = $(wildcard $(SRCDIR)/*.c)
OBJS = $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SRCS))
DEPS = $(OBJS:.o=.d)

all: myprogram

myprogram: $(OBJS)
 $(CC) $(CFLAGS) -o $@ $^

$(OBJDIR)/%.o: $(SRCDIR)/%.c
 @mkdir -p $(OBJDIR)
 $(CC) $(CFLAGS) -c $< -o $@

-include $(DEPS)

.PHONY: all clean
clean:
 rm -rf $(OBJDIR) myprogram

स्पष्टीकरण:

  • ]] सभी ]] को स्रोत निर्देशिका में फाइलें एकत्र करती हैं।
  • ] उन्हें ऑब्जेक्ट फ़ाइल पथ में बदल देता है।
  • ]]]: [[FLT::::::]]] [[FLT:::::]]]] [[FLT::]]]]]: निर्भरता फ़ाइलें सूची (जैसे: [[FLT::::]]]]]] [[FLT::]]]]]]]]] [[FLT:]]]]]]]]]]] [[FLT:]]]]]]]]]]]]]] [[FLT:[FLT:]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] [[[[[[[[[[[[[[[[[[[[[[[[FLT:[[[[FLT:]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
  • पैटर्न नियम ]] प्रत्येक फ़ाइल को संकलित करता है और ]] के कारण, एक फ़ाइल को एक साइड इफेक्ट के रूप में उत्पन्न करता है।
  • लाइन ] ने उत्पन्न फ़ाइलों को पढ़ा, उन्हें वास्तविक मेकफ़ाइल पूर्वावश्यकताओं में बदल दिया। डैश (]) त्रुटियों को दबा देता है जब फ़ाइलें अभी तक मौजूद नहीं हैं (उदाहरण के लिए, पहले निर्माण पर).

अब, अगर को संशोधित किया गया है, तो [[FLT::39]] का अगला चालान स्वचालित रूप से ] होगा क्योंकि ]]] ]]]] के लिए फ़ाइल [[FLT: 4]]]]] में एक पूर्वावश्यकता के रूप में [FLT: 43]]]]]] शामिल हैं।

उन्नत तकनीक

सुरक्षित रूप से उत्पन्न निर्भरता को संभालने

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

स्रोत परिवर्तन के बाद निर्भरता फ़ाइलें शामिल करना

एक सूक्ष्मता: यदि एक स्रोत फ़ाइल एक को जोड़ती है या हटाती है, तो संबंधित फ़ाइल को फिर से उत्पन्न किया जाना चाहिए। क्योंकि फ़ाइल खुद को ऑब्जेक्ट फ़ाइल की एक पूर्वावश्यकता है, make] बदली हुई समय-स्थिप्त और पुनः संक्रामक नोटिस करेगा, जो फ़ाइल को फिर से उत्पन्न करता है। यह पुनरावृत्ति पहले निर्माण पूरा होने के बाद स्वचालित रूप से काम करती है।

केवल आदेश-केवल आवश्यकता का उपयोग करना

कभी-कभी आपको इमारत से पहले मौजूद होने की जरूरत होती है, लेकिन आप इसके पुनर्निर्माण को ट्रिगर करने के लिए अपने समय-समय पर नहीं चाहते हैं। यह आदेश की भूमिका है - केवल शर्त (]]]] द्वारा अलग किया गया है। ऊपर दिए गए पैटर्न नियम में, हम [[FLT: 51]] का इस्तेमाल करते थे, जो नुस्खा के अंदर है; एक विकल्प है:

$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
 $(CC) $(CFLAGS) -c $< -o $@

$(OBJDIR):
 mkdir -p $@

यह सुनिश्चित करता है कि निर्देशिका किसी भी संकलन से पहले बनाई गई है, लेकिन निर्देशिका में एक बदलाव (जैसे, एक नई फ़ाइल अंदर) पुनर्संयोजन को ट्रिगर नहीं करेगी।

प्रबंधन निर्भरता के लिए सर्वश्रेष्ठ अभ्यास

  1. ]]दिन एक से स्वचालित निर्भरता पीढ़ी का उपयोग करें। यहां तक कि एक एकल फ़ाइल परियोजना के लिए भी, यह एक अच्छी आदत है। यह कुछ भी नहीं है और भविष्य की गलतियों को रोकता है।
  2. ]]] ]] ] निर्देशिका में उन्हें डालो। यह सफाई को आसान बनाता है और स्रोत पेड़ को clutter करने से रोकता है।
  3. ]]]]]]]]] निर्देश ठीक है, लेकिन इसे पैटर्न नियम के बाद रखने के लिए यह सुनिश्चित करता है कि ]make]]]]] पहले जानता है कि फ़ाइलों को पढ़ने की कोशिश करने से पहले ऑब्जेक्ट फ़ाइलों का निर्माण कैसे किया जाए।
  4. ]]घर के लिए फोनी लक्ष्य का उपयोग करें ], ], ]], और ]]]]] आम हैं। हमेशा उन्हें ]] के साथ घोषित किया।
  5. ]]कंपाइलर झंडे, स्रोत निर्देशिकाओं और फ़ाइलों की सूची के लिए विलंब परिवर्तनीय। यह मेकफ़ाइल को परियोजनाओं के पार पुन: प्रयोज्य बनाता है और अनुकूलित करने में आसान बनाता है।
  6. ]एक जानबूझकर हेडर परिवर्तन के साथ अपनी Makefile का परीक्षण करें। एक हेडर को संशोधित करें, ] चलाएँ, और केवल प्रभावित ऑब्जेक्ट फ़ाइलों की पुष्टि की जाए। यदि कोई पूर्ण पुनर्निर्माण होता है, तो निर्भरता ट्रैकिंग के साथ कुछ गलत है।
  7. ]]Keep the Makefile सरल लेकिन आवश्यक से सरल नहीं है। ]] जैसे उन्नत कार्यों के साथ ओवर-इंजीनियरिंग दर्दनाक बना सकते हैं। इस लेख में दिखाए गए पैटर्न के साथ शुरू करें; यह दर्जनों फाइलों के लिए अच्छी तरह से स्केल करता है।

बाह्य संसाधन

अपनी समझ को गहरा करने के लिए, इन आधिकारिक संदर्भों से परामर्श करें:

निष्कर्ष

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