Tiny CC 編譯器簡介 -- 安裝、使用與編譯

TinyCC 編譯器

簡介

MinGW 測試

整體架構

編譯器

組譯器

目的檔

連結器

整合測試

訊息

相關網站

參考文獻

最新修改

簡體版

English

TCC (TinyCC) 是一個超小型的 C 語言編譯器,其創作者是 Fabrice Bellard,你可以從 http://bellard.org/tcc/ 當中下載其最新版本。

筆者在此所使用的是 tcc-0.9.25 的版本,然後在 Windows XP 作業系統中使用 Dev C++ 所內附的 gcc 進行編譯,其過程與結果如下。

首先看看 TinyCC 專案的檔案與目錄結構。

C:\tcc>dir
 磁碟區 C 中的磁碟沒有標籤。
 磁碟區序號:  8C1F-9341

 C:\tcc 的目錄

2011/02/18  上午 09:42    <DIR>          .
2011/02/18  上午 09:42    <DIR>          ..
2009/05/18  下午 10:27               325 .cvsignore
2009/05/18  下午 10:27            38,681 arm-gen.c
2009/05/18  下午 10:27            70,941 c67-gen.c
2009/05/18  下午 10:27            14,462 Changelog
2009/05/18  下午 10:27            22,419 coff.h
2011/02/18  上午 09:42               109 config.h
2009/05/18  下午 10:27             9,276 configure
2009/05/18  下午 10:27            26,428 COPYING
2009/05/18  下午 10:27            78,631 elf.h
2011/02/18  上午 09:42    <DIR>          examples
2009/05/18  下午 10:27            36,588 i386-asm.c
2009/05/18  下午 10:27            21,281 i386-asm.h
2009/05/18  下午 10:27            29,033 i386-gen.c
2009/05/18  下午 10:27            16,721 il-gen.c
2009/05/18  下午 10:27             7,612 il-opcodes.h
2011/02/18  上午 09:42    <DIR>          include
2011/02/18  上午 09:42    <DIR>          lib
2009/05/18  下午 10:27            61,474 libtcc.c
2009/05/18  下午 10:27             3,490 libtcc.h
2009/05/18  下午 10:27             6,940 Makefile
2009/05/18  下午 10:27             2,650 README
2009/05/18  下午 10:27             9,131 stab.def
2009/05/18  下午 10:27               259 stab.h
2009/05/18  下午 10:27           107,357 tcc-doc.html
2009/05/18  下午 10:27            33,562 tcc-doc.texi
2009/05/18  下午 10:27            17,454 tcc.c
2009/05/18  下午 10:27            23,165 tcc.h
2009/05/18  下午 10:27            28,037 tccasm.c
2009/05/18  下午 10:27            22,693 tcccoff.c
2009/05/18  下午 10:27            90,590 tccelf.c
2009/05/18  下午 10:27           154,158 tccgen.c
2009/05/18  下午 10:27            47,290 tccpe.c
2009/05/18  下午 10:27            84,003 tccpp.c
2009/05/18  下午 10:27            11,439 tcctok.h
2011/02/18  上午 09:42    <DIR>          tests
2009/05/18  下午 10:27            11,030 texi2pod.pl
2009/05/18  下午 10:27             3,405 TODO
2009/05/18  下午 10:27                 6 VERSION
2011/02/18  上午 09:42    <DIR>          win32
2009/05/18  下午 10:27            40,738 x86_64-gen.c
              35 個檔案       1,131,378 位元組
               7 個目錄  29,695,655,936 位元組可用

您會發現一個 win32 的資料夾,這符合我們所用的 Windows XP 平台,進入看看。

C:\tcc>cd win32

C:\tcc\win32>dir
 磁碟區 C 中的磁碟沒有標籤。
 磁碟區序號:  8C1F-9341

 C:\tcc\win32 的目錄

2011/02/18  上午 09:42    <DIR>          .
2011/02/18  上午 09:42    <DIR>          ..
2009/05/18  下午 10:27               985 build-tcc.bat
2011/02/18  上午 09:42    <DIR>          examples
2011/02/18  上午 09:42    <DIR>          include
2011/02/18  上午 09:42    <DIR>          lib
2009/05/18  下午 10:27             3,934 tcc-win32.txt
2011/02/18  上午 09:42    <DIR>          tools
               2 個檔案           4,919 位元組
               6 個目錄  29,697,015,808 位元組可用

您會再其中發現一個 build-tcc.bat 的檔案,這是 Windows 的批次檔,讓我們執行看看。

C:\tcc\win32>build-tcc

C:\tcc\win32>gcc -Os -fno-strict-aliasing ../tcc.c -o tcc.exe -s

C:\tcc\win32>gcc -Os -fno-strict-aliasing ../libtcc.c -c -o libtcc.o

C:\tcc\win32>gcc -Os tools/tiny_impdef.c -o tiny_impdef.exe -s

C:\tcc\win32>gcc -Os tools/tiny_libmaker.c -o tiny_libmaker.exe -s

C:\tcc\win32>mkdir libtcc

C:\tcc\win32>ar rcs libtcc/libtcc.a libtcc.o

C:\tcc\win32>del libtcc.o

C:\tcc\win32>copy ..\libtcc.h libtcc
複製了         1 個檔案。

C:\tcc\win32>.\tcc -c lib/crt1.c

C:\tcc\win32>.\tcc -c lib/wincrt1.c

C:\tcc\win32>.\tcc -c lib/dllcrt1.c

C:\tcc\win32>.\tcc -c lib/dllmain.c

C:\tcc\win32>.\tcc -c lib/chkstk.S

C:\tcc\win32>.\tcc -c ../lib/libtcc1.c

C:\tcc\win32>.\tcc -c ../lib/alloca86.S

C:\tcc\win32>.\tcc -c ../lib/alloca86-bt.S

C:\tcc\win32>ar rcs lib/libtcc1.a crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
libtcc1.o alloca86.o alloca86-bt.o

C:\tcc\win32>del *.o

C:\tcc\win32>

賓果,我們已經建立好整個 tcc 專案了,其中 tcc 編譯器就是 tcc.exe 這個輸出檔了,讓我們用這個編譯器編譯幾個程式吧。

tcc 已經為我們準備好一些測試程式,位在 examples 這個資料夾中。但是萬事具備,只差還沒讓我們可以到處使用 tcc 這個指令。我們必須設定 PATH 路徑。請在「開始/控制台/系統/進階/環境變數」中,將 tcc.exe 所在的資料夾 (筆者的為 C:\tcc\win32) 設定到 PATH 變數當中。然後重新開啟一個命令列視窗。

example 資料夾中已經有 5 個 C 語言程式範例,讓我們一一測試看看。

範例一:ex1.c

#! /usr/local/bin/tcc -run
#include <tcclib.h>

int main()
{
    printf("Hello World\n");
    return 0;
}

編譯執行過程

C:\tcc\examples>tcc -I ../include ex1.c -o ex1.exe

C:\tcc\examples>ex1
Hello World

範例 2: ex2.c

#include <stdlib.h>
#include <stdio.h>

#define N 20

int nb_num;
int tab[N];
int stack_ptr;
int stack_op[N];
int stack_res[60];
int result;

int find(int n, int i1, int a, int b, int op)
{
    int i, j;
    int c;

    if (stack_ptr >= 0) {
        stack_res[3*stack_ptr] = a;
        stack_op[stack_ptr] = op;
        stack_res[3*stack_ptr+1] = b;
        stack_res[3*stack_ptr+2] = n;
        if (n == result)
            return 1;
        tab[i1] = n;
    }

    for(i=0;i<nb_num;i++) {
        for(j=i+1;j<nb_num;j++) {
            a = tab[i];
            b = tab[j];
            if (a != 0 && b != 0) {

                tab[j] = 0;
                stack_ptr++;

                if (find(a + b, i, a, b, '+'))
                    return 1;
                if (find(a - b, i, a, b, '-'))
                    return 1;
                if (find(b - a, i, b, a, '-'))
                    return 1;
                if (find(a * b, i, a, b, '*'))
                    return 1;
                if (b != 0) {
                    c = a / b;
                    if (find(c, i, a, b, '/'))
                        return 1;
                }

                if (a != 0) {
                    c = b / a;
                    if (find(c, i, b, a, '/'))
                        return 1;
                }

                stack_ptr--;
                tab[i] = a;
                tab[j] = b;
            }
        }
    }

    return 0;
}

int main(int argc, char **argv)
{
    int i, res, p;

    if (argc < 3) {
        printf("usage: %s: result numbers...\n"
               "Try to find result from numbers with 
                the 4 basic operations.\n", argv[0]);
        exit(1);
    }

    p = 1;
    result = atoi(argv[p]);
    printf("result=%d\n", result);
    nb_num = 0;
    for(i=p+1;i<argc;i++) {
        tab[nb_num++] = atoi(argv[i]);
    }

    stack_ptr = -1;
    res = find(0, 0, 0, 0, ' ');
    if (res) {
        for(i=0;i<=stack_ptr;i++) {
            printf("%d %c %d = %d\n",
                   stack_res[3*i], stack_op[i],
                   stack_res[3*i+1], stack_res[3*i+2]);
        }
        return 0;
    } else {
        printf("Impossible\n");
        return 1;
    }
}

這個範例 ex2.c 的功能我看不太懂,但顯然參數是一堆數字,讓我們試著執行看看。

C:\tcc\examples>tcc -I ../include ex2.c -o ex2.exe

C:\tcc\examples>ex2
usage: ex2: result numbers...
Try to find result from numbers with the 4 basic operations.

C:\tcc\examples>ex2 1 2
result=1
Impossible

C:\tcc\examples>ex2 1 2 3 4
result=1
2 + 3 = 5
5 - 4 = 1

C:\tcc\examples>ex2 1 2 3 4 5 6 7
result=1
2 + 3 = 5
5 + 4 = 9
9 + 5 = 14
14 - 6 = 8
8 - 7 = 1

看來是在找加減乘除的關係。

範例 3 : ex3.c

#include <stdlib.h>
#include <stdio.h>

int fib(n)
{
    if (n <= 2)
        return 1;
    else
        return fib(n-1) + fib(n-2);
}

int main(int argc, char **argv)
{
    int n;
    if (argc < 2) {
        printf("usage: fib n\n"
               "Compute nth Fibonacci number\n");
        return 1;
    }

    n = atoi(argv[1]);
    printf("fib(%d) = %d\n", n, fib(n, 2));
    return 0;
}

範例 3 顯然是用費氏序列問題在測試遞迴,其編譯執行結果如下。

C:\tcc\examples>tcc -I ../include ex3.c -o ex3.exe

C:\tcc\examples>ex3
usage: fib n
Compute nth Fibonacci number

C:\tcc\examples>ex3 5
fib(5) = 5

C:\tcc\examples>ex3 6
fib(6) = 8

C:\tcc\examples>ex3 10
fib(10) = 55

C:\tcc\examples>ex3 20
fib(20) = 6765

範例 4: ex4.c

#!./tcc -run -L/usr/X11R6/lib -lX11
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>

/* Yes, TCC can use X11 too ! */

int main(int argc, char **argv)
{
    Display *display;
    Screen *screen;

    display = XOpenDisplay("");
    if (!display) {
        fprintf(stderr, "Could not open X11 display\n");
        exit(1);
    }
    printf("X11 display opened.\n");
    screen = XScreenOfDisplay(display, 0);
    printf("width = %d\nheight = %d\ndepth = %d\n",
           screen->width,
           screen->height,
           screen->root_depth);
    XCloseDisplay(display);
    return 0;
}

由於第 4 個範例牽涉到 XWindow,筆者電腦沒有安裝,因此無法正確編譯,其錯誤結果如下。

C:\tcc\examples>tcc -I ../include ex4.c -o ex4.exe
ex4.c:4: include file 'X11/Xlib.h' not found

範例 5: ex5.c

第 5 個範例則牽涉到標準檔頭 stdio.h 與 stdlib.h,其程式碼如下。

#include <stdlib.h>
#include <stdio.h>

int main()
{
    printf("Hello World\n");
    return 0;
}

由於牽涉到標準執行檔的檔頭,但是 tcc 當中又沒有內附,筆者只好利用 Dev C++ 當中所具有的檔頭,將 C:\Dev-Cpp\include 引用進來,其編譯結果如下。

C:\tcc\examples>tcc -I ../include -I C:\Dev-Cpp\include ex5.c -o ex5.exe
In file included from ex5.c:1:
C:/Dev-Cpp/include/stdlib.h:97: declaration for parameter '__argc_dll' but no su
ch parameter

這下踢到鐵板了,讓我們看看錯誤的第 97 行吧!

__MINGW_IMPORT int    __argc_dll;

顯然這牽涉到 __MINGW_IMPORT 這的定義,也就是與 MINGW 有關,經過觀察之後,發現 win32 目錄下居然有 stdio.h 等檔案,於是改用下列指令進行編譯,這樣就通過編譯程序了。

C:\tcc\examples>tcc -I ../include -I ../win32/include ex5.c -o ex5.exe

C:\tcc\examples>ex5
Hello World

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License