使用 Directory.Build 来消除项目文件中的重复配置

使用 Directory.Build 来消除项目文件中的重复配置

Intro

如果解决方案里的项目比较多的话,往往会有很多重复的项目属性,通常我们可以使用独立的 props 属性文件来配置公用的属性,而一般的属性文件都需要手动的 Import 到项目文件中,而 MSBuild 支持自动导入我们要介绍的 Directory.Build.props中的配置,所以通常我们可以使用 Directory.Build.props 来减少项目中重复的属性

DirectoryBuild

什么是 Directory.Build 呢?

Directory.Build 文件是放在某一个目录下,其中的配置针对这个目录下所有的项目都生效,并且 MSBuild 运行的时候会自动引入,不需要显式地在项目文件中引入,主要分成 Directory.Build.propsDirectory.Build.targets 两类,在很多开源项目包括微软的开源项目都有用到这个来简化项目配置,.props 文件是属性文件,通常定义公用的属性,导入时机较早,项目中的定义可以覆盖掉其中的配置,.targets 是目标文件,通常定义一些自定义的 MSBuild Task,导入时间稍后,可以用来覆盖项目文件中的定义

通常我只是用到 Directory.Build.props 来配置公用的属性

下面是一个项目文件中的一部分:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <LangVersion>latest</LangVersion>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
</Project>

上面 TargetFramwork/Nullable/ImplicitUsings 是一个 MSBuild 属性,需要声明在 PropertyGroup

如果一个解决方案中有很多个项目,那么这些可能就都是重复项了,这时候使用 Directory.Build.props 就会比较方便,比如说 ImplicitUsing 这一属性,这个属性是用来启用 .NET 6 里的隐式命名空间引用的,但是从 .NET 6 RC1 默认是禁用的,需要显式声明 <ImplicitUsings>enable</ImplicitUsings> 来启用,如果项目里的项目都是需要启用的,那就可以直接声明在 Directory.Build.props 中,放在项目根目录下,如下所示:

<Project>
    <PropertyGroup>
        <LangVersion>latest</LangVersion>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>
</Project>

除了 PropertyGroup 之外,我们也可以定义 <ItemGroup>,下面就是一个示例:

<Project>
    <PropertyGroup>
        <LangVersion>latest</LangVersion>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>
    <ItemGroup>
        <Using Include="WeihanLi.Common"/>
        <Using Include="WeihanLi.Common.Helpers"/>
        <Using Include="WeihanLi.Extensions"/>
    </ItemGroup>
</Project>

这样我们可以把公用的命名空间定义在 Directory.Build.props 上, MSBuild 会按目录结构依次寻找上层的 Directory.Build.props,找到第一个之后就会停止再往上寻找,下面是一个示例

c:\users\username\code\test\case1
c:\users\username\code\test
c:\users\username\code
c:\users\username
c:\users
c:\

如果项目较多可以使用多层 Directory.Build.props,下面是一个示例:

\
  MySolution.sln
  Directory.Build.props     (1)
  \src
    Directory.Build.props   (2-src)
    \Project1
    \Project2
  \test
    Directory.Build.props   (2-test)
    \Project1Tests
    \Project2Tests

所有项目 (1) 的通用属性、src 项目 (2-src) 的通用属性,以及 test 项目 (2-test) 的通用属性

前面我们提到过,MSBuild 对于指定项目找到第一个 Directory.Build.props 就会停止再向上寻找 Directory.Build.props 如果要同时使用多级 Directory.Build.props 则需要显式导入上层的 Directory.Build.props

<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />

Sample

下面我们来看一些使用示例吧

Sample1

在稍微复杂一些项目,往往会引用很多的 Nuget 包,而一些项目的版本可能是有关系的,有些包的版本是一致的,此时我们可以考虑定义一个属性,而在包版本的地方则引用这个属性

项目根目录下 Directory.Build.props 内容

<PropertyGroup>
    <LangVersion>latest</LangVersion>
    <Nullable>enable</Nullable>
    <EFVersion>6.0.0-rc.1.*</EFVersion>
</PropertyGroup>

项目文件中内容:

<ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(EFVersion)" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="$(EFVersion)" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(EFVersion)" />
</ItemGroup>

这样我们如果需要更新 EF 的版本,我们只需要更新 Directory.Build.props 文件中的 EFVersion 这个属性就可以了,详细配置可以参考:https://github.com/WeihanLi/WeihanLi.EntityFramework

Sample2

我们再来看一个多个层级使用的示例,项目结构如下所示:

Directory.Build.props
--src
--tests
--Directory.Build.props
----UnitTest
----IntegrationTest

98bdfdb18d7dc02b1726046a8febedd7.png

项目根目录下 Directory.Build.props,主要定义 package 相同的属性配置以及启用可控引用类型,隐式命名空间和公用的命名空间

<Project>
    <PropertyGroup>
        <LangVersion>latest</LangVersion>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <PackageIcon>icon.png</PackageIcon>
        <PackageTags>HTTPie http https curl rest</PackageTags>
        <GenerateDocumentationFile>false</GenerateDocumentationFile>
        <PackageLicenseExpression>MIT</PackageLicenseExpression>
        <RepositoryType>git</RepositoryType>
        <RepositoryUrl>https://github.com/WeihanLi/dotnet-httpie</RepositoryUrl>
        <PackageProjectUrl>https://github.com/WeihanLi/dotnet-httpie</PackageProjectUrl>
        <Product>dotnet-HTTPie</Product>
        <Authors>WeihanLi</Authors>
        <PackageReleaseNotes>https://github.com/WeihanLi/dotnet-httpie/tree/main/docs/ReleaseNotes.md</PackageReleaseNotes>
        <Copyright>Copyright 2021 (c) WeihanLi</Copyright>
    </PropertyGroup>
    <ItemGroup>
        <Using Include="WeihanLi.Common"/>
        <Using Include="WeihanLi.Common.Helpers"/>
        <Using Include="WeihanLi.Extensions"/>
    </ItemGroup>
</Project>

tests 目录下 Directory.Build.props,定义了测试项目公用的命名空间,并引入了上一层 Directory.Build.props 中的属性

<Project>
    <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
    <ItemGroup>
        <Using Include="FluentAssertions"/>
        <Using Include="Xunit"/>
    </ItemGroup>
</Project>

IntegrationTest 项目文件,引入自己需要的命名空间引用

<ItemGroup>
    <Using Include="HTTPie"/>
    <Using Include="HTTPie.Implement"/>
    <Using Include="HTTPie.Middleware"/>
    <Using Include="HTTPie.Models"/>
    <Using Include="HTTPie.Utilities"/>
</ItemGroup>

具体配置可以参考:https://github.com/WeihanLi/dotnet-httpie

More

使用好 Directory.Build.props 可以简化项目配置,使得项目更容易维护,如果还没用起来的可以尝试一下哈

References

  • https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?WT.mc_id=DT-MVP-5004222&view=vs-2019

  • https://github.com/WeihanLi/SparkTodo/blob/master/Directory.Build.props

  • https://github.com/WeihanLi/SamplesInPractice/tree/master/net6sample

  • https://github.com/WeihanLi/WeihanLi.EntityFramework/blob/dev/Directory.Build.props

  • https://github.com/WeihanLi/dotnet-httpie/blob/dev/Directory.Build.props

  • https://github.com/WeihanLi/dotnet-httpie/blob/dev/tests/Directory.Build.props

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: project.build.outputDirectory是Maven构建工具定义的一个属性,用于指定Maven项目构建时的输出目录,也就是编译生成的.class文件的存放路径。默认情况下,这个目录是target/classes,可以通过在pom.xml文件进行配置来修改它。在该目录下还可能包含其他的生成文件,比如资源文件等。 ### 回答2: project.build.outputDirectory文件指的是Maven项目编译输出文件夹的路径。在Maven项目,当我们进行编译时,编译的结果(如编译后的类文件、资源文件等)会被放置在指定的输出文件。这个输出文件夹的路径就是project.build.outputDirectory。 在一个标准的Maven项目,该属性的默认值是"target",也就是项目根目录下的target文件夹。当我们运行"mvn clean package"命令时,Maven会自动清理该文件夹并重新生成编译输出结果。 在Maven的项目配置文件(pom.xml),我们可以通过修改<build><directory>标签下的<outputDirectory>元素来自定义project.build.outputDirectory的路径。这对于需要将编译资源输出到其他目录的项目非常有用,比如在Web项目将编译结果输出到Web服务器的指定目录。 project.build.outputDirectory文件的存在使得项目的构建和部署更加方便和灵活。通过指定输出文件夹的路径,我们可以轻松地管理项目的编译输出结果,并将其部署到合适的位置。这对于团队协作开发和自动化构建工具的集成都提供了很大的便利。 ### 回答3: project.build.outputDirectory是Maven项目的一个配置属性,表示编译输出的目录。 在Maven项目,源代码通常位于src/main/java目录下,而编译后生成的字节码文件会被放置在target目录下。而project.build.outputDirectory就是用来定义target目录的路径的。 当我们执行mvn compile命令时,Maven会将源代码编译成字节码,并将编译后的字节码文件存放在project.build.outputDirectory指定的目录。 这个属性可以在pom.xml文件进行配置,通常默认为target目录。但也可以根据需要,修改其值,比如将编译输出目录修改为其他路径,或是将编译输出目录分为多级目录等。 在项目构建过程,编译输出目录非常重要,因为它是编译后的代码的存放位置。其他插件也可以参考此属性来定位编译后的文件。 总而言之,project.build.outputDirectory指定了Maven项目编译后输出的目录路径,并且在项目构建过程,对于编译生成的文件的存放位置起到了关键作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值