흠....

제목이 좀 이상한데....엄밀이 말해서 런타임에 컴파일을 하는 게 아니고 닷넷 프로그램을 이용하여 닷넷을 컴파일하는 것을 말합니다.

일종의 컴파일러를 만드는 것을 의미합니다.

다행히도 닷넷에서는 컴파일을 위한 api를 제공하기 때문에 손쉽게 이런 컴파일러를 만들 수 있죠.

 

그럼 이런 컴파일러를 왜 만들어야 하는가?

라는 질문을 하게 되는데....

이건 이 포스팅의 마지막에 다루겠습니다.

 

 

1. 'CodeDom'을 이용하기

MSDN에 설명이 잘 나와 있습니다만.... 이 기능은 소스코드를 빌드하기위한 기능입니다.

(참고 : MSDN - CodeDOM 사용)

 

그러니 우리는 'CodeDom'을 이용하여 동적으로 코드를 컴파일 할 수 있다는 것입니다.

 

 

2. 샘플 만들기

샘플을 간단하게 윈폼에서 만들겠습니다.

버튼을 누르면 빌드가되고 빌드결과를 텍스트 박스에 출력 하는 형식입니다.

 

 

2-1. 디자인

윈폼프로젝트를 만듭니다.

버튼 한개와 텍스트박스를 넣고 텍스트 박스의 'Multilne'속성을 'True'로 바꿉니다.

 

 

 

 

 

 

 

2-2. 코드 넣기

 

using System.CodeDom.Compiler;

을 해주신후 버튼의 클릭이벤트에 다음과 같이 코드를 넣습니다.

 

 

public partial class Form1 : Form
{
	public Form1()
	{
		InitializeComponent();
	}


	private void button1_Click(object sender, EventArgs e)
	{

		string sCode = @"
using System;
 
namespace Zmeun.CodeDom
{
class CodeDomTest
{
    static void Main(string[] args)
    {
        System.Console.WriteLine(""Hello World!"");
        System.Console.WriteLine(""Press the Enter key to continue."");
        System.Console.ReadLine();
    }
}
}";

		CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("c#");
		CompilerParameters compilerParameters = new CompilerParameters();

		//.GenerateExecutable 이값을 'false'로 하면 dll로 출력됨
		compilerParameters.GenerateExecutable = true;
		compilerParameters.OutputAssembly = @"c:\test.exe";
		CompilerResults compilerResults = codeDomProvider.CompileAssemblyFromSource(compilerParameters, sCode);

		if (compilerResults.Errors.Count > 0)
		{
			textBox1.Text = compilerResults.Errors[0].ToString();
		}
		else
		{
			textBox1.Text = "성공";
		}

	}

		
}

 

CodeDomProvider.CreateProvider("c#");

를 통해 컴파일할 언어를 지정합니다.

닷넷언어들은 다쓸수 있다고 보시면 됩니다.

(참고 : MSDN - CodeDomProvider.CreateProvider 메서드 (String))

c#, vb

등을 사용할 수 있습니다.

자세한 내용은 아래 링크dml 63라인부터 보시면 각언어의 프로바인더 정보가 나와있습니다.

(참고 : Microsoft Reference Source - CodeDomCompilationConfiguration)

 

compilerParameters.GenerateExecutable = true;

'GenerateExecutable'이 속성을 'true'로 하면 실행파일(.exe)로 만들어 집니다.

dll로 만들고 싶으시면 false를 합니다.

 

compilerParameters.OutputAssembly = @"c:\test.exe";

출력 위치 및 파일이름 입니다.

 

CompilerResults compilerResults = codeDomProvider.CompileAssemblyFromSource(compilerParameters, sCode);

컴파일을 진행 합니다.

컴파일 하는 동안 애러가 발생하면 'compilerResults.Errors'에 에러가 쌓입니다.

 

 

1. 테스트

이제 테스트를 해봅시다.

 

 

헉!!!

이런이런,,,,,

이거 비주얼 스튜디오를 관리자 권한으로 열지 않으면 이런 에러가 발생 합니다.

 

비주얼 스튜디오를 관리자 권한으로 열고 다시 해봅시다.

 

 

잘되네요 ㅋ

 

 

마무리

프로젝트의 샘플입니다.

 

CodeDom.zip

 

 

이렇게 우리는 닷넷 컴파일러를 만들었습니다. ㅡ.ㅡ

왜 이런 짓을 하느냐....

 

UI의 재구성이라던가 프로그램의 재구성을 하는데 코어프로그램을 재컴파일하지 않고 해야 하는 경우가 있습니다.

보안적인 목적이라던가 사용자나 디자이너의 커스텀을 쉽게 하려는 목적일 수도 있습니다.

이런 경우 사용하는 것이 스크립(script)입니다.

 

스크립을 구현하기 위해서 인터프리터(interpreter)를 만들 수도 있고 이미 구현된 스크립언어들을 쓸 수도 있습니다.

그리고 보통은 스크립트는 실행마다 컴파일과 비슷한 과정을 거치게 됩니다.

 

그런데 닷넷의 경우 api가 제공되므로 손쉽게 C#이나 VB.Net 같은 닷넷언어로 만들어진 소스 자체를 스크립트처럼 사용할 수 있다는 장점이 있습니다.

다른 스크립트 언어와 다르게 컴파일을 하면 .exe파일이나 .dll로 출력이 됩니다.

덕분에 컴파일만 끝나면 재컴파일 없이도 참조만으로 사용할 수 있기 때문에 실행 속도가 빠릅니다.

(dll을 동적으로 로드하여 사용합니다.)

문제는 만들어진 닷넷 스크립트는 코어프로그램에 맞먹는 동작이 가능하다는 점입니다.

(저도 이 기능을 많이 사용해보지 않아서 잘 모르겠지만 동작을 어느 정도 제한하는 것이 가능할 것으로 예상되네요.)

장점이자 단점이기도 하죠 ㅎㅎㅎㅎ

 

이 기능을 프로그램 시작전 런처프로그램등을 이용하여 dll을 생성한후 참조할 수도 있고 프로그램실행중에 생성하여 동적 참조를 할 수도 있습니다.

(참고 : [.Net] DLL을 동적으로 로드하기)

 

다른 테스트 프로그램

DynamicCompile 0.1 - C#, VB.Net, javascript, c++ 컴파일러

 



 

 

  1. 안녕하세요 2019.01.24 16:56 신고  Address  Edit/Delete  Reply

    꼭 찾던 정보였는데 큰 도움이 되었습니다!
    감사합니다~

댓글 작성

이름
패스워드
홈페이지
비밀글