Visual Studio 빌드 프로세스는 프로젝트 파일로 가져온 일련의 MSBuild .targets
파일에 의해 정의됩니다. Visual Studio 프로젝트처럼 SDK를 사용하는 경우 이러한 가져오기는 암시적입니다. 이러한 가져온 파일 중 하나인 Microsoft.Common.targets를 확장하여 빌드 프로세스의 여러 지점에서 사용자 지정 작업을 실행할 수 있습니다. 이 문서에서는 Visual Studio 빌드 프로세스를 확장하는 데 사용할 수 있는 세 가지 방법을 설명합니다.
사용자 지정 대상을 만들고
BeforeTargets
및AfterTargets
특성을 사용하여 실행 시기를 지정합니다.공통 목표에서
DependsOn
에 정의된 속성을 재정의합니다.공통 대상(Microsoft.Common.targets 또는 가져오는 파일)에 정의된 특정 미리 정의된 대상을 재정의합니다.
AfterTargets 및 BeforeTargets
사용자 지정 대상에서 특성을 사용하여 AfterTargets
BeforeTargets
실행할 시기를 지정할 수 있습니다.
다음 예제에서는 특성을 사용하여 AfterTargets
출력 파일에서 작업을 수행하는 사용자 지정 대상을 추가하는 방법을 보여줍니다. 이 경우 출력 파일을 CustomOutput 폴더에 복사합니다. 이 예제는 CustomClean
특성을 사용하고 사용자 지정 정리 작업이 BeforeTargets
대상 전에 실행되도록 지정함으로써 CoreClean
대상을 사용하여 사용자 지정 빌드 작업에서 생성된 파일을 정리하는 방법을 보여줍니다.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild" AfterTargets="Build">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Text="_FilesToCopy: @(_FilesToCopy)" Importance="high"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles=
"@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean" BeforeTargets="CoreClean">
<Message Text="Inside Custom Clean" Importance="high"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files='@(_CustomFilesToDelete)'/>
</Target>
</Project>
경고
미리 정의된 대상은 SDK 가져오기를 통해 재정의되므로, 반드시 미리 정의된 대상과 다른 이름을 사용해야 합니다. 예를 들어, 여기에서 사용자 지정 빌드 대상은 CustomAfterBuild
이고, AfterBuild
이 아닙니다. 미리 정의된 대상 목록은 이 문서의 끝부분에 있는 표를 참조하세요.
DependsOn 속성 확장
빌드 프로세스를 확장하는 또 다른 방법은 속성(예DependsOn
: )을 사용하여 BuildDependsOn
표준 대상 전에 실행해야 하는 대상을 지정하는 것입니다.
이 메서드는 다음 섹션에서 논의될 미리 정의된 대상을 재정의하는 것보다 더 선호됩니다. 미리 정의된 대상 재정의는 여전히 지원되는 이전 메서드이지만 MSBuild는 대상 정의를 순차적으로 평가하므로 프로젝트를 가져오는 다른 프로젝트가 이미 재정의된 대상을 재정의하지 못하도록 방지할 수 없습니다. 예를 들어 다른 모든 프로젝트를 가져온 후 프로젝트 파일에 정의된 마지막 AfterBuild
대상은 빌드 중에 사용되는 대상이 됩니다.
DependsOn
속성을 공통 대상 전반의 DependsOnTargets
특성에서 재정의하여 대상의 의도치 않은 재정의를 방지할 수 있습니다. 예를 들어 대상에는 Build
.의 DependsOnTargets
특성 값이 "$(BuildDependsOn)"
포함됩니다. 고려할 사항은 다음과 같습니다.
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>
이 XML 조각은 대상이 실행되기 전에 Build
속성에 BuildDependsOn
지정된 모든 대상이 먼저 실행되어야 임을 나타냅니다. 속성은 BuildDependsOn
다음과 같이 정의됩니다.
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
프로젝트 파일의 끝에 BuildDependsOn
라는 속성을 선언하여 이 속성 값을 재정의할 수 있습니다. SDK 스타일 프로젝트에서는 명시적 가져오기를 사용해야 합니다. 마지막 가져오기 다음에 속성을 넣을 수 있도록 DependsOn
참조하세요. 새 속성에 이전 BuildDependsOn
속성을 포함하면 대상 목록의 시작과 끝에 새 대상을 추가할 수 있습니다. 다음은 그 예입니다.
<PropertyGroup>
<BuildDependsOn>
MyCustomTarget1;
$(BuildDependsOn);
MyCustomTarget2
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCustomTarget1">
<Message Text="Running MyCustomTarget1..."/>
</Target>
<Target Name="MyCustomTarget2">
<Message Text="Running MyCustomTarget2..."/>
</Target>
프로젝트 파일을 가져오는 프로젝트는 사용자가 만든 사용자 지정을 덮어쓰지 않고도 이러한 속성을 추가로 확장할 수 있습니다.
DependsOn 속성을 재정의하려면
재정의하려는 공통 대상에서 미리 정의된
DependsOn
속성을 식별합니다. 일반적으로 재정의된DependsOn
속성 목록은 다음 표를 참조하세요.프로젝트 파일의 끝에 있는 속성 또는 속성의 다른 인스턴스를 정의합니다. 새 속성에 원래 속성(예
$(BuildDependsOn)
: )을 포함합니다.속성 정의 전후에 사용자 지정 대상을 정의합니다.
프로젝트 파일을 빌드합니다.
일반적으로 재정의된 DependsOn 속성
속성 이름 | 추가된 대상은 이 시점 이전에 실행됩니다. |
---|---|
BuildDependsOn |
기본 빌드 진입점입니다. 전체 빌드 프로세스 전후에 사용자 지정 대상을 삽입하려는 경우 이 속성을 재정의합니다. |
RebuildDependsOn |
그 Rebuild |
RunDependsOn |
최종 빌드 출력의 실행(.EXE 경우) |
CompileDependsOn |
해당 컴파일(Compile 대상)입니다. 컴파일 단계 전후에 사용자 지정 프로세스를 삽입하려는 경우 이 속성을 재정의합니다. |
CreateSatelliteAssembliesDependsOn |
위성 어셈블리 만들기 |
CleanDependsOn |
Clean 대상(모든 중간 및 최종 빌드 출력 삭제)입니다. 사용자 지정 빌드 프로세스에서 출력을 정리하려는 경우 이 속성을 재정의합니다. |
PostBuildEventDependsOn |
PostBuildEvent 대상 |
PublishBuildDependsOn |
빌드 게시 |
ResolveAssemblyReferencesDependsOn |
**
ResolveAssemblyReferences 대상(지정된 종속성의 전이적 폐쇄를 찾기).
ResolveAssemblyReference 을(를) 참조하세요. |
예: BuildDependsOn 및 CleanDependsOn
다음 예제는 BeforeTargets
및 AfterTargets
예제와 비슷하지만, 유사한 기능을 구현하는 방법을 보여줍니다.
BuildDependsOn
를 사용하여 빌드 후 출력 파일을 복사하는 고유한 작업 CustomAfterBuild
를 추가하여 빌드를 확장하며, CustomClean
를 사용하여 해당 CleanDependsOn
작업도 추가합니다.
이 예제에서는 SDK 스타일 프로젝트입니다. 이 문서의 앞부분에 있는 SDK 스타일 프로젝트에 대한 참고 사항에서 설명한 것처럼 Visual Studio에서 프로젝트 파일을 생성할 때 사용하는 특성 대신 Sdk
수동 가져오기 메서드를 사용해야 합니다.
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);CustomAfterBuild
</BuildDependsOn>
<CleanDependsOn>
$(CleanDependsOn);CustomClean
</CleanDependsOn>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Importance="high" Text="_FilesToCopy: @(_FilesToCopy)"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles="@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean">
<Message Importance="high" Text="Inside Custom Clean"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files="@(_CustomFilesToDelete)"/>
</Target>
</Project>
요소의 순서가 중요합니다.
BuildDependsOn
및 CleanDependsOn
요소는 표준 SDK 대상 파일을 가져온 후에 나타나야 합니다.
미리 정의된 대상 덮어쓰기
공통 .targets
파일에는 빌드 프로세스의 일부 주요 대상 전후에 호출되는 미리 정의된 빈 대상 집합이 포함되어 있습니다. 예를 들어, MSBuild는 BeforeBuild
대상을 주 CoreBuild
대상 앞에 호출하고, AfterBuild
대상 뒤에 CoreBuild
대상을 호출합니다. 기본적으로 공통 대상의 빈 대상은 아무 작업도 수행하지 않지만 프로젝트 파일에서 원하는 대상을 정의하여 기본 동작을 재정의할 수 있습니다. 이 문서의 앞부분에서 설명한 메서드가 선호되지만 이 메서드를 사용하는 이전 코드가 발생할 수 있습니다.
프로젝트에서 SDK를 사용하는 경우(예 Microsoft.Net.Sdk
: 명시적 가져오기 및 암시적 가져오기에서 설명한 대로) 암시적 가져오기에서 명시적 가져오기로 변경해야 합니다.
미리 정의된 대상을 덮어쓰려면
프로젝트에서
Sdk
특성을 사용하는 경우, 명시적으로 가져오기 구문으로 바꿉니다. 명시적 및 암시적 가져오기를 참조하세요.재정의하려는 공통 대상에서 미리 정의된 대상을 식별합니다. 안전하게 재정의할 수 있는 대상의 전체 목록은 다음 표를 참조하세요.
프로젝트 파일의 끝 부분에서 명시적 SDK 가져오기 직후 및
</Project>
태그 바로 앞에 대상을 정의합니다. 다음은 그 예입니다.<Project> <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /> ... <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /> <Target Name="BeforeBuild"> <!-- Insert tasks to run before build here --> </Target> <Target Name="AfterBuild"> <!-- Insert tasks to run after build here --> </Target> </Project>
최상위
Sdk
요소의Project
특성이 제거되었습니다.프로젝트 파일을 빌드합니다.
미리 정의된 대상 테이블
다음 표는 재정의할 수 있는 공통 대상의 모든 대상을 나타냅니다.
대상 이름 | 설명 |
---|---|
BeforeCompile , AfterCompile |
이러한 대상 중 하나에 삽입된 작업은 코어 컴파일이 완료되기 전이나 후에 실행됩니다. 대부분의 사용자 지정은 이러한 두 대상 중 하나에서 수행됩니다. |
BeforeBuild , AfterBuild |
이러한 대상 중 하나에 삽입된 작업은 빌드의 다른 모든 항목 앞이나 뒤에 실행됩니다.
메모:BeforeBuild 대부분의 프로젝트 파일 끝에 있는 주석에 대상과 AfterBuild 대상이 이미 정의되어 있으므로 빌드 전 이벤트와 빌드 후 이벤트를 프로젝트 파일에 쉽게 추가할 수 있습니다. |
BeforeRebuild , AfterRebuild |
이러한 대상 중 하나에 삽입된 작업은 핵심 다시 빌드 기능이 호출되기 전이나 후에 실행됩니다.
Microsoft.Common.targets의 대상 실행 순서는 다음과 BeforeRebuild Clean Build AfterRebuild 같습니다. |
BeforeClean , AfterClean |
이러한 대상 중 하나에 삽입된 작업은 핵심 정리 기능이 호출되기 전이나 후에 실행됩니다. |
BeforePublish , AfterPublish |
이러한 대상 중 하나에 삽입된 작업은 핵심 게시 기능이 호출되기 전이나 후에 실행됩니다. |
BeforeResolveReferences , AfterResolveReferences |
이러한 대상 중 하나에 삽입된 작업은 어셈블리 참조가 해결되기 전이나 후에 실행됩니다. |
BeforeResGen , AfterResGen |
이러한 대상 중 하나에 삽입된 작업은 리소스가 생성되기 전이나 후에 실행됩니다. |
빌드 시스템 및 .NET SDK에는 더 많은 대상이 있습니다. MSBuild 대상( SDK 및 기본 빌드 대상)을 참조하세요.
사용자 지정 대상에 대한 모범 사례
속성 DependsOnTargets
과 BeforeTargets
둘 다 대상이 다른 대상 앞에 실행되도록 지정할 수 있지만 서로 다른 시나리오에서 둘 다 필요합니다. 종속성 요구 사항이 지정되는 대상 방식이 다릅니다. 사용자 고유의 대상만 제어할 수 있으며 시스템 대상 또는 기타 가져온 대상을 안전하게 수정할 수 없으므로 선택한 메서드를 제약할 수 있습니다.
사용자 지정 대상을 작성할 때 다음 일반 지침에 따라 대상이 의도한 순서대로 실행되도록 합니다.
DependsOnTargets
특성을 사용하여 대상이 실행되기 전에 수행해야 하는 대상을 지정합니다. 제어하는 대상 체인의 경우 각 대상은 체인DependsOnTargets
의 이전 멤버를 지정할 수 있습니다.제어할 수 없는 대상을 먼저 실행해야 할 때
BeforeTargets
를 사용하세요(예를 들어, 빌드 초기에 실행해야 하는 대상을 위한BeforeTargets="PrepareForBuild"
와 같이 사용).귀하가 제어하지 않는 대상 중 필요한 출력의 사용 가능성을 보장하는 모든 대상에
AfterTargets
를 사용합니다. 예를 들어 참조 목록을 수정할 항목을 지정AfterTargets="ResolveReferences"
합니다.이러한 항목을 조합하여 사용할 수 있습니다. 예:
DependsOnTargets="GenerateAssemblyInfo" BeforeTargets="BeforeCompile"
.
명시적 및 암시적 가져오기
Visual Studio에서 생성된 프로젝트는 일반적으로 프로젝트 요소의 Sdk
특성을 사용합니다. 이러한 유형의 프로젝트를 SDK 스타일 프로젝트라고합니다. MSBuild 프로젝트 SDK 사용참조하세요. 예제는 다음과 같습니다.
<Project Sdk="Microsoft.Net.Sdk">
프로젝트에서 특성을 사용하는 Sdk
경우 두 개의 가져오기가 암시적으로 추가되고, 하나는 프로젝트 파일의 시작 부분에, 다른 하나는 끝에 추가됩니다.
암시적 가져오기는 다음과 같은 import 문을 요소 뒤 Project
의 프로젝트 파일의 첫 번째 줄로 사용하는 것과 같습니다.
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
및 다음 import 문을 프로젝트 파일의 마지막 줄로 지정합니다.
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
이 구문을 명시적 SDK 가져오기라고 합니다. 이 명시적 구문을 사용하는 경우 프로젝트 요소의 Sdk
특성을 생략해야 합니다.
암시적 SDK 가져오기는 다음과 같이 이전 프로젝트 파일에서 일반적인 구문인 특정 "공통" .props
또는 .targets
파일을 가져오는 것과 같습니다.
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
및
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
이러한 이전 참조는 이 섹션의 앞부분에 표시된 명시적 SDK 구문으로 바꿔야 합니다.
명시적 SDK 구문을 사용하면 첫 번째 가져오기 전이나 최종 SDK 가져오기 후에 고유한 코드를 추가할 수 있습니다. 즉, 가져온 파일에 적용되는 .props
첫 번째 가져오기 전에 속성을 설정하여 동작을 변경할 수 있으며, 최종 가져오기 후에 SDK .targets
파일 중 하나에 정의된 대상을 재정의할 수 있습니다. 이 메서드를 사용하여 BeforeBuild
또는 AfterBuild
를 다음에 설명한 대로 재정의할 수 있습니다.
다음 단계
빌드를 사용자 지정하기 위해 MSBuild를 사용하여 수행할 수 있는 작업은 훨씬 더 많습니다. 을 참조하여을 사용자 지정합니다.