本文主要介紹了使用tcc編譯器編譯lua解釋器源碼。
1 介紹
lua是一門編程語言,開源且源碼很容易編譯,我平時用來測試C語言編程環境時經常使用。一般能編譯成功就說明編程環境設置正常。下面用之前設置好的tcc編程環境進行測試。
2 獲取源碼
我一般有保留多個版本的lua源碼進行測試,你可以去官網進行下載.
官網地址
https://www.lua.org/home.html
下載頁面
https://www.lua.org/download.html
最新版本即可,現在最新版為Lua 5.4.7,直接下載地址為
https://www.lua.org/ftp/lua-5.4.7.tar.gz
下載下來的文件保存到任意文件夾,我保存在C:\run\test,解壓得到lua-5.4.7文件夾,文件如下
其中src就是源碼文件夾。
3 初次編譯
將前文配置好的tcc編程環境.bat復制到C:\run\test\lua-5.4.7\src下,直接打開。輸入下面批處理指令
::編譯所有c文件并生成可執行文件
tcc *.c
::可執行文件名稱為lapi.exe
編譯會失敗,顯示luac.c: error: ‘main’ defined twice,因為luac.c是一個lua編譯器源碼,里面也有一個main函數,luac.c文件暫時不用到,可以直接刪除,或者想剪切到其他文件夾保留。
刪除或移動后,重新執行上面命令,沒有提示錯誤信息即編譯成功,一般編譯速度很快。文件夾下面會生成lapi.exe文件,點擊打開
即說明編譯成功,你可以輸入一些lua代碼測試一下效果。
print("你好,世界")
4 編譯測試
上面編譯指令為最簡單的編譯指令,使用很簡單,但是有一個問題,輸出文件為lapi.exe文件而不是lua.exe,因為沒有指定輸出程序名稱,可以使用-o文件進行指定輸出文件名稱。
::編譯所有c文件并生成可執行文件,
::-o選項指定輸出文件為lua.exe
tcc *.c -o lua.exe
上面編譯命令雖然簡單,但是隱藏了很多細節,下面進一步分析。
lua.c為解釋器源碼,如果直接編譯lua.c文件則會出錯,出錯信息如下
tcc lua.c -o lua.exe
因為編譯這個解釋器需要鏈接到其他代碼的信息。即所有c代碼均要指出,如
::編譯所有c代碼,輸出程序為lua.exe
::等價于tcc *.c -o lua.exe
tcc lapi.c lauxlib.c lbaselib.c lcode.c lcorolib.c lctype.c ldblib.c ldebug.c ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c ltm.c lua.c lundump.c lutf8lib.c lvm.c lzio.c -o lua.exe
正常c語言程序包含編譯和鏈接兩個步驟,使用tcc編譯和鏈接如下:
::編譯所有c文件并生成obj文件,
::-c選項指定只編譯不進行鏈接
tcc -c *.c
::將所有obj文件鏈接為可執行文件,-o選項指定輸出文件為lua.exe
tcc *.o -o lua.exe
除了一次性編譯所有c代碼文件,還可以逐個編譯c代碼文件,再進行鏈接。
::逐個編譯所有c文件并生成obj文件,
::-c選項指定只編譯不進行鏈接
tcc -c lapi.c
tcc -c lauxlib.c
tcc -c lbaselib.c
tcc -c lcode.c
tcc -c lcorolib.c
tcc -c lctype.c
tcc -c ldblib.c
tcc -c ldebug.c
tcc -c ldo.c
tcc -c ldump.c
tcc -c lfunc.c
tcc -c lgc.c
tcc -c linit.c
tcc -c liolib.c
tcc -c llex.c
tcc -c lmathlib.c
tcc -c lmem.c
tcc -c loadlib.c
tcc -c lobject.c
tcc -c lopcodes.c
tcc -c loslib.c
tcc -c lparser.c
tcc -c lstate.c
tcc -c lstring.c
tcc -c lstrlib.c
tcc -c ltable.c
tcc -c ltablib.c
tcc -c ltm.c
tcc -c lua.c
tcc -c lundump.c
tcc -c lutf8lib.c
tcc -c lvm.c
tcc -c lzio.c
::將所有obj文件鏈接為可執行文件,-o選項指定輸出文件為lua.exe
tcc *.o -o lua.exe
這樣寫的好處是當你修改某個c代碼文件時可以,直接重新編譯這個文件而其他未修改文件可以不編譯,提高編譯效率。
::若我們只修改了lua.c文件,不需編譯其他文件,只需編譯lua.c文件
tcc -c lua.c
::將所有obj文件鏈接為可執行文件,-o選項指定輸出文件為lua.exe
tcc *.o -o lua.exe
此外還c語言開發中有兩種特殊的編譯方法,一個是生成靜態鏈接庫,如下
::編譯除lua.c外所有c代碼文件,生成靜態鏈接庫liblua.a
::-r代表重定向
tcc -r lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lcorolib.c ldblib.c liolib.c lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c lutf8lib.c -o liblua.a::生成文件靜態鏈接庫liblua.a,
::編譯生成lua(靜態鏈接庫版本).exe,需用到liblua.a文件
tcc liblua.a lua.c -o lua(靜態鏈接庫版本).exe
還有一種是生成動態鏈接庫版本
::編譯除lua.c外所有c代碼文件,生成動態鏈接庫lua.dll
tcc -shared -rdynamic lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lcorolib.c ldblib.c liolib.c lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c lutf8lib.c -o lua.dll
::生成文件動態鏈接庫lua.dll,以及導出函數表lua.def文件
::編譯生成lua(動態鏈接庫版本).exe,需用到lua.def文件
tcc lua.def lua.c -o lua(動態鏈接庫版本).exe
5 小結
使用tcc來編譯lua源代碼還是比較簡單的,一方面是tcc編譯器使用比較簡單容易上手,另一方面是lua源代碼也比較簡單沒有其他第三方庫依賴,而且所有源碼位于同一文件夾方便編譯。