不同平臺框架項目使用同一套代碼,一次編譯生成多個框架類庫 [TOC] 需要先瞭解的東西 "msbuild" .net framework遷移至.net core,或者合併,單個項目編譯不同的框架 —— "官方文檔" 分析 使用 ".NET 可移植性分析器工具" 分析項目依賴 .NET 可移植性分析器 ...
不同平臺框架項目使用同一套代碼,一次編譯生成多個框架類庫
[TOC]
需要先瞭解的東西
分析
- 使用.NET 可移植性分析器工具分析項目依賴
- .NET 可移植性分析器工具有關博客
- 根據分析結果以及建議,到這個網站可以根據fx框架下類型名查找對應的nuget包,來替代不相容的引用
- 重新組織項目依賴,整理各個框架公共的代碼文件和其他平臺不支持的功能的代碼文件,必要時可將一個文件分成多個多個文件
- 由於我這裡已經是多個分開的項目,就省了分析代碼這一步,直接分析文件應該歸屬哪些項目,哪些獨有的
添加PropertyGroup
多目標平臺
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;net45;netstandard2.0</TargetFrameworks>
</PropertyGroup>
</Project>
編譯符號和輸出目錄設置
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Debug|AnyCPU|net45'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<DocumentationFile>..\..\Bin\net45\XCode.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Release|AnyCPU|net45'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>..\..\Bin\net45\XCode.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)'=='Debug|AnyCPU|netstandard2.0'">
<OutputPath>..\..\Bin\</OutputPath>
<DocumentationFile>..\..\Bin\netstandard2.0\XCode.xml</DocumentationFile>
<DefineConstants>TRACE;DEBUG;NETSTANDARD2_0;__CORE__</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)'=='Release|AnyCPU|netstandard2.0'">
<OutputPath>..\..\Bin\</OutputPath>
<DocumentationFile>..\..\Bin\netstandard2.0\XCode.xml</DocumentationFile>
<DefineConstants>TRACE;RELEASE;NETSTANDARD2_0;__CORE__</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Debug|AnyCPU|net40'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET4</DefineConstants>
<DocumentationFile>..\..\Bin\net40\XCode.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)|$(TargetFramework)' == 'Release|AnyCPU|net40'">
<OutputPath>..\..\Bin\</OutputPath>
<DefineConstants>TRACE;NET4</DefineConstants>
<DocumentationFile>..\..\Bin\net40\XCode.xml</DocumentationFile>
</PropertyGroup>
添加依賴
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' Or '$(TargetFramework)' == 'netstandard2.0' ">
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Management" />
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Session" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.0.0" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net40'">
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Management" />
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NewLife.Core\NewLife.Core.csproj">
<Name>NewLife.Core</Name>
</ProjectReference>
</ItemGroup>
- 如果依賴項那裡顯示感嘆號,關掉項目重新打開即可
代碼文件處理
- 將前面分析好的代碼文件分情況做排除,由於項目裡面的文件自動顯示在解決方案,不用顯式包含文件,只需要根據目標平臺做好排除即可
主副平臺項目文件處理
全部平臺都包含
- MSBuild項目文件會自動包含項目文件下麵的所有文件,不必處理
一個或多個平臺包含
- 在所有不包含的此文件的平臺的ItemGroup中移除
沒有平臺包含
- 沒有項目包含此文件為什麼還有放在項目文件夾?我也不知道,在全局ItemGroup移除即可
最後
- 生成看看還有什麼錯誤,看情況解決,比如PropertyGroup設置了文件版本信息,同時引用了
/Properties/AssemblyInfo.cs
導致報錯等等。 - 合併之前的項目文件
- 合併之後的項目文件
- 合併第一個項目的時候,簡直一團糟,本來所有項目都不包含的代碼都涌進來,有的文件只是一個項目有。合併到第二個,先做好分析,什麼文件該引用還是排除,有條理很快就完成,處理好文件引用之後一次性生成成功,沒有第一個項目合併的時候一千多個錯誤
補充
自動生成內部版本號
- 以前的寫法是在/Properties/AssemblyInfo.cs里通過
[assembly: AssemblyVersion("2.3.*")]
這樣的形式生成,但是現在預設關閉這個功能了,如果我們直接指定<AssemblyVersion>9.8.*</AssemblyVersion>
會警告錯誤,加上<Deterministic>False</Deterministic>
即可 為什麼預設關閉?請瞭解下Roslyn中的確定性構建,我不是很懂,不,是根本看不懂
其它生成方式、彙編內部版本號後面兩位的生成規則,請看使用Visual Studio時是否可以自動增加文件構建版本、Visual Studio 2017中的自動版本控制(.NET Core)、如何有一個自動遞增版本號(Visual Studio)
msbuildtasks也瞭解一下,如果要相容以前的內部版本號生成規則,可自己動手
nuget包相關
- 靜態文件如何指定複製行為等等,或許你會發現安裝nuget之後希望能編輯的文件僅僅只是一個鏈接而已,如何讓它包含在項目裡面呢,參考NuGet ContentFiles揭秘,帶回解決方案級包的討論
- PackageReference方式作為包管理格式,安裝時不支持執行install.ps1等powershell相關腳本,init.ps1在解決方案第一次安裝時可用。vs2017中,已不支持此功能,NuGet 3 - 什麼和為什麼-Powershell安裝和卸載腳本
- 關於nuget包安裝的相關行為估計都可以通過msbuild屬性或者任務來搞定,這一切都是可以通過命令行來執行的,方便跨平臺使用吧
- msbuildtasks也瞭解一下,可以代替ps1腳本完成你想做的事