2017年6月7日 星期三

Build Tiny C Compiler by VC in Visual Studio


     Tiny C compiler (TCC) is a profound contribution by Fabrice Bellard. Originally, the predecessor of TCC was for International Obfuscated C Code Contest. Now it has become an authentic C compiler prestiging for its compact, fast in compilation (not the binary built by TCC runs in high speed), complete (TCC could build itself, and It is evidenced the linux kernel built by TCC is workable) and cross platforms (it support the targets could be x86 32/64 and arm).

  For It does not rely on any library besides C standard (like lex or yacc) and dense code, TCC is excellent compiler for the person beginning to study how a compiler works.  It supports C99 standard but C++ (the C++ standards are very long-winded), Thus, TCC is self-consistent but any redundant implementation, it is beneficial for the compiler learner.

    The original code(obfuscated Tiny C Compiler) for International Obfuscated C Code Contest you could download here.  You should notice that : The compiler is not complete, its purpose is to compiling itself only.

    By default, TCC should be built by gcc (or itself). But the code of TCC tallies with C89, hence, it should be able to be compiled by the other compilers; and Visual Studio series are excellent tools for tracking code. It is high efficiency on studying how a compiler works if somebody observe how TCC works on VS. To achieve this purpose,  is this post's goal.

   In here, I adopt TCC version 0.9.26 and Visual Studio 2005, and the native and target platform are the same : 32 bit Windows.  
   You could download TCC source code in here. The Visual Studio version does not be confined to be VS2005, the versions later than it is workable also.

  零. (Optional) Build TCC via MinGW with gcc.

 After you download the TCC bz2 ball, you could use MinGW to build it :

Go into TCC folder, input the command to configurate the Makefile for TCC:

$ configure --prefix=$PWD/built

After that, build and install the TCC :

$ make && make install

While it has done, test the built tcc binary is workable or not  :

$ built/tcc.exe examples/ex1.c -o ex1.exe && ex1.exe
Hello World

The TCC built by gcc on MinGW works.

You could replace the ex1 as ex2, ex3, ex4, ex5, or the test files in folder built\examples.


  The remain steps are for Visual Studio (VS), you could close your MinGW bash now.

  一. Folder for VS working.

    Create a folder inside TCC folder for VS building. For me, I name the folder as VSBuild. The folder will content one VS solution which have two VC projects: one for building the TCC itself, the other for building TCC essential libraries.      


 二. Build TCC compiler.

 I create the first project named as tcc. The VC project settings :
The source files would be built by this VC-project are : i386-asm.c, i386-gen.c, libtcc.c, tcc.c, tccasm.c, tccelf.c, tccgen.c, tccpe.c, tccpp.c and tccrun.c, those are all located in TCC folder root.


  












The preprocessor definitions (which could be set  in project setting -> configuration properties -> C/C++ ->preprocessor) be :


_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_WARNINGS
TCC_TARGET_PE
TCC_TARGET_I386


(the first two macro is not necessary for VS2005, but if you use the version later than that, the two definition are required for passing the building)

For the include path, it is very simple, just parent directory (TCC folder root):

..\

Till here, this project setting has been done, press play button to observe if the building is passed or not. theoretically, it should pass.


But if you want to use the built TCC to compile the example code, ex1.c. You will find that the executable file would not be generated by TCC:



../examples/ex1.c:2: error: include file 'tcclib.h' not found


That is, the essential library does not exist for TCC usage.


   二. Build TCC essential library.

   The essential library should be compiled by TCC, in here, I add custom-build setting in VS to built the library. Of course, you could build the library via VC, but it is better to follow the standard.
  The second VC project named as tiny_libmaker, it function is the same as GCC tool ar (library archive), to sort .o file(s) as a single .a file.

  The project content one file, tiny_libmaker.c (located in TCC_RPPT\win32\tools), and the setting for preprocessor definition, include path, external library are empty.







 But there are command lines should be set in build event of project setting:


The command lines be:

$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../lib/libtcc1.c -o $(ConfigurationName)/libtcc1.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../lib/alloca86.S -o $(ConfigurationName)/alloca86.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../lib/alloca86-bt.S -o $(ConfigurationName)/alloca86-bt.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../lib/bcheck.c -o $(ConfigurationName)/bcheck.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../win32/lib/crt1.c -o $(ConfigurationName)/crt1.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../win32/lib/wincrt1.c -o $(ConfigurationName)/wincrt1.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../win32/lib/dllcrt1.c -o $(ConfigurationName)/dllcrt1.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../win32/lib/dllmain.c -o $(ConfigurationName)/dllmain.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
$(ConfigurationName)\tcc.exe -c -B../win32 -I../include -c ../win32/lib/chkstk.S -o $(ConfigurationName)/chkstk.o -I..  -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_I386 -DTCC_TARGET_PE
mkdir $(ConfigurationName)\lib
$(ConfigurationName)\tiny_libmaker.exe rcs  $(ConfigurationName)//lib/libtcc1.a  $(ConfigurationName)/libtcc1.o $(ConfigurationName)/alloca86.o $(ConfigurationName)/alloca86-bt.o $(ConfigurationName)/bcheck.o $(ConfigurationName)/crt1.o $(ConfigurationName)/wincrt1.o $(ConfigurationName)/dllcrt1.o $(ConfigurationName)/dllmain.o $(ConfigurationName)/chkstk.o
mkdir  $(ConfigurationName)\include
xcopy /y /s /e ..\win32\include  $(ConfigurationName)\include
xcopy /y /s /e ..\include  $(ConfigurationName)\include

You should be prudent that : back-slash(\) and slash (/) for separating folder layers, correspond to Windows shell and TCC arguments, respectively. You could not be regardless of the difference, or the command lines would not run normally.

After the setting done, set the project ( tiny_libmaker.c) depending on tcc project, And build that.



  三. Rebuild and run tiny C compiler again.

Press the play button, you will find there are output on the output dialog, just like below.

:
:
2>..\win32\include\winapi\wingdi.h
2>..\win32\include\winapi\winnetwk.h
2>..\win32\include\winapi\winnls.h
2>..\win32\include\winapi\winnt.h
2>..\win32\include\winapi\winreg.h
2>..\win32\include\winapi\winuser.h
2>..\win32\include\winapi\winver.h
2>已複製 81 個檔案
2>..\include\float.h
2>..\include\stdarg.h
2>..\include\stdbool.h
2>..\include\stddef.h
2>..\include\tcclib.h
2>..\include\varargs.h


 And the ex1.exe will been generated successfully. Run the binary in Windows command line tool, you will find that :


C:\MinGW\msys\1.0\home\Gaiger\tcc-0.9.26\VSBuild>ex1.exe
Hello World


The TCC works without any insufficiency, it is time to study how a self-consistent compiler meets with standard works via Visual Studio environment.