Flex程序编译
Makefile三要素:
目標(biāo)、依賴、命令
詳解可見makefile 編寫_周北-CSDN博客_makefile 編寫
Makefile中常用函數(shù)和自動化變量:
wildcard-擴展通配符
例:OBJECTS=$(wildcard *.o)
該找到目標(biāo)文件下的所有后綴為.c的文件名并將它們?nèi)假x給OBJECT(即,OBJECT是.o文件的集合,并且這個函數(shù)中的OBJECTS是個任意命名的變量,但是$(wildcard .o)是這個實現(xiàn)找出.o文件的Makefile函數(shù)),要注意的是在wildcard和.o之間是是通過空格隔開的)。
patsubst-替換通配符
obj=$(patsubst %, $(LIBPATH)/%/$(LIB_TYPE), $(LINKDIRS))
該函數(shù)的功能是在LINKDIRS(第三個參數(shù)的集合)中取出各個單元(庫所在目錄名), 將所有包含第一個參數(shù)的部分替換成第二個參數(shù)的部分。要注意的是在這個函數(shù)中patsubst 和%之間是沒有逗號將它們兩個隔開的,它們兩個之間只有空格,%, $(LIBPATH)/%/$(LIB_TYPE), $(LINKDIRS)之間則使用逗號隔開。
foreach-循環(huán)函數(shù)
也可使用類似于Shell的for循環(huán)語句:
for name in $(FILES); do \ ?echo "$$name"; \ ?
done ?
注意, 在makefile中的shell變量要用2個$號表示變量名稱
其他函數(shù)可參見makefile中常用函數(shù)_.-CSDN博客_makefile常用函數(shù)
Makefile三個自動化變量:
$@?? ?規(guī)則中的目標(biāo)集合,在模式規(guī)則中,如果有多個重復(fù)目標(biāo)的話,“$@” 表示匹配模式中定義的目標(biāo)集合
$%?? ?當(dāng)目標(biāo)是函數(shù)庫的時候表示規(guī)則中的目標(biāo)成員名,如果目標(biāo)不是函數(shù)庫文件,那么其值為空
$<?? ?依賴文件集合中的第一個文件,如果依賴文件是以模式(即“%”)定義的,那么“$<” 就是符合模式的一系列的文件集合,多次調(diào)用則向后順移讀取
$??? ?所有比目標(biāo)新的依賴目標(biāo)集合,以空格分開
$^?? ?所有依賴文件的集合,使用空格分開,如果在依賴文件中有多個文件“$^” 會去除重復(fù)的依賴文件,值保留一份
$+?? ?和“$^”類似,但是當(dāng)依賴文件存在重復(fù)的話不會去除重復(fù)的依賴文件
$*?? ?這個變量表示目標(biāo)模式中"%"及其之前的部分,如果目標(biāo)是式為a.%.c,那么“$*”就是test/a.test
makefile允許命令行傳參,通常用于指定宏編譯
實例解析可見一點一點學(xué)寫Makefile(4) - 編譯時指定宏參數(shù)_qq849635649的博客-CSDN博客_make 指定宏
makefile可以使用自動化構(gòu)建工具CMake生成
Makefile中常見預(yù)定義變量
AR ?庫文件維護程序的名稱,默認值為ar,創(chuàng)建靜態(tài)庫.a
AS ?匯編程序的名稱,默認值為as
CC ?C編譯器的名稱,默認值為cc
CPP C預(yù)編譯器的名稱,默認值為$(CC) –E
CXX C++編譯器的名稱,默認值為g++
FC ?FORTRAN編譯器的名稱,默認值為f77
RM ?文件刪除程序的名稱,默認值為rm –f
ARFLAGS 庫文件維護程序的選項,無默認值
ASFLAGS 匯編程序的選項,無默認值
CFLAGS ?C編譯器的選項,無默認值
CPPFLAGS C預(yù)編譯的選項,無默認值
CXXFLAGS C++編譯器的選項,無默認值
FFLAGS ? FORTRAN編譯器的選項,無默認值
GCC編譯選項CFLAGS參數(shù)
-c?? ?用于把源碼文件編譯成.o對象文件,不進行鏈接過程
-o?? ?用于連接生成可執(zhí)行文件,在其后可以指定輸出文件的名稱
-g?? ?用于在生成的目標(biāo)可執(zhí)行文件中,添加調(diào)試信息,可以使用GDB進行調(diào)試
-Idir?? ?用于把新目錄添加到include路徑上,可以使用相對和絕對路徑,“-I.”、“-I./include”、“-I/opt/include”
-Wall?? ?生成常見的所有告警信息,且停止編譯,具體是哪些告警信息,請參見CC手冊,一般用這個足矣!
-w?? ?關(guān)閉所有告警信息
-O?? ?表示編譯優(yōu)化選項,其后可跟優(yōu)化等級0\1\2\3,默認是0,不優(yōu)化
-fPIC?? ?用于生成位置無關(guān)的代碼
-v?? ?(在標(biāo)準(zhǔn)錯誤)顯示執(zhí)行編譯階段的命令,同時顯示編譯器驅(qū)動程序,預(yù)處理器,編譯器的版本號
GCC鏈接選項LDFLAGS參數(shù)
-llibrary?? ?鏈接時在標(biāo)準(zhǔn)搜索目錄中尋找?guī)煳募?#xff0c;搜索名為liblibrary.a 或 liblibrary.so
-Ldir?? ?用于把新目錄添加到庫搜索路徑上,可以使用相對和絕對路徑,“-L.”、“-L./include”、“-L/opt/include”
-Wl,option?? ?把選項 option 傳遞給連接器,如果 option 中含有逗號,就在逗號處分割成多個選項
-static?? ?使用靜態(tài)庫鏈接生成目標(biāo)文件,避免使用共享庫,生成目標(biāo)文件會比使用動態(tài)鏈接庫大
另外,LDFLAGS告訴鏈接器從哪里尋找?guī)煳募?#xff0c;LIBS告訴鏈接器要鏈接哪些庫文件。
接下來利用一個簡單地實例進行說明,安裝Flex編譯一個文本識別的小demo。Flex的源程序(定義詞法解析處理規(guī)則)需要經(jīng)過Flex工具形成完成的詞法解析程序,最后和Main程序鏈接到一起。
編寫testMain.c
#include <stdio.h>extern int yylex();extern int chars;
extern int words;
extern int lines;void main(int argc, char **argv)
{yylex();printf("line: %d, word: %d, char: %d\n", lines, words, chars);
}
編寫testFlex.l
%{int chars = 0;int words = 0;int lines = 0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
\n ? ? ? ?{ chars++; lines++; }
. ? ? ? ? { chars++; }
%%
根據(jù)編譯過程,編寫一個直觀的Makefile
ECHO = echo ? ? ? #將編譯器選項定義為變量,提高makefile文件的可移植性 ? ? ? ? ??
CC ? = gcc?
FLEX = flextarget: start testDemo ? ? ? ? ? ?#make命令默認執(zhí)行第一個target及其依賴項@$(ECHO) compiling is finished!
start:@$(ECHO) compiling......
testDemo: testMain.o testFlex.o$(CC) -o testDemo testMain.o testFlex.o -lfl -Wall
testMian.o: testMain.c$(CC) -c testMian.c
testFlex.o: testFlex.c$(CC) -c testFlex.c?
testFlex.c: testFlex.l$(FLEX) -o testFlex.c testFlex.l?
clean: ? ? ? ? ? ? ? #make clean執(zhí)行非第一個target子程序的clean target@$(ECHO) cleaning......rm testFlex.c ./*.o testDemo
根據(jù)編譯過程,編寫一個使用自動化變量的Makefile
ECHO = echo ? ? ? #將編譯器選項定義為變量,提高makefile文件的可移植性 ? ? ? ? ??
CC ? = gcc?
FLEX = flexOBJECTS = testMain.o
OBJECTS += testFlex.oTARGET = ./testDemo
CFLAGS = -Wall
LIBS ? = -lflTARGET: $(OBJECTS) ?#make命令默認執(zhí)行第一個target及其依賴項$(CC) -o $(TARGET) $(OBJECTS) $(LIBS) $(CFLAGS)@$(ECHO) compiling is finished!#.c.o : ? 一種舊格式寫法
%.o : %.c$(CC) -o $@ -c $<#.l.c :
%.c : %.l$(FLEX) -o $@ $<clean: ? ? ? ? ? ? ? #make clean執(zhí)行非第一個target子程序的clean target@$(ECHO) cleaning......rm $(OBJECTS) $(TARGET) -f.PHONY : clean
在clean目標(biāo)中需要配合使用偽目標(biāo)聲明,這個偽目標(biāo)聲明是指當(dāng)當(dāng)前路徑下含有以clean命令的文件或者是目錄的時候,則在使用命令make clean的時候,就會導(dǎo)致結(jié)果無法執(zhí)行。
解決這種問題,只需要在makefile中加入一個偽目標(biāo)聲明即可,格式為 .PHONY.clean。
具體說明可見makefile中的all和.PHONY的作用-andyhzw-ChinaUnix博客
另外,關(guān)于Makefile特殊目標(biāo)的詳細說明可見Makefile的特殊目標(biāo) | 學(xué)步園
總結(jié)
- 上一篇: 铝合金窗多少钱一平方啊?
- 下一篇: 我的灰姑娘是哪首歌啊?