यह lex -t scanner.l को चलाने का निर्णय क्यों लेता है और स्कैनर.c को आउटपुट को प्रभावी ढंग से मेरे कोड को ओवरराइट करने का निर्णय लेता है?
जब भी ऐसा होता है कि आप अपने निर्माण निर्देशिका में एक scanner.c
और एक scanner.l
कि अधिक नवीनतम scanner.c
जब आप चलाने make scanner
, नुस्खा से है:
scanner: scanner.h scanner.c lex.yy.c
cc lex.yy.c scanner.c -o scanner
कि आवश्यकता है इसकी पूर्व शर्त scanner.c
अपतटीय हो जाएगी। आप ने कोई नुस्खा नहीं दिया है जो ऐसा करता है, इसलिए बिल्टिन व्यंजनों के डेटाबेस पर वापस आते हैं।
make -p
चलाकर उन builtin व्यंजनों की जांच करना और आपको:
%.c: %.l
# recipe to execute (built-in):
@$(RM) [email protected]
$(LEX.l) $< > [email protected]
यह अंतर्निहित नुस्खा चलाकर मिलान file.l
से एक file.c
कर देगा:
rm file.c # Not echoed
lex -t file.l > file.c
मेक पाता पैटर्न है कि इस नुस्खा के लिए नियम - %.c: %.l
- scanner.c
से संतुष्ट है, क्योंकि scanner.l
मौजूद है और हाल ही मेंसे अधिक है। तो यह यह नुस्खा का उपयोग करता scanner.c
uptodate बनाने के लिए:
lex -t scanner.l > scanner.c
जिससे आपके scanner.c
clobbering।अपने makefile में किसी भी नुस्खा के बिना
%.c: %.l
:
आप इस builtin नुस्खा लागू करने के लिए कभी नहीं करना चाहते, तो आप स्पष्ट रूप से यह सिर्फ नियम लिख कर रद्द कर सकते हैं।
तुम भी मेकअप कमांडलाइन पर --no-builtin-rules
पास करके सभी builtin व्यंजनों निष्क्रिय कर सकते हैं।
हालांकि, जब भी एक makefile के व्यवहार के बारे अपनी उम्मीदों builtin व्यंजनों से नाकाम कर रहे हैं यह मजबूत संकेत है कि अपनी अपेक्षाओं नहीं इनपुट फ़ाइलें से उत्पादन फ़ाइलें बनाने का हमेशा की तरह के रूप में अच्छी तरह से वाकिफ रहे हैं आपके मेकफ़ाइल का उपयोग करने वाले टूल के साथ। मेक के Catalogue of Built-In Rules:
%.<target-type>: %.<prereq-type>
<command>
...
मेकअप के साथ एक <prereq-type>
फ़ाइल से एक <target-type>
फ़ाइल बनाने का विहित रास्ता प्रतीक है, ताकि आप अपने makefiles में यह नुस्खा खुद के लेखन रखने के लिए नहीं है। उदाहरण C और C++ प्रोग्रामर जो जीएनयू के साथ सक्षम हैं बनाने .c
फाइल या .cpp
फाइलों से .o
फ़ाइलें बनाने के लिए, कोने मामलों को छोड़कर व्यंजनों बारे में नहीं है, क्योंकि वे जानते हैं कि इस तरह से बना यह करना होगा स्वचालित रूप से सामान्य रूप से है जिस तरह से वे चाहते हैं। %.c: %.l
शासन के लिए
मेक के builtin नुस्खा बनाने file.c
एक file.l
दिया के विहित रास्ता व्यक्त करता है। तो अपने आप से पूछना: आप नहीं चाहते scanner.c
scanner.l
से ऐसा किए जाने के लिए करते हैं, और अगर आप चाहते हैं बजाय lex.yy.c
को scanner.l
से बनाया जा, यह आवश्यक या फ़ाइल आप scanner.l
कहा जाता है होना करने के लिए के लिए उपयोगी है कहा जाता है कि, जब आपके पास एक बहुत ही स्वतंत्र स्रोत फ़ाइल है जिसे scanner.c
कहा जाता है?
मान लीजिए आप इस खिलौने उदाहरण के रूप में कर के builtin व्यंजनों का फायदा उठाया:
lexer.l
%{
#include <stdio.h>
%}
%%
[ \t] ;
[0-9]+\.[0-9]+ { printf("Found a floating-point number: [%s]\n",yytext); }
[0-9]+ { printf("Found an integer: [%s]\n",yytext); }
[a-zA-Z0-9]+ { printf("Found a string: [%s]\n",yytext); }
%%
scanner.c
#include "scanner.h"
int main(void) {
yylex();
return 0;
}
स्कैनर।ज
#ifndef SCANNER_H
#define SCANNER_H
extern int yylex(void);
#endif
फिर अपने makefile हो सकता है बस:
Makefile
SRCS := scanner.c lexer.c
OBJS := $(SRCS:.c=.o)
LDLIBS := -lfl
.PHONY: all clean
all: scanner
scanner: $(OBJS)
$(LINK.o) -o [email protected] $^ $(LDLIBS)
scanner.o: scanner.h
clean:
rm -f scanner *.o
जो की तरह चलाता है:
$ make
cc -c -o scanner.o scanner.c
lex -t lexer.l > lexer.c
cc -c -o lexer.o lexer.c
cc -o scanner scanner.o lexer.o -lfl
rm lexer.c
ध्यान दें कि बनाने के लिए इन सभी आदेशों चलाता है:
012,
cc -c -o scanner.o scanner.c
lex -t lexer.l > lexer.c
cc -c -o lexer.o lexer.c
आप किसी भी व्यंजनों है कि यह बताने के लिए ऐसा करने के लिए लिखा बिना lexer.c
, lexer.o
और scanner.o
बनाने के लिए। यह भी स्वचालित रूप से देखती है कि lexer.c
एक मध्यवर्ती फ़ाइल है - कि केवल lexer.l
lexer.o
करने से प्राप्त करने के लिए मौजूद करने की जरूरत है एक उत्पन्न फ़ाइल - तो यह यह अंत में हटाता है:
rm lexer.c
करने के लिए कहा जा रहा है बिना ।
और यह स्कैनर की तरह चलाता है: ठीक है
$ ./scanner
hello
Found a string: [hello]
42
Found an integer: [42]
42.42
Found a floating-point number: [42.42]
^C