自己動手制作CSharp編譯器


  1. 在你喜歡的位置(如F盤根目錄)新建一個文件夾,並命名為“CSharp開發環境”。找到或下載C#編譯器組件(csc.exe和cscui.exe),並放在先前建立的文件夾中。該組件的一般位置在C盤的.NET文件夾中,如“C:\Windows\Microsoft.NET\Framework\v4.0.30319”,最后一個為版本號,可根據你的需要選擇。同時在這個文件夾中還有我們需要的類庫(System.dll),找到並復制到“CSharp開發環境\lib”文件夾中。

  2. 2

    為了能夠在控制台下找到我們的編譯器,下面設置環境變量Path。右擊桌面的計算機->點擊屬性->點擊高級選項卡中的環境變量->在用戶環境變量選中Path並點擊編輯->添加“F:\CSharp開發環境;”->點擊OK即可。如下圖:

    自己動手制作CSharp編譯器
  3. 3

    測試。打開控制台(如果你用到是Win8,可以 Win+X ->C 快速打開控制台),並輸入csc,若出現下圖結果即表示正常。

    自己動手制作CSharp編譯器
    END

編寫代碼

 
  1. 1

    在你喜歡的位置(例如,“F:\CSharp開發環境\project”目錄)中建立一個文件夾,並命名為“cc”,該目錄便是我們存放源代碼的目錄。

  2. 2

    添加源文件。在cc目錄中新建“cc.cs”文件,並用文本編輯器打開,並輸入以下代碼:

    using System;

    using System.IO;

    using System.CodeDom;

    using System.CodeDom.Compiler;

    using Microsoft.CSharp;

    namespace CC{

    public class CC{

    public static void Main(string[] args){

    if(args.Length==0){

    Console.WriteLine("該工具的正確使用方法是:cc 源文件");

    Console.Read();

    return;

    }

    FileInfo sourceFile=new FileInfo(args[0]);

    CodeDomProvider provider=null;

     

    if(sourceFile.Extension.ToUpper()==".CS"){

    provider=CodeDomProvider.CreateProvider("CSharp");

    }

    else if(sourceFile.Extension.ToUpper()==".VB"){

    provider=CodeDomProvider.CreateProvider("VisualBasic");

    }

    else{

    Console.WriteLine("錯誤1:源代碼文件必須以“.cs”或“.vb”為后綴");

    }

     

    if(provider !=null){

    string exeName=String.Format(@"{0}\{1}.exe",Environment.CurrentDirectory,sourceFile.Name.Replace(".","_"));

    CompilerParameters cp=new CompilerParameters();

    cp.GenerateExecutable=true;

    cp.OutputAssembly=exeName;

    cp.GenerateInMemory=false;

    CompilerResults cr=provider.CompileAssemblyFromFile(cp,args[0]);

    if(cr.Errors.Count > 0){

    Console.WriteLine("Errors building {0} into {1}",args[0], cr.PathToAssembly);

    foreach(CompilerError ce in cr.Errors)

    {

    Console.WriteLine("  {0}", ce.ToString());

    Console.WriteLine();

    }

    }

    else

    {

    Console.WriteLine("Source {0} built into {1} successfully.",args[0], cr.PathToAssembly);

    }

    }

    Console.Write("Press any key to exit...");

    Console.Read();

    }

     

    }

    }

  3. 3

    代碼解釋。

    前5行代碼是名稱空間的引用,我們使用的最重要的類便在System.CodeDom.Compiler中。

    6-8行分別定義名稱空間、類和入口函數。

    9-13行是對命令行參數的檢驗,為了簡單,本文設定只有第一個參數有效,並且便是源文件名。

    14-15行定義兩個非常重要的變量,一個表示源文件的變量sourceFile(FileInfo),其參數從上一步中得到,即命令行第一個參數。另一個表示編譯器的變量provider(CodeDomProvider,使用CompileAssemblyFromFile方法即可把源文件編譯成目標文件),並初始化為null。

    17-25行使用“工廠模式”得到CodeDomProvider的實例,即根據后綴初始化為VB編譯器還是C#編譯器。注意:本文只考慮C#代碼,若您還想編譯VB代碼只需添加相應的引用即可。

    27行是對provider的檢驗,若不為空則則可以繼續編譯。這是避免空引用異常的常用方法。28-34行定義編譯選型,即CompilerParameters類。GenerateExecutable=true表示生成可執行文件,若為false表示生成類庫;OutputAssembly表示生成的文件。

    35行調用provider.CompileAssemblyFromFile(編譯選項,源文件)方法生成可執行文件,並得到CompilerResults類的一個實例,該實例表示編譯結果。

    36行以后是對編譯結果的處理,若有錯則輸出錯誤,若成功則提示生成成功。

     

  4. 4

    編譯。我們可以在命令行下直接編譯,而為了在調試時不必重復輸入相同的命令,我們可以做一個批處理。新建文本文件並重命名為“MakeFile.bat”,添加如下代碼:

    csc cc.cs /reference:%Lib%\System.dll

    pause

    然后雙擊運行,若沒有錯誤的話就會得到“cc.exe”文件。

    注意:為了方便的引用類庫,我們需要添加環境變量,“Lib=F:\CSharp開發環境\lib”,注意這里沒有分號而且只有這一個值(這是為了在寫批處理文件時方便采這么設定的)。

    END

測試

 
  1.  

    為了測試我們做的“編譯器”,我們在project目錄中添加hello工程(一個文件夾),並添加源代碼文件“hello.cs”,hello.cs的內容為:

    using System;

     

    namespace Test{

    public class Test{

    public static void Main(string[] arg){

    Console.WriteLine("Hello world");

    Console.ReadLine();

    }

    }

    }

    然后,我們把得到的cc.exe文件復制到當前目錄中。 同樣的,我們也建立一個“MakeFile.bat”文件,代碼如下:

    cc hello.cs

    pause

    雙擊該批處理,若沒有錯誤的話即可得到一個可執行文件(hello_cs.exe),如下:

    自己動手制作CSharp編譯器
  2. 2

    執行“hello_cs.exe”文件,如圖:

    自己動手制作CSharp編譯器
  3.  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM