Neden Lex -t scanner.l çalışmasına karar veriyor
ve çıkış benim kod overwritting etkili bir scanner.c için? Bu sizin inşa dizinde var durumla
bir scanner.c
ve scanner.c
Eğer make scanner
çalıştırın tarifi daha daha yeni bir scanner.l
:
scanner: scanner.h scanner.c lex.yy.c
cc lex.yy.c scanner.c -o scanner
gerektirir Önkoşul scanner.c
güncel olacaktır. , bunu yapan hiçbir reçete hazırlamamıştır, bu yüzden yerleşik reçeteler veritabanında geri çekilir.
make -p
çalıştırarak bu yerleşik tarifleri inceleyin ve şunları bulacaksınız:
%.c: %.l
# recipe to execute (built-in):
@$(RM) [email protected]
$(LEX.l) $< > [email protected]
Bu yerleşik tarifi çalıştırarak eşleşen file.l
bir file.c
yapacaktır:
rm file.c # Not echoed
lex -t file.l > file.c
Yap desen sonucuna varmıştır Bu tarifi için kural - %.c: %.l
- scanner.c
tarafından memnun, scanner.l
var ve daha güncel olan scanner.c
.
lex -t scanner.l > scanner.c
böylece
scanner.c
clobbering: Yani
scanner.c
UPTODATE yapmak için bu tarifi kullanır.
bu yerleşik tarifi uygulamak hiç yapmak istemiyorsanız
, açıkça sadece kural yazarak iptal edebilirsiniz:
%.c: %.l
makefile herhangi tarifi olmadan.
Ayrıca yapmak komut satırında --no-builtin-rules
geçirerek tüm yerleşik tarifleri devre dışı bırakabilir. Bir makefile davranışı hakkında beklentileriniz yerleşik tarifleri tarafından sabote verildiğinde
Ancak, bu beklentileriniz giriş dosyaları çıktı dosyalarını yapma zamanki gibi yanı bilgili değildir kuvvetli göstergesidir Makefile'nin çağırdığı araçlarla. Yap en Catalogue of Built-In Rules: Eğer sizin makefiles bu tarifi kendiniz yazmaya devam etmek zorunda kalmamak için
%.<target-type>: %.<prereq-type>
<command>
...
, marka ile
<prereq-type>
dosyadan
<target-type>
dosyası yapma
kurallı yolu somutlaştırmak. onlar yol yapmak bunu biliyorum çünkü GNU yetkili örnek C ve C++ programcıları için otomatik normalde, köşe durumlar dışında,
.c
dosyaları veya
.cpp
dosyalarından
.o
dosyaları yapmak tarifleri yazmıyorum yapmak istedikleri şekilde.
%.c: %.l
kural için
yapmak en yerleşik tarifi bir file.l
verilen file.c
yapma kanonik yolu ifade eder. Eğer değilscanner.c
scanner.l
gelen böyle yapılmasını istiyoruz değilse ve için lex.yy.c
scanner.l
yapılabilir istemek yerine, eğer sen olmak scanner.l
çağrıda dosya için gerekli veya yararlıdır: Yani kendinize sorun Ayrıca, scanner.c
denen oldukça bağımsız bir kaynak dosya olduğunda, buna denir?
bu oyuncak örnekte olduğu gibi make 'yerleşik tarifleri yararlandı varsayalım: 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;
}
tarayıcı.yapmak tüm bu komutları çalıştırır
$ 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
Not: gibi çalışır
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
:
#ifndef SCANNER_H
#define SCANNER_H
extern int yylex(void);
#endif
saat Sonra makefile sadece olabilir
cc -c -o scanner.o scanner.c
lex -t lexer.l > lexer.c
cc -c -o lexer.o lexer.c
Eğer nasıl bunu söylemek herhangi tarifleri yazılı kalmadan lexer.c
, lexer.o
ve scanner.o
yapmak. Sadece lexer.l
lexer.o
noktasından hedefine bulunması gerekir bir oluşturulan dosyası - - Ayrıca otomatik lexer.c
bir ara dosya olduğunu fark yüzden sonunda siler: söylenmişti olmadan
rm lexer.c
.
Ve bu tarayıcı gibi çalışır: Eh
$ ./scanner
hello
Found a string: [hello]
42
Found an integer: [42]
42.42
Found a floating-point number: [42.42]
^C