다음을 통해 공유


MSBuild 인라인 작업

MSBuild 작업은 일반적으로 인터페이스를 구현하는 클래스를 컴파일하여 만듭니다 ITask . 자세한 내용은 작업참조하세요.

컴파일된 작업을 만드는 오버헤드를 방지하려면 프로젝트 파일 또는 가져온 파일에서 작업을 인라인으로 만들 수 있습니다. 작업을 호스트하기 위해 별도의 어셈블리를 만들 필요가 없습니다. 인라인 작업을 사용하면 소스 코드를 더 쉽게 추적하고 작업을 쉽게 배포할 수 있습니다. 소스 코드는 MSBuild 프로젝트 파일 또는 가져온 파일(일반적으로 파일) .targets 에 통합됩니다.

코드 작업 팩터리를 사용하여 인라인 작업을 만듭니 . 현재 개발의 경우 RoslynCodeTaskFactory를 사용하지 않고 사용해야 합니다 CodeTaskFactory. CodeTaskFactory 는 C# 버전에서 최대 4.0까지만 지원합니다.

인라인 작업은 복잡한 종속성이 필요하지 않은 작은 작업에 편리한 용도로 사용됩니다. 인라인 작업에 대한 디버깅 지원은 제한됩니다. 더 복잡한 코드를 작성하거나, NuGet 패키지를 참조하거나, 외부 도구를 실행하거나, 오류 조건을 생성할 수 있는 작업을 수행하려는 경우 인라인 작업 대신 컴파일된 작업을 만드는 것이 좋습니다. 또한 인라인 작업은 빌드할 때마다 컴파일되므로 빌드 성능에 눈에 띄는 영향을 줄 수 있습니다.

인라인 작업의 구조

인라인 작업은 UsingTask 요소에 의해 포함됩니다. 인라인 작업 및 UsingTask 인라인 작업이 포함된 요소는 일반적으로 파일에 포함 .targets 되고 필요에 따라 다른 프로젝트 파일로 가져옵니다. 다음은 아무 작업도 수행하지 않지만 구문을 보여 주는 기본 인라인 작업입니다.

 <!-- This simple inline task does nothing. -->
  <UsingTask
    TaskName="DoNothing"
    TaskFactory="RoslynCodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
    <ParameterGroup />
    <Task>
      <Reference Include="" />
      <Using Namespace="" />
      <Code Type="Fragment" Language="cs">
      </Code>
    </Task>
  </UsingTask>

UsingTask 이 예제의 요소에는 태스크와 이를 컴파일하는 인라인 작업 팩터리를 설명하는 세 가지 특성이 있습니다.

  • 이 경우 DoNothing특성은 TaskName 작업의 이름을 지정합니다.

  • 이 특성은 TaskFactory 인라인 작업 팩터리를 구현하는 클래스의 이름을 지정합니다.

  • 이 특성은 AssemblyFile 인라인 작업 팩터리의 위치를 제공합니다. 또는 특성을 사용하여 AssemblyName 일반적으로 있는 인라인 작업 팩터리 클래스의 정규화된 이름을 지정할 수 있습니다 $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll.

작업의 나머지 요소는 DoNothing 비어 있으며 인라인 작업의 순서와 구조를 설명하기 위해 제공됩니다. 전체 예제는 이 문서의 뒷부분에서 제공합니다.

  • ParameterGroup 요소는 선택적입니다. 지정하면 작업에 대한 매개 변수를 선언합니다. 입력 및 출력 매개 변수에 대한 자세한 내용은 이 문서의 뒷부분에 있는 입력 및 출력 매개 변수 를 참조하세요.

  • 요소는 Task 작업 소스 코드를 설명하고 포함합니다.

  • 요소는 Reference 코드에서 사용 중인 .NET 어셈블리에 대한 참조를 지정합니다. 이 요소를 사용하는 것은 Visual Studio에서 프로젝트에 대한 참조를 추가하는 것과 같습니다. 이 특성은 Include 참조된 어셈블리의 경로를 지정합니다. mscorlib, .NET Standard, Microsoft.Build.FrameworkMicrosoft.Build.Utilities.Core의 어셈블리뿐만 아니라 종속성으로 전이적으로 참조되는 일부 어셈블리는 없이 Reference사용할 수 있습니다.

  • 요소 Using 에는 액세스하려는 네임스페이스가 나열됩니다. 이 요소는 C#의 using 지시문과 동일합니다. 특성은 Namespace 포함할 네임스페이스를 지정합니다. 이 코드는 지시문이 허용되지 않는 메서드 본문 using 에 배치되므로 인라인 코드에 지시문을 배치 using 하는 것은 작동하지 않습니다.

ReferenceUsing 요소는 언어에 구애받지 않습니다. 인라인 작업은 Visual Basic 또는 C#으로 작성할 수 있습니다.

비고

요소에 Task 포함된 요소는 작업 팩터리(이 경우 코드 작업 팩터리)에 따라 다릅니다.

Code 요소

요소 내에 Task 표시되는 마지막 자식 요소는 요소입니다 Code . 요소는 Code 작업으로 컴파일할 코드를 포함하거나 찾습니다. 요소에 입력한 Code 내용은 작업을 작성하는 방법에 따라 달라집니다.

이 특성은 Language 코드가 작성되는 언어를 지정합니다. 허용되는 값은 cs Visual Basic의 경우 C# vb 입니다.

특성은 Type 요소에 있는 코드의 형식을 Code 지정합니다.

  • TypeClass면 요소에 Code 인터페이스에서 파생되는 클래스에 대한 코드가 ITask 포함됩니다.

  • TypeMethod면 코드는 인터페이스 메서드의 재정의를 ExecuteITask 정의합니다.

  • Type 이면 코드는 Fragment메서드의 Execute 내용을 정의하지만 서명이나 return 문은 정의하지 않습니다.

코드 자체는 일반적으로 표식과 ]]> 표식 사이에 <![CDATA[ 나타납니다. 코드는 CDATA 섹션에 있으므로 예약된 문자(예: "" 또는 "<>")를 이스케이프하는 것에 대해 걱정할 필요가 없습니다.

또는 요소의 Code 특성을 사용하여 Source 작업에 대한 코드가 포함된 파일의 위치를 지정할 수 있습니다. 소스 파일의 코드는 특성에 지정된 Type 형식이어야 합니다. 특성이 Source 있으면 기본값 Type 은 .입니다 Class. 없는 경우 Source 기본값은 .입니다 Fragment.

비고

소스 파일에서 작업 클래스를 정의할 때 클래스 이름은 해당 UsingTask 요소의 특성에 TaskName 동의해야 합니다.

HelloWorld

다음은 간단한 인라인 작업의 예입니다. HelloWorld 작업은 일반적으로 시스템 콘솔 또는 Visual Studio 출력 창인 기본 오류 로깅 디바이스에 "Hello, world!"를 표시합니다.

<Project>
  <!-- This simple inline task displays "Hello, world!" -->
  <UsingTask
    TaskName="HelloWorld"
    TaskFactory="RoslynCodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
    <ParameterGroup />
    <Task>
      <Using Namespace="System"/>
      <Using Namespace="System.IO"/>
      <Code Type="Fragment" Language="cs">
<![CDATA[
// Display "Hello, world!"
Log.LogError("Hello, world!");
]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

HelloWorld.targets라는 파일에 HelloWorld 작업을 저장한 다음, 다음과 같이 프로젝트에서 호출할 수 있습니다.

<Project>
  <Import Project="HelloWorld.targets" />
  <Target Name="Hello">
    <HelloWorld />
  </Target>
</Project>

입력 및 출력 매개 변수

인라인 작업 매개 변수는 요소의 자식 요소입니다 ParameterGroup . 모든 매개 변수는 해당 매개 변수를 정의하는 요소의 이름을 사용합니다. 다음 코드는 매개 변수 Text를 정의합니다.

<ParameterGroup>
  <Text />
</ParameterGroup>

매개 변수에는 다음 특성 중 하나 이상이 있을 수 있습니다.

  • Required 는 기본적으로 선택적 특성입니다 false . 이면 true매개 변수가 필요하며 작업을 호출하기 전에 값을 지정해야 합니다.
  • ParameterType 는 기본적으로 선택적 특성입니다 System.String . 를 사용하여 ChangeType문자열로 변환하거나 문자열에서 변환할 수 있는 항목 또는 값인 정규화된 형식으로 설정할 수 있습니다. 즉, 외부 작업으로 전달될 수 있는 모든 형식입니다.
  • Output 는 기본적으로 선택적 특성입니다 false . 이 경우 trueExecute 메서드에서 반환하기 전에 매개 변수에 값을 지정해야 합니다.

예를 들면 다음과 같습니다.

<ParameterGroup>
  <Expression Required="true" />
  <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
  <Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>

는 다음 세 가지 매개 변수를 정의합니다.

  • Expression 는 System.String 형식의 필수 입력 매개 변수입니다.

  • Files 는 필수 항목 목록 입력 매개 변수입니다.

  • Tally 는 System.Int32 형식의 출력 매개 변수입니다.

요소에 Code 특성 FragmentType 있는 Method경우 모든 매개 변수에 대해 속성이 자동으로 만들어집니다. 그렇지 않으면 속성이 작업 소스 코드에서 명시적으로 선언되어야 하며 해당 매개 변수 정의와 정확히 일치해야 합니다.

인라인 작업 디버그

MSBuild는 인라인 작업에서 원본 파일을 생성하고 임시 파일 폴더 AppData\Local\Temp\MSBuildTemp에 GUID 파일 이름을 사용하여 출력을 텍스트 파일에 씁니다. 출력은 일반적으로 삭제되지만 이 출력 파일을 유지하려면 환경 변수 MSBUILDLOGCODETASKFACTORYOUTPUT 를 1로 설정할 수 있습니다.

예제 1

다음 인라인 작업은 지정된 파일에서 토큰이 발생할 때마다 지정된 값으로 바꿉니다.

<Project>

  <UsingTask TaskName="TokenReplace" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
    <ParameterGroup>
      <Path ParameterType="System.String" Required="true" />
      <Token ParameterType="System.String" Required="true" />
      <Replacement ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Code Type="Fragment" Language="cs"><![CDATA[
string content = File.ReadAllText(Path);
content = content.Replace(Token, Replacement);
File.WriteAllText(Path, content);

]]></Code>
    </Task>
  </UsingTask>

  <Target Name='Demo' >
    <TokenReplace Path="Target.config" Token="$MyToken$" Replacement="MyValue"/>
  </Target>
</Project>

예제 2

다음 인라인 작업은 직렬화된 출력을 생성합니다. 이 예제에서는 출력 매개 변수 및 참조를 사용하는 방법을 보여 있습니다.

<Project>
  <PropertyGroup>
    <RoslynCodeTaskFactoryAssembly Condition="$(RoslynCodeTaskFactoryAssembly) == ''">$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll</RoslynCodeTaskFactoryAssembly>
  </PropertyGroup>

    <UsingTask 
    TaskName="MyInlineTask" 
    TaskFactory="RoslynCodeTaskFactory" 
    AssemblyFile="$(RoslynCodeTaskFactoryAssembly)">
    <ParameterGroup>
      <Input ParameterType="System.String" Required="true" />
      <Output ParameterType="System.String" Output="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="System.Text.Json" /> <!-- Reference an assembly -->
      <Using Namespace="System.Text.Json" />   <!-- Use a namespace -->
      <Code Type="Fragment" Language="cs">
        <![CDATA[
          Output = JsonSerializer.Serialize(new { Message = Input });
        ]]>
      </Code>
    </Task>
  </UsingTask>

  <Target Name="RunInlineTask">
    <MyInlineTask Input="Hello, Roslyn!" >
      <Output TaskParameter="Output" PropertyName="SerializedOutput" />
    </MyInlineTask>
    <Message Text="Serialized Output: $(SerializedOutput)" />
  </Target>
</Project>