[MSBuild] 개념잡기 #1 - 기본설정과 동작

4

MSBuild 기본 설정과 동작

일반적으로는 Visual Studio 빌드를 이용해서 처리하지만 파일 배포나 경로 변경 또는 상황적으로 파일 필터링이 필요한 경우등의 추가적인 활용을 위해서는 MSBuild 확장 또는 NAnt 와 같은 빌드 툴을 이용해야 한다.

MSBuild 개념

*.csproj 파일을 생각해 보자. 대부분은 그냥 프로젝트 파일이라고 생각하고 별다른 생각을 하지 않겠지만, 이 파일 자체가 MSBuild를 정의한 파일이다. 즉, 프로젝트를 빌드하기 위해서 필요한 정보를 담고 있는 XML 파일인 것이다.

기본적인 구성

빌드 스크립트는 아래의 샘플과 같이 기본적인 구성이 존재한다. 이 구성을 기준으로 필요한 부분들을 추가하고 조정하면 되는 것이다. 진행하면서 테스트를 위해 아래의 내용을 “build.xml” 이라는 이름으로 생성해 놓도록 하자.

1
2
3
4
5
6
7
8
9
10
11
12
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Tasks 구성 -->
<Target Name="Clean">
<Message Text="타겟: Clean" />
</Target>
<Target Name="Build">
<Message Text="타겟: Build" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean; Build">
<Message Text="타겟: Rebuild" />
</Target>
</Project>

위의 샘플에는 3개의 "Target"이 존재하며 각 “Clean”, “Build”, “Rebuild” 로 지정되어 있다.

  • Clean : 기존 대상을 정리하는 것으로 보통은 bin, obj 폴더를 지우는 역할을 담당한다.
  • Build : 대상 소스 코드를 빌드하는 역할을 담당한다.
  • Rebuild : 다시 빌드하는 것으로 DependsOnTargets에 명기된 “Clean”, “Build” 를 순차적으로 처리한다.

MSBuild 의 기본 구성 요소는 다음과 같다.

  • Item : 소스 파일등과 같은 값을 지칭한다.
  • Property : 속성 정보등과 같은 값을 지칭한다.
  • Target : 작업을 의미하며 처리할 행동을 지칭한다.

실제로 *.csproj 파일을 열어보면 Import, ItemGrop, PropertyGroup 등의 내용을 볼 수 있지만, Target 에 대한 내용은 없다.

Target은 행동을 나타내기 때문에 Visual Studio 에서 MSBuild 에 미리 지정해 놓은 작업들 “Copy”, “Delete”, “Exec”, “ReadLinesFromFile”, “VCBuild” 등의 대략 30 여개 작업들을 호출하는 것이기 때문에 *.csproj 파일은 Task 처리에 필요한 프로젝트 구성 정보만 가지고 있기 때문이다.

이런 Target들은 확장이 가능하며, 대표적인 사례로 MSBuildCommunityTask 라는 오픈 소스도 이런 확장 기능을 사용한 것이다.

MSBuild 실행

위의 기본 구성을 실행해 보기 위해서는 MSBuild.exe 파일의 경로를 찾아야 한다.

Notes

예전에는 MSBuild 가 프레임워크 특정 버전 아래에 존재했었다.

C:\Windows\Microsoft.NET\Framework(또는 Framework64)\v2.0.50727\msbuild.exe

그러나 VS2015 버전 사용 중이라면 설치 경로에 존재할 것이고

C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe

VS2017 버전 사용 중이라면 Visual Studio 설치 경로 아래에 존재할 것이다. C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise(또는 다른 등급)\MSBuild\15.0\bin\msbuild.exe

실행을 위한 스크립트 파일을 아래와 같이 구성하면 된다. (구성하는 방법은 여러 가지가 있으므로 원하는데로 구성하면 된다)

1
2
3
4
5
6
7
8
@echo off

SETLOCAL
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin\msbuild.exe" %*
ENDLOCAL

SET ERR_LEVEL=%errorlevel%
exit /b %ERR_LEVEL%

위의 내용 중에 SETLOCALENDLOCAL 의 기능은 예를 들어 vcvarsall.bat 과 같은 스크립트를 호출했을 때 PATH 정보를 변경하기 때문에 현재 LOCAL 에서만 적용하겠다는 의미이고 %*은 지정된 모든 아규먼트를 그대로 전달한다는 의미를 나타낸다.

이제 실행은 아래와 같이 빌드 시크립트와 태스크를 지정하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
build.bat build.xml /t:build

.NET Framework용 Microsoft (R) Build Engine 버전 15.7.179.6572
Copyright (C) Microsoft Corporation. All rights reserved.

빌드 시작: 2018-06-09 오전 11:45:30
1 노드의 "...\build.xml" 프로젝트(build 대상)입니다.
Build:
타겟: Build
"...\build.xml" 프로젝트를 빌드했습니다(build 대상).

빌드했습니다.
경고 0개
오류 0개

경과 시간: 00:00:00.10

위의 같이 실행될 결과를 확인할 수 있다. 각 태스크인 Clean, Rebuild 를 지정해서 결과를 확인해 보도록 한다.

Notes

스크립트를 실행할 때 build.xml 도 /t:xxx 정보도 주지 않으면 어떻게 될까?

  • 태스크가 지정되지 않으면 build.xml 에 정의된 첫번째 태스크가 수행된다. (DefaultTargets 가 지정되어 있다면 그 태스크가 실행된다)
  • build.xml 이 지정되지 않으면 해당 경로에서 “msbuild.xml” 파일을 찾는다.

Solution Build

이제 기본 스트립트 처리는 완성이 되었으므로 실제 솔루션을 대상으로 동작을 확인해 보도록 하자.

간단하게 “Hello World!” 를 출력하는 콘솔 어플리케이션을 하나 생성하고 프로젝트 파일 (*.csproj)을 열어서 확인해 보도록 하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DFF106D2-66B5-4E04-9300-5426AE6C7771}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>TestApp</RootNamespace>
<AssemblyName>TestApp</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

위의 내용을 대략적으로 확인해 보면 다음과 같은 항목들로 구성된 것을 확인할 수 있다.

  • Import : 또 다른 설정이 존재하는 빌드에 필요한 스크립트 파일을 가져오는데 사용한다. 주로 공통 속성 값을 모아 놓은 것이나 태스크 (Target) 들을 모아놓은 것들이다.
  • PropertyGroup : MSBuild 에 Property 로 값을 전달할 수 있으며, 이런 속성들을 그룹으로 묶어주는 역할을 담당하고 조건에 따라서 적용할 수 있도록 하는데 사용한다. 쉽게 변수 그룹으로 생각하면 된다.
  • ItemGroup : MSBuild 가 처리해야할 대상들을 전달하고 그룹으로 묶어주는 역할을 담당한다. 쉽게 대상 항목들의 배열이라고 생각하면 된다.

Visual Studio 에서 빌드를 하면 이런 정보가 전달이 되고 이 정보들을 기준으로 MSBuild 가 태스크를 실행하게 되는 것이다.

여기서는 스크립트를 통해서 처리하는 것을 알아보고 있으므로 위에서 작성했던 기본 스크립트 파일을 아래와 같이 변경해서 처리하는 것으로 구성해 본다. 물론 솔루션 파일 (*.sln)을 아규먼트로 전달 받아서 처리할 수도 있지만 여기에서는 직접 지정해서 처리하는 것으로 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<Project DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- configuration -->
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">Any CPU</Platform>
<BuildCondition>$(Configuration)|$(Platform)</BuildCondition>
</PropertyGroup>

<!-- Build Condition -->
<PropertyGroup Condition=" '$(BuildCondition)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(BuildCondition)' == 'Release|AnyCPU' ">
</PropertyGroup>

<!-- Solution -->
<ItemGroup>
<ProjectReferences Include=".\TestApp\TestApp.sln">
<Configuration>$(Configuration)</Configuration>
<Platform>$(Platform)</Platform>
</ProjectReferences>
</ItemGroup>

<!-- Targets -->
<Target Name="Clean">
<Message Text="타겟: Clean" />
</Target>
<Target Name="Build">
<Message Text="타겟: Build" />
<Message Text="빌드 조건: '$(BuildCondition)'" Importance="high" />
<MSBuild Projects="@(ProjectReferences)"
Properties="Configuration=%(ProjectReferences.Configuration); Platform=%(ProjectReferences.Platform)"
StopOnFirstFailure="true" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean; Build">
<Message Text="타겟: Rebuild" />
</Target>
</Project>

Notes

  • @(…) : 빌드 스크립트 내부에 정의된 Property나 ItemGroup 을 참조할 때 사용한다.
  • %(…) : 빌드 스크립트 내부에 정의된 Proeprty에 의해서 참조된 내부 Property의 값을 참조할 때 사용한다.

기본 구성에 Configuration 과 Solution 설정이 들어간 것을 확인할 수 있다. Solution 설정은 작성한 샘플 어플리케이션이 존재하는 경로를 지정하면 된다. (여기서는 동일한 경로에 TestApp 라는 이름으로 생성했다)

*.sln 파일 역시 솔루션에 포함될 *.csproj 들을 “ProjectReference” 형식으로 포함하고 있는 MSBuild 스크립트 파일이다.

기본 메시지만 출력하던요소를 실제 MSBuild 가 동작하는 것으로 추가한 ProjectReference를 대상을 지정헀고 Configuration과 Platform 정보가 전달될 수 있도록 구성했다.

이제 옵션을 줘서 실제 빌드를 실행해 보도록 하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
build.bat build.xml /p:Configuration=Release

.NET Framework용 Microsoft (R) Build Engine 버전 15.7.179.6572
Copyright (C) Microsoft Corporation. All rights reserved.

빌드 시작: 2018-06-09 오후 12:38:19
1 노드의 "...\build.xml" 프로젝트(기본 대상)입니다.
Build:
타겟: Build
빌드 조건: 'Release|Any CPU'
"...\build.xml"(1) 프로젝트가 1 노드에서 "...\TestApp\TestApp.sln"(2)을(를) 빌드하고 있습니다(기본 대상).
ValidateSolutionConfiguration:
솔루션 구성 "Release|Any CPU"을(를) 빌드하고 있습니다.
"...\TestApp\TestApp.sln"(2) 프로젝트가 1 노드에서 "...\TestApp\TestApp\TestApp.csproj"(3)을(를) 빌드하고 있습니다(기본 대상).
PrepareForBuild:
"obj\Release\" 디렉터리를 만들고 있습니다.
GenerateBindingRedirects:
ResolveAssemblyReferences에서 제안된 바인딩 리디렉션이 없습니다.
GenerateTargetFrameworkMonikerAttribute:
해당 입력 파일과 비교하여 출력 파일이 모두 최신 파일이므로 "GenerateTargetFrameworkMonikerAttribute" 대상을 건너뜁니다.
CoreCompile:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin\Roslyn\csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:anycpu32bitpreferred /errorreport:prompt /warn:
4 /define:TRACE /highentropyva+ /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Microsoft.CSharp.dll" /reference:"C:\Program Files (x86)\Refer
ence Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Core.dll" /refer
ence:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Data.DataSetExtensions.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft
\Framework\.NETFramework\v4.6.1\System.Data.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll" /reference:"C:\Program Files (x86
)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Net.Http.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xm
l.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xml.Linq.dll" /debug:pdbonly /filealign:512 /optimize+ /out:obj\Release\TestApp.
exe /ruleset:"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Team Tools\Static Analysis Tools\\Rule Sets\MinimumRecommendedRules.ruleset" /subsystemversion:6.00 /target:exe /u
tf8output Program.cs Properties\AssemblyInfo.cs "Z:\TEMP\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs"
디렉터리의 컴파일러로 공유 컴파일 사용: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin\Roslyn
_CopyAppConfigFile:
"App.config"에서 "bin\Release\TestApp.exe.config"(으)로 파일을 복사하고 있습니다.
CopyFilesToOutputDirectory:
"obj\Release\TestApp.exe"에서 "bin\Release\TestApp.exe"(으)로 파일을 복사하고 있습니다.
TestApp -> ...\TestApp\TestApp\bin\Release\TestApp.exe
"obj\Release\TestApp.pdb"에서 "bin\Release\TestApp.pdb"(으)로 파일을 복사하고 있습니다.
"...\TestApp\TestApp\TestApp.csproj" 프로젝트를 빌드했습니다(기본 대상).

"...\TestApp\TestApp.sln" 프로젝트를 빌드했습니다(기본 대상).

"...\build.xml" 프로젝트를 빌드했습니다(기본 대상).

빌드했습니다.
경고 0개
오류 0개

경과 시간: 00:00:01.42

기본 태스크가 “Build” 로 되어 있으므로 /t 옵션은 제외하고, Debug/Realease 값을 옵션으로 전달한 것을 볼 수 있다. 이 옵션 값은 구성한 Build.xml 의 $(Configuration) 속성 값으로 전달되어 처리된다.

Solution Clean

실제 솔루션이 연결되었고 빌드도 처리했으므로 정말 Clean 이 제대로 동작하는지도 확인해 보자. Visual Studio 로 프로젝트나 솔루션을 만들면 Clean 작업이 이미 구성되어있기 때문에 동작이 되어야 한다.

build.xml 에 Clean 태스크를 아래와 같이 변경하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
...
<!-- Targets -->
<Target Name="Clean">
<Message Text="타겟: Clean" />
<Message Text="빌드 조건: '$(BuildCondition)'" Importance="high" />
<MSBuild Projects="@(ProjectReferences)"
Targets="Clean"
Properties="Configuration=%(ProjectReferences.Configuration); Platform=%(ProjectReferences.Platform)"
StopOnFirstFailure="true" />
</Target>
...

MSBuild 에 이미 구성되어 있는 Clean 태스크가 동작하도록 Targets="Clean"을 설정한 것을 확인할 수 있다.

이제 실행을 해서 제대로 Clean 이 동작하는지를 확인해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
build.bat build.xml /p:Configuration=Release /t:Clean

.NET Framework용 Microsoft (R) Build Engine 버전 15.7.179.6572
Copyright (C) Microsoft Corporation. All rights reserved.

빌드 시작: 2018-06-09 오후 1:05:45
1 노드의 "...\build.xml" 프로젝트(Clean 대상)입니다.
Clean:
타겟: Clean
빌드 조건: 'Release|Any CPU'
"...\build.xml"(1) 프로젝트가 1 노드에서 "...\TestApp\TestApp.sln"(2)을(를) 빌드하고 있습니다(Clean 대상).
ValidateSolutionConfiguration:
솔루션 구성 "Release|Any CPU"을(를) 빌드하고 있습니다.
"...\TestApp\TestApp.sln"(2) 프로젝트가 1 노드에서 "...\TestApp\TestApp\TestApp.csproj"(3)을(를) 빌드하고 있습니다(Clean 대상).
CoreClean:
"...\TestApp\TestApp\bin\Release\TestApp.exe.config" 파일을 삭제하고 있습니다.
"...\TestApp\TestApp\bin\Release\TestApp.exe" 파일을 삭제하고 있습니다.
"...\TestApp\TestApp\bin\Release\TestApp.pdb" 파일을 삭제하고 있습니다.
"...\TestApp\TestApp\obj\Release\TestApp.csprojAssemblyReference.cache" 파일을 삭제하고 있습니다.
"...\TestApp\TestApp\obj\Release\TestApp.csproj.CoreCompileInputs.cache" 파일을 삭제하고 있습니다.
"...\TestApp\TestApp\obj\Release\TestApp.exe" 파일을 삭제하고 있습니다.
"...\TestApp\TestApp\obj\Release\TestApp.pdb" 파일을 삭제하고 있습니다.
"...\TestApp\TestApp\TestApp.csproj" 프로젝트를 빌드했습니다(Clean 대상).

"...\TestApp\TestApp.sln" 프로젝트를 빌드했습니다(Clean 대상).

"...\build.xml" 프로젝트를 빌드했습니다(Clean 대상).

빌드했습니다.
경고 0개
오류 0개

경과 시간: 00:00:00.23

위의 결과와 같이 bin, obj 폴더에 존재하는 파일들을 삭제한 것을 확인할 수 있다. 그러나 실제 대상 폴더에 가 보면 Visual Studio 디버깅 과정에서 자동으로 생성된 .vshost. 등과 같은 파일들이 삭제되지 않고 남아있을 수도 있다. 따라서 완전히 Clean 작업을 수행하기 위해서는 해당 폴더를 삭제하는 것이 필요할 때가 있다.

이를 위해서는 아래와 같이 빌드 스크립트에 폴더와 관련된 설정을 추가해 줘야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
<!-- Clean Dir 설정 -->
<ItemGroup>
<BinDirs Include="**\**\bin\$(Configuration)" />
<ObjDirs Include="**\**\obj\$(Configuration)" />
</ItemGroup>
...
<Target Name="Clean">
<Message Text="타겟: Clean" />
<Message Text="빌드 조건: '$(BuildCondition)'" Importance="high" />
<MSBuild Projects="@(ProjectReferences)"
Targets="Clean"
Properties="Configuration=%(ProjectReferences.Configuration); Platform=%(ProjectReferences.Platform)"
StopOnFirstFailure="true" />
<RemoveDir Directories="@(BinDirs);@(ObjDirs)" />
</Target>

위에서 보이는 것과 같이 ItemGroup 으로 BinDirs, ObjDirs 를 정의하고 Clean 태스크에서 “RemoveDir” 태스크를 호출해서 삭제하는 것을 확인할 수 있다.

물론 내부에 삭제되지 않은 파일이 있을 경우에는 파일이 존재해서 삭제할 수 없다는 오류가 발생할 수 있고, 중첩된 폴더들이 존재하는 경우도 있을 수 있으므로 이런 경우를 모두 감안하려면

1
2
3
...
<Exec Command="..." />
...

와 같이 Command line 명령을 수행하도록 할 수도 있으며, MSBuild Extenstions 들을 통해서 처리할 수도 있다.

Debugging

아직은 스크립트 상태일 뿐이므로 디버깅보다는 디버깅을 위한 옵션이 어떻게 존재하는지를 알아보도록 한다.

1
build.bat /?

MSBuild 에서 제공하는 여러가지 옵션들이 보인다. 그 중에서 디버깅 용도로 사용할 수 있는 옵션은 /verbosity:<level> 로 약어로는 /v:<level> 로 지정하면 된다. 사용할 수 있는 Level 은 다음과 같다.

  • q[uiet] : 로거로 요약만 처리된다.
  • m[minimal] : 로거에 요약과 오류, 경고등과 같은 중요 메시지만 처리된다.
  • n[ormal] : 로거에 요약과 오류, 경고등과 같은 중요 메시지와 이벤트 상태 정보를 처리한다.
  • d[etail] : 로거에 요약과 오류, 경고등과 같은 중요 및 일반 메시지와 이벤트 상태 정보를 처리한다.
  • diag[nostic] : 로거에 빌드 요약과 모든 메시지, 이벤트 등의 전부를 처리한다.

Conclusion

지금까지 아주 기본적인 MSBuild 의 구성과 동작에 대해서 정리해 보았다. 현재는 많은 확장들이 오픈소스로 제공되고 있으므로 이를 활용해서 빌드 스크립트를 구성하는 것이 좋다.

이 글을 정리하는 의미는 향후에 개발하는 모든 프로젝트에 빌드 스크립트를 적용해서 문서화 (DocFx를 사용해서 Markdown 기반의 Static Site 제공까지 고려) 를 하는 기반으로 사용하기 위함이다.

다음에는 DocFx 와의 연계를 하는 부분에 대해서 정리할 생각이다.

Written by Morris (ccambo@gmail.com - MSFL)


공유하기