2009年2月27日 星期五

Setup Lex and Yacc From Unix to Linux

首先,先替王立天老師的編譯器課程終於開課了高興一下,也讓老師搬出了多年前回台灣就封起來的紙箱從見天日啦。給我們以前在外國的學生所交的作業,並要我們先把讓這些程式可以執行。大致跟老師討論一下程式的內容,花了點時間研究一下,也成功的執行。大概的整理了一下,以 Eishi 同學所繳交的 asgn1 為例,筆記如下:

Step 1. Makefile

Step 1-1. Introduction
因為程式是經由 make 來編譯的,所以先了解一下 Makefile 是做什麼的。可以到 跟我一起寫 Makefile 這裡來了解一下。只需閱讀 概述 MakeFile 介紹 即可。

Step1-2. Error : No targets specified and no makefile found. Stop.
打開 asgn1 可以發現裡有 LEX.l , GRAM.y 和 MAKEFILE。直接給他執行 make,會得到
make: *** No targets specified and no makefile found. Stop.
這樣的錯誤,根據 Appendix B Errors Generated by Make 的說明是找不到 makefile。我記得 Linux 中的 make 的檔名應該只有 Makefile 和 makefile,所以重新命名就解決了。
mv MAKEFILE makefile


Step 1-3. Error : *** missing separator. Stop.
重新命名後,執行 make ,卻發生錯誤
makefile:1:*** missing separator. Stop.
那個 1 應該是代表行數,第一行就發生錯誤...。打開 Makefile,第一行和第二行是 /* ... */ 的註解,但是可以看到下面是以有亮顯 # 的符號來當做註解。第一直覺就是 /* ... */ 不是 Makefile 的註解,刪掉。

Step 1-4. Error : makefile:2: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.
再度 make ,出現的錯誤是
makefile:2: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.
Orz...看了一下錯誤說明,了解 Makefile 裡面的分隔字元都必須很清楚的定義而且都有固定的格式。打開 Makefile ,箭頭直接瞄準 command 區塊,把左邊的空白字元清掉,以 Tab 代替,亮顯就出現了!以此類推,下面的也改一改。 clean 左邊有一個空白字元也刪掉。

Step 1-5. Error : make: *** No rule to make target `y_tab.obj', needed by `asgn1.exe'. Stop.
看來是因為要產生 asgn1.exe 而找不到 y_tab.obj,打開 makefile,把最下面的 rule

y_tab_obj : y_tab.c lexyy.c
tcc -c -w- y_tab.c

改成

y_tab.obj : y_tab.c lexyy.c
tcc -c -w- y_tab.c

Step 1-6. Error : make: *** No rule to make target `gram.y', needed by `y_tab.c'. Stop.
這訊息是說找不到指定的 gram.y,老師有跟我說 UNIX 是不分大小寫的,但是 Linux 有分。所以把 GRAM.y 和 LEX.l 分別改成 gram.y 和 lex.l 就解決了兩個問題了。

Step 1-7. Error : lex.l:36: unrecognized rule
發生這錯誤,明顯的就是 lex 的程式有問題,打開 lex.l ,找到 36 行。區塊唯一沒亮顯就是他...看了一下,給他一個空格來區隔 match 和 function 就可以了。

Step 2. Start Make
Step 2-1. Error : make: tcc: Command not found
再 make lex.l 時,可能產生了一些 warning ,但我想應該不影響,所以先不理他。看看這個錯誤訊息,找不到 tcc 這個指令。查了一下,tcc 是 Tiny C Compiler 。Linux 下都用 gcc ,所以把 tcc 的部份修改成 gcc ,並對照一下 option 修改所需要的參數。如下:

gcc -c file_name


Step 2-2. Error : gcc: y_tab.c: No such file or directory
很明顯的是因為 gcc 找不到要 compile 的檔案,看了一下,資料夾卻有 y.tab.c。這邊可以知道 Yacc 所產生的檔案應為 y.tab.c ,而不是 y_tab.c,修改

y_tab.obj : y_tab.c lexyy.c
gcc -c y_tab.c



y_tab.obj : y_tab.c lexyy.c
gcc -c y.tab.c

*注意:這邊 make 裡面用的是 bycc ,實為 Berkeley Yacc 若無安裝,改成 yacc 即可。

Step 2-3. Error : gram.y:89:20: error: lexyy.c: No such file or directory
嗯...找不到 lexyy.c,快瘋了喔!看了資料夾,裡面有 lex.yy.c,所以 Lex 所產生的檔案應為 lex.yy.c 而不是 lexyy.c。打開 gram.y ,尋找 lexyy.c 並修改即可。

Step 2-4. Error : gcc: y_tab.obj: No such file or directory
一樣,找不到該檔,打開 makefile :

asgn1.exe : y_tab.obj
gcc -c y.tab.o

修改成

asgn1.exe : y_tab.obj
gcc -o asgn1.exe y.tab.o

即可,gcc 的參數設定可自行執行 gcc --help 來了解

Step 2-5. Error : y.tab.c:(.text+0xb31): undefined reference to `yywrap'
Google 一下,這個錯誤可以透過加上

int yywrap()
{
return(1);
}

來解決。打開 gram.y 發現原本就有加了,只是備註解掉而已。

Step 3. Make Successed
Step 3-1. asgn1.exe
終於,make 沒有錯誤訊息了,並且產生了一個 asgn1.exe 的檔案。接下來可以自己玩一玩了,透過
./asgn1.exe

執行,然後輸入 +,/ 和 if,else,while,或是亂輸入也可以喔!

1 則留言:

scarf 提到...

you did the good job!!