MSBuild는 실제로 어떻게 작동하나요? 이 문서에서는 MSBuild가 Visual Studio에서 호출하든 명령줄이나 스크립트에서 호출하든 프로젝트 파일을 처리하는 방법을 알아봅니다. MSBuild의 작동 방식을 알면 문제를 더 잘 진단하고 빌드 프로세스를 더 잘 사용자 지정할 수 있습니다. 이 문서에서는 빌드 프로세스를 설명하고 모든 프로젝트 형식에 주로 적용됩니다.
전체 빌드 프로세스는 초기 시작, 평가및 프로젝트를 빌드하는 대상 및 작업의 실행 구성됩니다. 이러한 입력 외에도 외부 가져오기는 microsoft.Common.targets 같은 표준 가져오기 솔루션 또는 프로젝트 수준에서 사용자 구성 가능한 가져오기를 포함하여 빌드 프로세스의 세부 정보를 정의합니다.
스타트업
MSBuild는 visual Studio에서 Microsoft.Build.dllMSBuild 개체 모델을 통해 호출하거나 명령줄 또는 CI 시스템과 같은 스크립트에서 실행 파일(MSBuild.exe
또는 dotnet build
)을 직접 호출하여 호출할 수 있습니다. 두 경우 모두 빌드 프로세스에 영향을 주는 입력에는 프로젝트 파일(또는 Visual Studio 내부 프로젝트 개체), 솔루션 파일, 환경 변수 및 명령줄 스위치 또는 해당 개체 모델 등가물이 포함될 수 있습니다. 시작 단계에서는 로거 구성과 같은 MSBuild 설정을 구성하는 데 명령줄 옵션 또는 개체 모델에 해당하는 옵션이 사용됩니다.
-property
또는 -p
스위치를 사용하여 명령줄에 설정된 속성은 나중에 프로젝트 파일을 읽어도 프로젝트 파일에서 설정되는 값을 재정의하는 전역 속성으로 설정됩니다.
다음 섹션에서는 솔루션 파일 또는 프로젝트 파일과 같은 입력 파일에 대해 설명합니다.
솔루션 및 프로젝트
MSBuild 인스턴스는 솔루션의 일부로 하나의 프로젝트 또는 여러 프로젝트로 구성됩니다. 솔루션 파일은 MSBuild XML 파일이 아니지만 MSBuild는 지정된 구성 및 플랫폼 설정에 대해 빌드해야 하는 모든 프로젝트를 알도록 해석합니다. MSBuild가 이 XML 입력을 처리할 때 이를 솔루션 빌드라고 합니다. 모든 솔루션 빌드에서 무언가를 실행할 수 있는 확장 가능한 지점이 있지만, 이 빌드는 개별 프로젝트 빌드와는 별개의 실행이므로 솔루션 빌드의 속성 또는 대상 정의 설정은 각 프로젝트 빌드와 관련이 없습니다.
솔루션 빌드 사용자 지정에서 솔루션 빌드를 확장하는 방법을 확인할 수 있습니다.
Visual Studio 빌드 및 MSBuild.exe 빌드
Visual Studio에서 프로젝트를 빌드하는 경우와 MSBuild 실행 파일을 통해 MSBuild를 직접 호출할 때 또는 MSBuild 개체 모델을 사용하여 빌드를 시작할 때와 몇 가지 중요한 차이점이 있습니다. Visual Studio는 Visual Studio 빌드에 대한 프로젝트 빌드 순서를 관리합니다. 개별 프로젝트 수준에서만 MSBuild를 호출하며, 이 경우 MSBuild가 수행하는 일에 크게 영향을 주는 부울 속성(BuildingInsideVisualStudio
, BuildProjectReferences
)이 몇 개 설정됩니다. 각 프로젝트 내에서 실행은 MSBuild를 통해 호출될 때와 동일하게 발생하지만 참조된 프로젝트에서 차이가 발생합니다. MSBuild에서 참조된 프로젝트가 필요한 경우 빌드가 실제로 발생합니다. 즉, 작업 및 도구를 실행하고 출력을 생성합니다. Visual Studio 빌드에서 참조된 프로젝트를 찾으면 MSBuild는 참조된 프로젝트의 예상 출력만 반환합니다. Visual Studio에서 이러한 다른 프로젝트의 빌드를 제어할 수 있습니다. Visual Studio는 빌드 순서를 결정하고 필요에 따라 MSBuild를 별도로 호출하며, 모두 Visual Studio의 제어 하에 있습니다.
또 다른 차이점은 MSBuild가 솔루션 파일을 사용하여 호출될 때 발생합니다. MSBuild는 솔루션 파일을 구문 분석하고, 표준 XML 입력 파일을 만들고, 평가하고, 프로젝트로 실행합니다. 솔루션 빌드는 프로젝트 전에 실행됩니다. Visual Studio에서 빌드할 때는 이 작업이 수행되지 않습니다. MSBuild는 솔루션 파일을 볼 수 없습니다. 결과적으로 솔루션은 이전에 사용하여 사용자 지정을 빌드합니다. SolutionName.sln.targets는 후 . SolutionName.sln.targets)는 Visual Studio 빌드가 아닌 MSBuild.exe, dotnet build
또는 개체 모델 기반 빌드에만 적용됩니다.
프로젝트 SDK
MSBuild 프로젝트 파일의 SDK 기능은 비교적 새로운 기능입니다. 이 변경이 있기 전에는 프로젝트 파일이 특정 프로젝트 형식의 빌드 프로세스를 정의하는 .targets 파일과 .props 파일을 명시적으로 가져왔습니다.
.NET Core 프로젝트는 적절한 .NET SDK 버전을 가져옵니다. 개요, .NET Core 프로젝트 SDK , 그리고 속성에 대한 참조를 보십시오.
평가 단계
이 섹션에서는 이러한 입력 파일을 처리하고 구문 분석하여 빌드할 내용을 결정하는 메모리 내 개체를 생성하는 방법을 설명합니다.
평가 단계의 목적은 입력 XML 파일 및 로컬 환경을 기반으로 메모리에 개체 구조를 만드는 것입니다. 평가 단계는 프로젝트 XML 파일과 같은 입력 파일을 처리하는 6개의 패스로 구성되며, 가져온 XML 파일은 주로 속성을 설정하거나 빌드 대상을 정의하는지 여부에 따라 .props 또는 .targets 파일로 이름이 지정됩니다. 각 패스는 나중에 실행 단계에서 프로젝트를 빌드하는 데 사용되는 메모리 내 개체의 일부를 빌드하지만 평가 단계 중에는 실제 빌드 작업이 발생하지 않습니다. 각 패스 내에서 요소는 표시되는 순서대로 처리됩니다.
평가 단계의 통과는 다음과 같습니다.
- 환경 변수 평가
- 가져오기 및 속성 평가
- 항목 정의 평가
- 항목 평가
- UsingTask 요소 평가
- 대상 평가하기
가져오기 및 속성은 가져오기가 현재 위치에서 확장되는 것처럼 모양 순서대로 동일한 패스로 평가됩니다. 따라서 이전에 가져온 파일의 속성 설정은 나중에 가져온 파일 내에서 사용할 수 있습니다.
이러한 패스의 순서는 상당한 영향을 미치며 프로젝트 파일을 사용자 지정할 때 알아야 합니다. 속성 및 항목 평가 순서참조하세요.
환경 변수 평가
이 단계에서는 환경 변수를 사용하여 동등한 속성을 설정합니다. 예를 들어 PATH 환경 변수는 속성 $(PATH)
사용할 수 있습니다. 명령줄 또는 스크립트에서 실행하는 경우 명령 환경은 정상적으로 사용되며 Visual Studio에서 실행하면 Visual Studio가 시작될 때 적용되는 환경이 사용됩니다.
가져오기 및 속성 검토
이 단계에서는 프로젝트 파일 및 전체 가져오기 체인을 포함하여 전체 입력 XML을 읽습니다. MSBuild는 프로젝트의 XML과 가져온 모든 파일을 나타내는 메모리 내 XML 구조를 만듭니다. 현재 대상에 없는 속성이 평가되고 설정됩니다.
프로세스 초기에 모든 XML 입력 파일을 읽는 MSBuild의 결과로 빌드 프로세스 중에 이러한 입력을 변경해도 현재 빌드에는 영향을 주지 않습니다.
대상 외부의 속성은 대상 내의 속성과 다르게 처리됩니다. 이 단계에서는 대상 외부에서 정의된 속성만 평가됩니다.
속성은 속성 전달에서 순서대로 처리되므로 입력의 모든 지점에서 속성은 입력의 앞부분에 표시되는 속성 값에 액세스할 수 있지만 나중에 표시되는 속성은 액세스할 수 없습니다.
항목이 평가되기 전에 속성이 처리되므로 속성이 전달되는 동안에는 항목의 값에 액세스할 수 없습니다.
항목 정의 평가
이 단계에서는 항목 정의가 해석되고 이러한 정의의 메모리 내 표현이 만들어집니다.
항목 평가
대상 내에 정의된 항목은 대상 외부의 항목과 다르게 처리됩니다. 이 단계에서는 대상 외부의 항목과 관련 메타데이터가 처리됩니다. 항목 정의에 의해 설정된 메타데이터는 항목에 설정된 메타데이터에 의해 재정의됩니다. 항목이 표시되는 순서대로 처리되므로 이전에 정의된 항목을 참조할 수 있지만 나중에 표시되는 항목은 참조할 수 없습니다. 항목 전달은 속성 전달 이후이므로 속성 정의가 나중에 표시되는지 여부에 관계없이 대상 외부에서 정의된 경우 항목이 모든 속성에 액세스할 수 있습니다.
UsingTask
요소를 평가하다
이 단계에서는 UsingTask 요소가 읽혀지며, 작업들이 실행 단계에서 나중에 사용될 수 있도록 선언됩니다.
대상 평가
이 단계에서는 실행을 준비하기 위해 모든 대상 개체 구조가 메모리에 생성됩니다. 실제 실행은 발생하지 않습니다.
실행 단계
실행 단계에서 대상은 순서가 지정되고 실행되며 모든 태스크가 실행됩니다. 그러나 먼저 대상 내에 정의된 속성과 항목은 표시되는 순서대로 단일 단계로 함께 평가됩니다. 처리 순서는 대상에 없는 속성 및 항목이 처리되는 방식과 특히 다릅니다. 모든 속성은 먼저, 모든 항목은 별도의 패스로 처리됩니다. 대상 내의 속성 및 항목에 대한 변경 사항은 변경이 발생한 대상 이후에 관찰할 수 있습니다.
대상 빌드 순서
단일 프로젝트에서 대상은 직렬로 실행됩니다. 핵심 문제는 종속성이 올바른 순서로 대상을 빌드하는 데 사용되도록 모든 항목을 빌드할 순서를 결정하는 방법입니다.
대상 빌드 순서는 각 대상에서 BeforeTargets
, DependsOnTargets
및 AfterTargets
특성을 사용하여 결정됩니다. 이전 대상이 이러한 특성에서 참조되는 속성을 수정하는 경우 이전 대상을 실행하는 동안 이후 대상의 순서가 영향을 받을 수 있습니다.
순서 지정 규칙은 대상 빌드 순서확인에 설명되어 있습니다. 프로세스는 빌드할 대상이 포함된 스택 구조에 의해 결정됩니다. 이 작업의 최상단 대상이 실행을 시작하고, 다른 항목에 의존하면 그러한 대상들은 스택의 맨 위로 푸시되고 실행을 시작합니다. 종속성이 없는 대상이 있으면 완료까지 실행되고 부모 대상이 다시 시작됩니다.
프로젝트 참조
MSBuild에서 사용할 수 있는 두 가지 코드 경로, 즉 여기에 설명된 일반 경로와 다음 섹션에 설명된 그래프 옵션이 있습니다.
개별 프로젝트는 ProjectReference
항목을 통해 다른 프로젝트에 대한 의존도를 지정합니다. 스택 맨 위에 있는 프로젝트가 빌드를 시작하면 공통 대상 파일에 정의된 표준 대상인 ResolveProjectReferences
대상이 실행되는 지점에 도달합니다.
ResolveProjectReferences
출력을 가져오기 위해 ProjectReference
항목의 입력을 사용하여 MSBuild 작업을 호출합니다.
ProjectReference
항목은 Reference
같은 로컬 항목으로 변환됩니다. 현재 프로젝트에 대한 MSBuild 실행 단계는 실행 단계가 참조된 프로젝트를 처리하기 시작하는 동안 일시 중지됩니다(평가 단계는 필요에 따라 먼저 수행됨). 참조된 프로젝트는 종속 프로젝트 빌드를 시작한 후에만 빌드되므로 프로젝트 빌드 트리가 만들어집니다.
Visual Studio를 사용하면 솔루션(.sln) 파일에서 프로젝트 종속성을 만들 수 있습니다. 종속성은 솔루션 파일에 지정되며 솔루션을 빌드하거나 Visual Studio 내에서 빌드할 때만 적용됩니다. 단일 프로젝트를 빌드하는 경우 이러한 유형의 종속성은 무시됩니다. 솔루션 참조는 MSBuild에서 ProjectReference
항목으로 변환된 후 동일한 방식으로 처리됩니다.
그래프 옵션
그래프 빌드 스위치(-graphBuild
또는 -graph
)를 지정하면 ProjectReference
MSBuild에서 사용하는 일류 개념이 됩니다. MSBuild는 모든 프로젝트를 구문 분석하고 프로젝트의 실제 종속성 그래프인 빌드 순서 그래프를 생성한 다음 빌드 순서를 결정하기 위해 트래버스됩니다. 개별 프로젝트의 대상과 마찬가지로 MSBuild는 참조된 프로젝트가 의존하는 프로젝트 다음에 빌드되도록 합니다.
병렬 실행
다중 프로세서 지원(-maxCpuCount
또는 -m
스위치)을 사용하는 경우 MSBuild는 사용 가능한 CPU 코어를 사용하는 MSBuild 프로세스인 노드를 만듭니다. 각 프로젝트는 사용 가능한 노드에 제출됩니다. 노드 내에서 개별 프로젝트 빌드는 직렬로 실행됩니다.
작업은 MSBuild의 $(BuildInParallel)
속성 값에 따라 설정된 부울 변수 BuildInParallel설정하여 병렬 실행을 사용하도록 설정할 수 있습니다. 병렬 실행을 사용하도록 설정된 작업의 경우 작업 스케줄러는 노드를 관리하고 노드에 작업을 할당합니다.
표준 가져오기
Microsoft.Common.props 및 Microsoft.Common.targets 모두 .NET 프로젝트 파일(SDK 스타일 프로젝트에서 명시적 또는 암시적으로)으로 가져오며 Visual Studio 설치의 MSBuild\Current\bin 폴더에 있습니다. C++ 프로젝트에는 고유한 가져오기 계층 구조가 있습니다. C++ 프로젝트에 대한 MSBuild 내부참조하세요.
Microsoft.Common.props 파일은 재정의할 수 있는 기본값을 설정합니다. 프로젝트 파일의 시작 부분에서 명시적으로 또는 암시적으로 가져옵니다. 이렇게 하면 프로젝트의 설정이 기본값보다 이후에 나타나게 되어 기본값을 재정의할 수 있습니다.
Microsoft.Common.targets 파일 및 가져오는 대상 파일은 .NET 프로젝트의 표준 빌드 프로세스를 정의합니다. 또한 빌드를 사용자 지정하는 데 사용할 수 있는 확장 지점을 제공합니다.
구현에서 Microsoft.Common.targets 는 Microsoft.Common.CurrentVersion.targets 를 가져오는얇은 래퍼입니다. 이 파일에는 표준 속성에 대한 설정이 포함되어 있으며 빌드 프로세스를 정의하는 실제 대상을 정의합니다.
Build
대상은 여기에서 정의되지만 실제로는 비어 있습니다. 그러나 Build
대상에는 실제 빌드 단계를 구성하는 개별 대상(BeforeBuild
, CoreBuild
및 AfterBuild
)을 지정하는 DependsOnTargets
특성이 포함됩니다.
Build
대상은 다음과 같이 정의됩니다.
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(BuildDependsOn)"
Returns="@(TargetPathWithTargetPlatformMoniker)" />
BeforeBuild
및 AfterBuild
확장 지점입니다. microsoft.Common.CurrentVersion.targets 파일에 비어 있지만 프로젝트는 기본 빌드 프로세스 전후에 수행해야 하는 태스크와 함께 고유한 BeforeBuild
및 AfterBuild
대상을 제공할 수 있습니다.
AfterBuild
가 Build
대상의 DependsOnTargets
특성에 나타나기 때문에 AfterBuild
는 no-op 대상 및 Build
보다 먼저 실행되지만, 이는 CoreBuild
이후에 발생합니다.
CoreBuild
대상에는 다음과 같이 빌드 도구에 대한 호출이 포함됩니다.
<PropertyGroup>
<CoreBuildDependsOn>
BuildOnlySettings;
PrepareForBuild;
PreBuildEvent;
ResolveReferences;
PrepareResources;
ResolveKeySource;
Compile;
ExportWindowsMDFile;
UnmanagedUnregistration;
GenerateSerializationAssemblies;
CreateSatelliteAssemblies;
GenerateManifests;
GetTargetPath;
PrepareForRun;
UnmanagedRegistration;
IncrementalClean;
PostBuildEvent
</CoreBuildDependsOn>
</PropertyGroup>
<Target
Name="CoreBuild"
DependsOnTargets="$(CoreBuildDependsOn)">
<OnError ExecuteTargets="_TimeStampAfterCompile;PostBuildEvent" Condition="'$(RunPostBuildEvent)'=='Always' or '$(RunPostBuildEvent)'=='OnOutputUpdated'"/>
<OnError ExecuteTargets="_CleanRecordFileWrites"/>
</Target>
다음 표에서는 이러한 대상에 대해 설명합니다. 일부 대상은 특정 프로젝트 형식에만 적용할 수 있습니다.
목표 | 묘사 |
---|---|
빌드 전용 설정 | Visual Studio에서 프로젝트 로드 시 MSBuild를 호출할 때가 아니라 실제 빌드에 대한 설정입니다. |
PrepareForBuild | 빌드를 위한 필수 구성 요소 준비 |
빌드 전 이벤트 | 빌드하기 전에 실행할 작업을 정의하는 프로젝트의 확장 지점 |
프로젝트 참조 해결하기 | 프로젝트 종속성 분석 및 참조된 프로젝트 빌드 |
어셈블리 참조 해결 | 참조된 어셈블리를 찾습니다. |
ResolveReferences | 모든 종속성을 찾기 위한 ResolveProjectReferences 및 ResolveAssemblyReferences 구성됩니다. |
리소스를 준비하다 | 리소스 파일 처리 |
키 소스 해결 | 어셈블리에 서명하는 데 사용되는 강력한 이름 키와 ClickOnce 매니페스트에 서명하는 데 사용되는 인증서를 확인합니다. |
컴파일하다 | 컴파일러를 호출합니다. |
ExportWindowsMDFile | 컴파일러에서 생성된 WinMDModule 파일에서 WinMD 파일을 생성합니다. |
비관리 해제 등록 | 이전 빌드에서 COM Interop 레지스트리 항목 제거/정리 |
직렬화 어셈블리를 생성 | sgen.exe사용하여 XML serialization 어셈블리를 생성합니다. |
필요 시 위성 어셈블리 생성 | 리소스의 모든 고유한 문화권에 대해 하나의 위성 어셈블리를 만듭니다. |
매니페스트 생성 | ClickOnce 애플리케이션 및 배포 매니페스트 또는 네이티브 매니페스트에 생성합니다. |
GetTargetPath | 메타데이터를 사용하여 이 프로젝트에 대한 빌드 제품(실행 파일 또는 어셈블리)이 포함된 항목을 반환합니다. |
PrepareForRun | 변경된 경우 빌드 출력을 최종 디렉터리에 복사합니다. |
무관리 등록 | COM Interop 대한 레지스트리 항목 설정 |
인크리멘탈클린 (IncrementalClean) | 이전 빌드에서 생성되었지만 현재 빌드에서 생성되지 않은 파일을 제거합니다. 이는 Clean 증분 빌드에서 작동하도록 하는 데 필요합니다. |
빌드 후 이벤트 | 빌드 후 실행할 작업을 정의하는 프로젝트의 확장 지점 |
이전 표의 대상 중 대부분은 microsoft.CSharp.targets 같은 언어별 가져오기에서 찾을 수 있습니다. 이 파일은 C# .NET 프로젝트에 특정한 표준 빌드 프로세스의 단계를 정의합니다. 예를 들어 실제로 C# 컴파일러를 호출하는 Compile
대상이 포함됩니다.
사용자 구성 가능한 가져오기
표준 가져오기 외에도 빌드 프로세스를 사용자 지정하기 위해 추가할 수 있는 몇 가지 가져오기가 있습니다.
- Directory.Build.props
- Directory.Build.targets
이러한 파일은 모든 하위 폴더에 있는 프로젝트에 대한 표준 임포트에 의해 읽혀집니다. 이는 일반적으로 솔루션의 모든 프로젝트를 제어하는 설정에 대한 솔루션 수준에서 수행되지만 파일 시스템의 경우 드라이브의 루트까지 더 높을 수도 있습니다.
Directory.Build.props 파일은 Microsoft.Common.props가져오므로 해당 파일에 정의된 속성을 프로젝트 파일에서 사용할 수 있습니다. 프로젝트 파일에서 다시 정의하여 프로젝트별로 값을 사용자 지정할 수 있습니다. Directory.Build.targets 파일은 프로젝트 파일 이후에 읽습니다. 일반적으로 대상을 포함하지만 여기에서 개별 프로젝트를 다시 정의하지 않으려는 속성을 정의할 수도 있습니다.
프로젝트 파일의 사용자 지정
Visual Studio는 솔루션 탐색기, 속성 창 또는 프로젝트 속성변경할 때 프로젝트 파일을 업데이트하지만 프로젝트 파일을 직접 편집하여 직접 변경할 수도 있습니다.
프로젝트 및 솔루션의 전체 폴더에 대해 전역적으로 속성을 설정하는 Directory.Build.props 파일을 만들어 프로젝트 파일에서 프로젝트 파일에 로컬로 설정하거나 이전 섹션에서 설명한 대로 MSBuild 속성을 설정하여 많은 빌드 동작을 구성할 수 있습니다. 명령줄 또는 스크립트에 대한 임시 빌드의 경우 명령줄의 /p
옵션을 사용하여 MSBuild의 특정 호출에 대한 속성을 설정할 수도 있습니다. 설정할 수 있는 속성에 대한 자세한 내용은 공통 MSBuild 프로젝트 속성 참조하세요.
관련 콘텐츠
- 빌드를 사용자 정의하기
- Visual Studio 빌드 프로세스확장하는 방법입니다.
- MSBuild