Monday, April 6, 2015

MSBuild 시작하기

MSBuild란 무엇인가? MSBuild란 오프라인, 그러니까 콘솔에서 Visual Studio IDE에서 수행했던 컴파일과 링크, 빌드를 수행해 주게 하는 프로그램이다. 유닉스에서 GNU Make, 자바의 Ant와 비슷하다. (금융권에 근무하던 시절 Makefile을 수천번 수정하고, 자바의 Ant로 자동빌드를 수행하던 기억이 난다.)

사실 처음에 MSBuild를 접하고 공부하였을 때는 Visual Studio는 JDK와 Eclipse처럼 IDE와 SDK가 분리되지 않는다고 생각했었다. 그러나 이것도 예전에 어렴풋이 알고 있던 cl.exe, al.exe, ln.exe와 같이 빌드시스템도 마찬가지로 분리되어 있었다.

Visual Studio에서 무언가를 컴파일 할려면 일반적으로 IDE(즉, Visual Studio GUI 프로그램)을 열어서 컴파일을 해야한다. 그런데 솔루션에 포함된 프로젝트가 정말 많고, 일부만 변해도 전체를 다 읽어서 컴파일을 할 것인가? 이것은 대규모 프로젝트에서는 IDE를 로딩하고 솔루션을 로딩하는데에 상당한 시간을 할애하게 되어, 누적되면 엄청난 시간의 손실을 가져온다.

또한, 그래피컬하게 프로젝트의 프로퍼티 페이지를 수정하는 것의 이점도 있지만, 직접 MSBuild 스크립트를 수정하여 사용하게 되면 조건에 따른 컴파일, 프로젝트 설정간의 상속도 가능하며, 중앙집중식 관리도 가능하다. MSBuild 스크립트는 csproj(C#), vbproj(VB.NET)와 같이 .NET 언어의 프로젝트 파일을 말하는데, 열어보면 알겠지만 XML이다.

암튼, 그래서 배우게 된 MSBuild. 이름도 많이 들어보고 인터넷 상에 자료도 많고 MSDN에 자료도 많지만 정작 가장 simple한 example이 없어서 직접 만들어 보았다. 언어는 C#이며, csproj에 .NET Framework 2.0의 MSBuild를사용한다.

MSBuild.exe는 C:\Windows\Microsoft.NET\Framework\v2.0.50727에 있다.
그리고 C#컴파일러인 csc.exe도 같은 폴더에 존재한다.

다음은 간단한 예제 C#소스이다. 사실 아무것도 없는 Hello World이다.
consolehwcs1.cs:
using System;
/// <summary>
/// Summary description for Class1
/// </summary>
public class ConsoleHWCS1
{
    public static void Main()
 {
  //
  // TODO: Add constructor logic here
  //
        Console.WriteLine("ConsoleHWCS1");
 }
}

다음은 우리가 살펴볼 예제 msbuild스크립트이다.(확장자가 csproj이다.)
MSBuildTest.csproj:
// 디폴트 타겟은 "Compile"이다.
<Project DefaultTargets = "Compile"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
// 프로퍼티 그룹, 여기에 정의된 <tag>들은 $(tag)이렇게 사용할 수 있다. 상수와 같다.
    <PropertyGroup>
// 어플리케이션 이름 
        <!-- Set the application name as a property -->
        <appname>HelloWorldCS</appname><!-- exe output filename -->
// 출력 폴더 이름
        <!-- Set the output folder as a property -->
        <builtdir>BuiltApp</builtdir>
    </PropertyGroup>

    <ItemGroup>
// 여기는 컴파일될 소스들의 리스트를 적는다.
        <!-- Specify the inputs by type and file name -->
        <CSFile Include = "consolehwcs1.cs"/>
    </ItemGroup>

// 여기는 컴파일 타겟을 정의 한다.
    <Target Name = "Compile">
        <!-- Check whether an output folder exists and create
        one if necessary -->
// 빌드디렉토리가 없을 경우(컨디션 적용), 디렉토리를 만든다. 이런것도 가능하다. 원래 Visual Studio의 기능이니
        <MakeDir Directories = "$(builtdir)" 
            Condition = "!Exists('$(builtdir)')" />

// 컴파일러를 호출해서 컴파일을 수행한다.
// 출력파일(어셈블리)이름도 정의해 준다.
// 그리고 소스들은 멀티로 적용한다. @(CSFIle)
        <!-- Run the Visual C# compiler -->
        <CSC Sources = "@(CSFile)" 
            OutputAssembly = "$(BuiltDir)\$(appname).exe">
            <Output TaskParameter = "OutputAssembly"
                ItemName = "EXEFile" />
        </CSC>

// 빌드가 끝나고 화면에 메세지를 뿌려준다. 위에서 정의한 OutputAssembly를 EXEFile에 보존했다가 화면에 뿌려줌
        <!-- Log the file name of the output file -->
        <Message Text="The output file is @(EXEFile)"/>
    </Target>
// 유닉스에서 Make clean과 동일하다. 전체 지우고 리빌드 할 경우에 사용

    <Target Name = "Clean">
        <RemoveDir Directories="$(builtdir)" />
    </Target>
</Project>


다음과 같이 입력후에 수행을 하면 빌드가 된다.
C:\Windows\Microsoft.NET\Framework\v2.0.50727\msbuild msbuildtest.csproj /t:Compile

/t:Compile은 컴파일 타겟이다. 유닉스에서 Make TargetName을 하는 것과 유사하다.
그러면 다음과 같이 메세지가 나오면서 빌드이 될 것이고, 결과 실행파일인 HelloWorldCS.exe는 .\BuildApp에 들어가게 된다.


이상으로 첫 MSBuild 프로그램이 완성 되었다. 끝으로, csproj파일을 Visual Studio에서 로딩을해 보면 로딩이 될 것이다.  

No comments:

Post a Comment