Directory.Build.props - Centralize suas compilações
Directory.Build.props - Centralize suas compilações
O Directory.Build.props funciona quase como um arquivo csproj "normal". Você pode definir dependências padrão ou até mesmo aplicar usos implícitos. Isso é, por exemplo, muito conveniente quando você tem um projeto de teste no qual sempre deseja importar o namespace Moq e XUnit devido à sua configuração.
Como funciona?
É simples. O MSBuild passará do seu caminho csproj atual para cima até a hierarquia de arquivos e selecionará o primeiro Mais para o Directory.Build.props posterior que puder encontrar e o incluirá. Dê uma olhada na seguinte estrutura de arquivos:
src/
?? Infrastructure/
? ?? Infrastructure.csproj
?? Tools/
? ?? Tools.csproj
?? Web/
? ?? Web.csproj
?? Directoy.Build.props
Sob nosso src está diretamente o Directory.Build.props e então temos algumas pastas que contém os projetos "reais". Esses projetos "reais" importam automaticamente nosso Directory.Build.props.
Vejamos um exemplo:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="SonarAnalyzer.CSharp" Version="8.35.0.42613">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="$(SolutionDir)\stylecop.json" Link="stylecop.json" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>$(SolutionDir)\stylecop.analyzers.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<WarningLevel>5</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project>
Isso é tirado diretamente do repositório do meu blog no github: aqui
Portanto, em nosso caso, Infrastructure.csproj, Web.csproj e Tools.csproj incluirão automaticamente SonarAnalyzer.CSharp e StyleCop.Analyzers como pacote nuget. Se eu atualizar a versão no meu Directory.Build.props, todos eles serão atualizados automaticamente!
Outro exemplo: Digamos que você tenha a seguinte configuração de teste:
tests/
?? IntegrationTests/
? ?? IntegrationTest.csproj
?? TestUtilities/
? ?? TestUtilities.csproj
?? UnitTests/
? ?? UnitTest.csproj
?? Directory.Build.props
Como a natureza dos testes, você provavelmente usará uma estrutura de teste em todos os seus testes, além da mesma estrutura de simulação. Eu pessoalmente amo o XUnit por várias razões e o Moq como biblioteca de simulação. Portanto, quero usá-los em todos os meus projetos de teste. Então meu Directory.Build.props ficaria assim:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.5.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0-preview-20220131-20" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.2-pre.12" />
</ItemGroup>
<ItemGroup Label="Implicit usings">
<Using Include="FluentAssertions" />
<Using Include="Moq" />
<Using Include="Xunit" />
</ItemGroup>
</Project>
Tirado daqui
Super conveniente, não é?
Agora vamos dizer que o projeto Tools não precisa de todos esses includes e outras coisas ou em geral: Como posso excluir um projeto?. Isso é bem fácil, pois estamos usando a sintaxe normal que usaríamos em um csproj: Condition. Tomando o exemplo acima, vamos excluir o TestUtilities.csproj:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Condition="$(MSBuildProjectName) != 'TestUtilities'">
<PackageReference Include="FluentAssertions" Version="6.5.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0-preview-20220131-20" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.2-pre.12" />
</ItemGroup>
<ItemGroup Label="Implicit usings" Condition="$(MSBuildProjectName) != 'TestUtilities'">
<Using Include="FluentAssertions" />
<Using Include="Moq" />
<Using Include="Xunit" />
</ItemGroup>
</Project>
Também muito simples. Basta adicionar o nome do seu projeto sem a extensão de arquivo "csproj".
Vários diretórios.Build.props
O que acontece se tivermos vários Directory.Build.props?
tests/
?? IntegrationTests/
? ?? IntegrationTest.csproj
?? TestUtilities/
? ?? TestUtilities.csproj
?? UnitTests/
? ?? UnitTest.csproj
?? Directory.Build.props
Directory.Build.props
Agora temos outro Directory.Build.props um nível acima da pasta "tests". Bem, este não será incluído automaticamente. Você deve informar ao MSBuild que ele deve continuar a varredura. Você pode fazer isso adicionando isso ao Directory.Build.props interno (aquele em "testes").
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
Conclusão
O Directory.Build.props oferece uma ferramenta útil para centralizar dependências e configurações comuns.
Leia mais aqui na documentação da Microsoft