Roslyn 使用 Directory.Build.props 文件定义编译

本文告诉大家 Directory.Build.props 是什么有什么优点?如何使用 Directory.Build.props 文件定义编译

在 MSBuild 的 15 之后,也就是安装了 VisualStudio 2017 就可以使用的新功能,支持新的 csproj 格式。如何把以前的格式升级为 VisualStudio 2017 的新格式请看从以前的项目格式迁移到 VS2017 新项目格式

在 MSBuild 15 的一个新的功能就是让开发者可以自己定义项目信息放在一个文件,这个文件会在 Microsoft.Common.props 引用,而且会在csproj项目文件所在的文件夹开始寻找,只要找到存在Directory.Build.props文件就会自动导入里面的内容。

除了定义Directory.Build.props之外,还可以定义 Directory.Build.targets 文件,不同的只是这个文件是在 Microsoft.Common.targets使用。

入门

最简单的方法是在 Directory.Build.props 定义一个随意的值,通过这个值可以用来处理多个项目引用相同的版本。例如我有 3 个不同的项目,我需要把这三个项目打包,但是我需要让这三个项目的版本保持一样,这时需要怎么做?

最简单的方法是我在每个项目的项目文件里面写版本,但是我有3个项目,每次修改版本就需要修改三个文件,这样的写法感觉一点都不好。

如果我有 100 个项目,那么我一定也不想去修改。所以下面来告诉使用Directory.Build.props定义版本。

虽然上面说了很多东西,但是不要忘了,还没有创建3个项目。

首先打开宇宙第一IDE某个在i7固态打开需要10分钟的工具,使用随意的变量做3个项目

通过上面的方式创建 3 个项目 GeajoYabaFarcho,SeepoHairsarsawjoo,KawkasDrurxere现在项目可以右击打包

可以看到现在打包的版本是 1.0 ,随意打开一个项目的文件,可以看到还没指定版本

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

</Project>

现在可以尝试添加 Directory.Build.props 文件,在 sln 文件所在的文件夹创建文件,请看下图

创建的 Directory.Build.props 文件只需要写很少的代码

<Project>
  <PropertyGroup>
    <Version>1.2.0</Version>
  </PropertyGroup>
</Project>

现在才是在三个项目右击打包,可以在对应的 bin\Debug\ 的文件夹找到下面的文件

  • GeajoYabaFarcho.1.2.0.nupkg
  • KawkasDrurxere.1.2.0.nupkg
  • SeepoHairsarsawjoo.1.2.0.nupkg

在需要修改版本号的时候就只需要修改 Directory.Build.props 文件版本

好处

可以提供多个项目使用统一的设置,如上面提高的修改版本号。或者统一的输出文件夹,上面有3个项目,打包的时候是输出到3个不同的文件夹,能不能都输出到相同的文件夹?使用 Directory.Build.props 可以指定所有项目相同的输出文件夹。

怎么做呢?肯定我会这里告诉大家,不然会被打的

打开 Directory.Build.props 在里面添加下面代码

<Project>
  <PropertyGroup>
    <Version>1.2.0</Version>
    <OutputPath>$(MSBuildThisFileDirectory)bin\$(Configuration)\</OutputPath>
  </PropertyGroup>
</Project>

如果真的有看上面的代码,就会看到实际上添加的代码只有下面一句

    <OutputPath>$(MSBuildThisFileDirectory)bin\$(Configuration)\</OutputPath>

这里的$(MSBuildThisFileDirectory)就是获得当前文件所在的文件夹,也就是Directory.Build.props所在文件夹的bin文件夹

更多关于编译变量请看项目文件中的已知属性(知道了这些,就不会随便在 csproj 中写死常量啦) - walterlv

不同的项目之间可以通过快速复制Directory.Build.props的方法统一配置,很经常我在写的时候需要打包 nuget 就需要很多常用的属性,如

    <Authors>lindexi</Authors>

现在可以把这个代码写在 Directory.Build.props 放在最外层,这样创建一个新的项目可以通过这个方法复制这个文件,就不需要自己再写很多属性

还可以通过安装 Nuget 的方法自动安装添加这个文件到最顶层文件夹,这时更新属性就通过更新 Nuget 的方式

寻找方式

只需要把 Directory.Build.props 放在文件夹,就会自动去找到这个文件,使用属性。但是如果我再创建一个文件夹DeahelSuceamor在这个文件夹里创建一个项目,并且在这个文件夹放一个 Directory.Build.props 猜猜现在会使用哪个 Directory.Build.props 文件。

是不是会和 .gitignore 一样继承?骚年,想太多,自己写去吧。之后找到最靠近项目的第一个 Directory.Build.props 使用这个文件,只要找到第一个文件就不会继续从上面继续找。

$(MSBuildProjectFullPath)开始找,那么$(MSBuildProjectFullPath)是哪个文件夹?骚年,是不是没有认真看博客,本渣已经说了这个知识在项目文件中的已知属性(知道了这些,就不会随便在 csproj 中写死常量啦) - walterlv,自己点去看

例如这个项目是在D:\lindexi\GeajoYabaFarcho\DeahelSuceamor\SalisHayjuGiszea,寻找顺序是

D:\lindexi\GeajoYabaFarcho\DeahelSuceamor\SalisHayjuGiszea
D:\lindexi\GeajoYabaFarcho\DeahelSuceamor\
D:\lindexi\GeajoYabaFarcho\
D:\lindexi\
D:\

不使用这个功能

通过设置ImportDirectoryBuildTargets 为 false 可以不使用这个功能

合并多个文件

刚刚是不是告诉大家,在找到第一个 Directory.Build.props 就不会继续往上找,如果需要合并多个 Directory.Build.props 文件就需要写一些代码,这个代码有些长,例如在D:\lindexi\GeajoYabaFarcho\DeahelSuceamor文件夹下有 Directory.Build.props 文件,需要在这个文件继续引用上一层的 Directory.Build.props 文件,就需要添加下面代码

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

这个代码写在哪?就在那个需要和上一层的 Directory.Build.props 合并的 Directory.Build.props 里

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

这样写就会找到第一个 Directory.Build.props 还继续在上一层找另外一个 Directory.Build.props 文件,把两个文件的属性合并。如果有严谨看上面代码,会发现多了一个属性Version,还记得刚刚上一层的 Directory.Build.props 定义的属性?里面也包含了 Version ,如果两个 Directory.Build.props 都定义 Version 是使用哪个?

估计是来打一下,看哪个文件赢就使用哪个文件,不过在这里不需要打,因为这个值使用的是哪一个和写 Import 的地方有关,在上面的代码是处于最里层的 Directory.Build.props 赢,最后的版本就是 1.5 。但是如果使用下面的代码,就是上层的 Directory.Build.props 修改属性,最后版本是 1.2 ,因为最后出手的才是有用的。

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

因为 Import 就是导入另一个 Directory.Build.props ,如果之前已经有定义一个值,在导入时发现相同的值就替换。

参见:

https://docs.microsoft.com/en-us/visualstudio/msbuild/what-s-new-in-msbuild-15-0


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏增长技术

Eclipse工程导入到Android Studio

2161
来自专栏蓝天

两个SSH2间免密码登录

以下针对的是ssh2,而不是ssh,也不是OpenSSH。配置分两部分:一是对登录机的配置,二是对被登录机的配置,其中登录机为客户端,被登录机为服务端,也就...

931
来自专栏bboysoul

ubuntu安装gooderp终极指南

我承认以前的centos安装上有错误,这次,我重新记录一下安装过程 注意,我使用pyenv来管理python的版本

1401
来自专栏Samego开发资源

Redis数据库集群搭建 | 实践篇

2074
来自专栏向治洪

mac 搭建Android开发环境

在mac上搭建Android环境和在window上大体相同,不过就是在做环境变量配置等方面有自己独到的方式,那么我们今天就讲一下在mac系统下搭建Android...

4207
来自专栏bboysoul

在树莓派上搭建gitea

自己搭建git 服务的解决方式有很多,昨天我在服务器上搭建了gitlab,没错gitlab是很强大,功能很完全,但是安装在树莓派上太卡了,安装在我的vps上也很...

1422
来自专栏海天一树

小朋友学Python Web(2):Get和Post请求

如果你要做一个App项目,比如iOS或安卓项目,这时App和后端的项目是分离的。 此时要发网络请求,可以采用Get方式,也可以采用Post方式。 这里先介绍Ge...

1352
来自专栏mantou大数据

MacOS多版本Python切换方案

6204
来自专栏向治洪

mac 搭建Android开发环境

在mac上搭建Android环境和在window上大体相同,不过就是在做环境变量配置等方面有自己独到的方式,那么我们今天就讲一下在mac系统下搭建Android...

4289
来自专栏orientlu

linux ssh 登录管理

功能类似 xshell 这类终端管理工具,将需要登录的机器ip信息统一记录在一个host文件中,登录直接选择对应序号就好,减少重复输入ip,账号。

1993

扫码关注云+社区

领取腾讯云代金券