背景
有时候我们在同一套代码基础上,我们存在多种商业/渠道/品牌,如果写死在代码里面,每次调试、打包可能需要改代码才行,那么有没有办法实现动态的输入呢?我们可以利用MsBuild的一个高级特性,自定义生成配置来实现这个需求。
工作原理
通过在包含源的根文件夹中名为Directory.Build.props
的单个文件内定义一个新属性,可以向每个项目添加该属性。在MSBuild运行时,Microsoft.Common.props
会搜索Directory.Build.props
文件的目录结构(Microsoft.Common.targets
将查找Directory.Build.targets
)。如果找到了一个文件,它将导入该文件并读取其中定义的属性。
Directory.Build.props
是用户定义文件,对目录下的项目提供自定义选项。
直白一点说:只要你的项目根目录或者父级目录存在一个自定义的
Directory.Build.props
,你的Visual Studio就会把它读取到可视化操作面板的配置清单中来,你就可以自由切换了。
自定义配置文件位置
这个很有意思,实际上自定义的Directory.Build.props
文件的位置很灵活,它可以位于项目的根目录,也可以父级,再父级,MsBuild会从你的项目目录往上一直找,找到为止,如果没找到就算了,找到了就用起来,但是需要注意,这个文件的名称必须完全是:Directory.Build.props
,大小写都不能偏差,在这个基础上,也能保障Linux下也可以用。
举个例子,如果你的项目位置是:c:\users\username\code\test\case1
,MsBuild会先往上一级目录开始找,比如c:\users\username\code\test
,找到就用,找不到继续往上一级目录c:\users\username\code
找,依此类推,找到或找不到为止。
另外,解决方案文件(.sln)所在位置和Directory.Build.props
所在位置没有关系,只和项目的位置有关系。
勤学实战
创建解决方案HelloDesktopBuildConfig
dotnet new sln -o HelloDesktopBuildConfig
cd .\HelloDesktopBuildConfig\
explorer.exe .
创建.Net Framework项目demoForNetFramework
选择C#语言
-Windows
平台-桌面
类型,选中Windows窗体应用(.Net Framework)
模板,创建名为demoForNetFramework2.0
的项目。
先试试从Visual Studio创建配置
- 进入配置管理器
- 新建配置
- 新建解决方案配置
这里我们可以选择从已有的两个配置进行复制,比如这里我从Debug
配置进行复制创建,起名为LinuxDebug
这样一个名为LinuxDebug
的配置就快速创建好了。
- 查看新建配置
我们来看看这个从Visual Studio内部创建的配置是咋回事。
我们看到,demoForNetFramework2.0.csproj
这个文件内容发生了变化。
在这个文件的Project
节点下新建了一个PropertyGroup
节点,其内容是:
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'LinuxDebug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\LinuxDebug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
在这个前面我们还看到已存在的另外两个配置:Debug
、Release
,还有个没有条件的。
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{08A34EAE-7E05-4293-A6D8-135DD99CB485}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>demoForNetFramework2._0</RootNamespace>
<AssemblyName>demoForNetFramework2.0</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
配置内容解读
目标平台(PlatformTarget)
目标平台是指将在其上运行生成项目的特定平台。
AnyCPU
应该是指代全部。x86
指定在Intel 80x86处理器或等效处理器上运行的32位Windows操作系统。x64
指定在Intel x64处理器或等效处理器上运行的64位Windows操作系统。Xbox
指定Microsoft Xbox 360平台
语言版本控制(LangVersion)
默认值:
目标框架 | version | C# 语言版本的默认值 |
---|---|---|
.NET | 6.x | C# 10 |
.NET | 5.x | C# 9.0 |
.NET Core | 3.x | C# 8.0 |
.NET Core | 2.x | C# 7.3 |
.NET Standard | 2.1 | C# 8.0 |
.NET Standard | 2.0 | C# 7.3 |
.NET Standard | 1.x | C# 7.3 |
.NET Framework | 全部 | C# 7.3 |
版本清单:
值 | 含义 |
---|---|
preview | 编译器接受最新预览版中的所有有效语言语法。 |
latest | 编译器接受最新发布的编译器版本(包括次要版本)中的语法。 |
latestMajor (default) | 编译器接受最新发布的编译器主要版本中的语法。 |
10.0 | 编译器只接受 C# 10 或更低版本中所含的语法。 |
9.0 | 编译器只接受 C# 9 或更低版本中所含的语法。 |
8.0 | 编译器只接受 C# 8.0 或更低版本中所含的语法。 |
7.3 | 编译器只接受 C# 7.3 或更低版本中所含的语法。 |
7.2 | 编译器只接受 C# 7.2 或更低版本中所含的语法。 |
7.1 | 编译器只接受 C# 7.1 或更低版本中所含的语法。 |
7 | 编译器只接受 C# 7.0 或更低版本中所含的语法。 |
6 | 编译器只接受 C# 6.0 或更低版本中所含的语法。 |
5 | 编译器只接受 C# 5.0 或更低版本中所含的语法。 |
4 | 编译器只接受 C# 4.0 或更低版本中所含的语法。 |
3 | 编译器只接受 C# 3.0 或更低版本中所含的语法。 |
ISO-2(或 2) | 编译器只接受 ISO/IEC 23270:2006 C# (2.0) 中所含的语法。 |
ISO-1(或 1) | 编译器只接受 ISO/IEC 23270:2003 C# (1.0/1.2) 中所含的语法。 |