.Net Core迁移到MSBuild平台(二)

一、前言

在上一篇文章.Net Core迁移到MSBuild的多平台编译问题中,简单的讲了下新的项目配置文件中的节点配置,这篇我将用一些例子来详细讲下从project.json迁移到msbuild过程的节点配置。做过完整迁移新项目配置文件的朋友,肯定会觉得新的项目配置文件Msbuild的配置太扯了,虽然能直接编辑项目文件,但整个配置文件中没有了像project.json中的智能提示,当你在打开文件后你就会发现以前很轻松能写出来的json配置,现在已经什么都写不出来了,而且也没有文档可以参考,一般的情况下,往往开发人员就会关掉项目文件,打开NuGet管理器来进行包引用,但是这真的够用吗?不是所有的配置都能用可视化的方法来完成。

二、XML定义

新的.csproj是基于xml格式的,下面介绍下project.json与.csproj文件的差异定义的例子:

项目名称 (ProjectName)#

Copy
{ "name": "MyProjectName" }

在csproj的配置中并没有对应的定义,它只会有项目文件名相同如:MyProjectName.csproj

程序集版本 (Version)#

Copy
{ "version": "1.0.0-alpha-*" }
Copy
<PropertyGroup> <VersionPrefix>1.0.0</VersionPrefix> <VersionSuffix>alpha</VersionSuffix> </PropertyGroup>

当然也可以只使用Version来定义:

Copy
<PropertyGroup> <Version>1.0.0-alpha</Version> </PropertyGroup>

程序集描述#

Copy
{ "authors": [ "Anne", "Bob" ], "company": "Contoso", "language": "en-US", "title": "My library", "description": "This is my library.\r\nAnd it's really great!", "copyright": "Nugetizer 3000", "userSecretsId": "xyz123" }
Copy
<PropertyGroup> <Authors>Anne;Bob<Authors> <Company>Contoso<Company> <NeutralLanguage>en-US</NeutralLanguage> <AssemblyTitle>My library</AssemblyTitle> <Description>This is my library. And it's really great!</Description> <Copyright>Nugetizer 3000</Copyright> <UserSecretsId>xyz123</UserSecretsId> </PropertyGroup>

frameworks (单目标框架)#

Copy
"frameworks": { "netcoreapp1.0": {} }
Copy
<PropertyGroup> <TargetFramework>netcoreapp1.0</TargetFramework> </PropertyGroup>

frameworks (多目标框架)#

Copy
"frameworks": { "netcoreapp1.0": {}, "net451": {} }
Copy
<PropertyGroup> <TargetFrameworks>netcoreapp1.0;net451</TargetFrameworks> </PropertyGroup>

dependencies (框架依赖)#

Copy
"dependencies": { "Microsoft.AspNetCore": "1.1.0" }
Copy
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore" Version="1.1.0" /> </ItemGroup>

不同目标框架的依赖 (Per-framework dependencies)#

Copy
{ "framework": { "net451": { "dependencies": { "System.Collections.Immutable": "1.3.1" } }, "netstandard1.5": { "dependencies": { "Newtonsoft.Json": "9.0.1" } } } }
Copy
<ItemGroup Condition="'$(TargetFramework)'=='net451'"> <PackageReference Include="System.Collections.Immutable" Version="1.3.1" /> </ItemGroup> <ItemGroup Condition="'$(TargetFramework)'=='netstandard1.5'"> <PackageReference Include="Newtonsoft.Json" Version="9.0.1" /> </ItemGroup>

imports (兼容导入)#

Copy
{ "dependencies": { "xxx": "1.0-pre001" }, "frameworks": { "netcoreapp1.0": { "imports": [ "dnxcore50", "dotnet" ] } } }
Copy
<PropertyGroup> <PackageTargetFallback>dnxcore50;dotnet</PackageTargetFallback> </PropertyGroup> <ItemGroup> <PackageReference Include="xxx" Version="1.0-pre001" /> </ItemGroup>

依赖类型 (dependency type)#

type: build#

Copy
{ "dependencies": { "Microsoft.EntityFrameworkCore.Design": { "version": "1.1.0", "type": "build" } } }
Copy
<ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.0" PrivateAssets="All" /> </ItemGroup>

type: platform#

Copy
{ "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0", "type": "platform" } } }

在*.csproj项目配置文件中没有对应的配置节点,只有目标框架定义:

Copy
<TargetFramework>netcoreapp1.1</TargetFramework>

之前想要编译出独立发布的可执行文件,就需要把 "type": "platform"节点删除掉。

独立发布定义 (runtimes)#

Copy
{ "runtimes": { "win7-x64": {}, "osx.10.11-x64": {}, "ubuntu.16.04-x64": {} } }
Copy
<PropertyGroup> <RuntimeIdentifiers>win7-x64;osx.10-11-x64;ubuntu.16.04-x64</RuntimeIdentifiers> </PropertyGroup>

现在想生成独立发布版本,只需要在项目配置中定义RuntimeIdentifiers节点,并运行如下命令:

Copy
dotnet publish --framework netcoreapp1.0 --runtime osx.10.11-x64

DOTNET CLI工具 (tools)#

Copy
{ "tools": { "Microsoft.EntityFrameworkCore.Tools.DotNet": "1.0.0-*" } }
Copy
<ItemGroup> <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" /> </ItemGroup>

提示:tools下的引用,不再支持“imports”节点定义(不能兼容非dotnet core版本的tools)。

编译可执行 (emitEntryPoint)#

Copy
{ "buildOptions": { "emitEntryPoint": true } }
Copy
<PropertyGroup> <OutputType>Exe</OutputType> </PropertyGroup>
Copy
{ "buildOptions": { "emitEntryPoint": false } }
Copy
<PropertyGroup> <OutputType>Library</OutputType> </PropertyGroup>

程序集强命名签名 (keyFile)#

Copy
{ "buildOptions": { "keyFile": "MyKey.snk" } }
Copy
<PropertyGroup> <AssemblyOriginatorKeyFile>MyKey.snk</AssemblyOriginatorKeyFile> <SignAssembly>true</SignAssembly> <PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign> </PropertyGroup>

其它编译设置#

Copy
{ "buildOptions": { "warningsAsErrors": true, "nowarn": ["CS0168", "CS0219"], "xmlDoc": true, "preserveCompilationContext": true, "outputName": "Different.AssemblyName", "debugType": "portable", "allowUnsafe": true, "define": ["TEST", "OTHERCONDITION"] } }
Copy
<PropertyGroup> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <NoWarn>$(NoWarn);CS0168;CS0219</NoWarn> <GenerateDocumentationFile>true</GenerateDocumentationFile> <PreserveCompliationContext>true</PreserveCompliationContext> <AssemblyName>Different.AssemblyName</AssemblyName> <DebugType>portable</DebugType> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <DefineConstants>$(DefineConstants);TEST;OTHERCONDITION</DefineConstants> </PropertyGroup>

打包设置 (packOptions)#

Copy
{ "packOptions": { "summary": "A bundle of cats", "tags": ["hyperscale", "cats"], "owners": [ "Nate", "Jenna" ], "releaseNotes": "Version 1.0", "iconUrl": "https://icons.com/awesomeness.png", "projectUrl": "https://github.com/natemcmaster", "licenseUrl": "https://www.apache.org/licenses/LICENSE-2.0", "requireLicenseAcceptance": false, "repository": { "type": "git", "url": "https://github.com/natemcmaster/natemcmaster.github.io" } } }
Copy
<PropertyGroup> <Description>A bundle of cats</Description> <PackageTags>hyperscale;cats</PackageTags> <PackageReleaseNotes>Version 1.0</PackageReleaseNotes> <PackageIconUrl>https://icons.com/awesomeness.png</PackageIconUrl> <PackageProjectUrl>https://github.com/natemcmaster</PackageProjectUrl> <PackageLicenseUrl>https://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl> <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance> <RepositoryType>git</RepositoryType> <RepositoryUrl>https://github.com/natemcmaster/natemcmaster.github.io</RepositoryUrl> <!-- regrettably, 'owners' does not translate to MSBuild. --> </PropertyGroup>

MsBuild脚本#

Copy
{ "scripts": { "precompile": "generateCode.cmd", "postpublish": [ "obfuscate.cmd", "removeTempFiles.cmd" ] } }
Copy
<Target Name="MyPreCompileTarget" BeforeTargets="Build"> <Exec Command="generateCode.cmd" /> </Target> <Target Name="MyPostCompileTarget" AfterTargets="Publish"> <Exec Command="obfuscate.cmd" /> <Exec Command="removeTempFiles.cmd" /> </Target>

运行时设置 (runtimeOptions)#

Copy
{ "runtimeOptions": { "configProperties": { "System.GC.Server": true, "System.GC.Concurrent": true, "System.GC.RetainVM": true, "System.Threading.ThreadPool.MinThreads": 10, "System.Threading.ThreadPool.MaxThreads": 100 } } }
Copy
<PropertyGroup> <ServerGarbageCollection>true</ServerGarbageCollection> <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection> <RetainVMGarbageCollection>true</RetainVMGarbageCollection> <!-- I'm not suggesting these settings...just showing usage ;) --> <ThreadPoolMinThreads>10</ThreadPoolMinThreads> <ThreadPoolMaxThreads>100</ThreadPoolMaxThreads> </ProeprtyGroup>

当然如果你创建的是一个web项目的话,及Microsoft.NET.Sdk.Web。那么 ServerGarbageCollection设置将默认为true。

项目文件管理#

Copy
{ "buildOptions": { "compile": { "copyToOutput": "notes.txt", "include": "../Shared/*.cs", "exclude": "../Shared/Not/*.cs" }, "embed": { "include": "../Shared/*.resx" } }, "packOptions": { "include": "Views/", "mappings": { "some/path/in/project.txt": "in/package.txt" } }, "publishOptions": { "include": [ "files/", "publishnotes.txt" ] } }
Copy
<ItemGroup> <Compile Include="..\Shared\*.cs" Exclude="..\Shared\Not\*.cs" /> <EmbeddedResource Include="..\Shared\*.resx" /> <Content Include="Views\**\*" PackagePath="%(Identity)" /> <None Include="some/path/in/project.txt" Pack="true" PackagePath="in/package.txt" /> <None Include="notes.txt" CopyToOutputDirectory="Always" /> <!-- CopyToOutputDirectory = { Always, PreserveNewest, Never } --> <Content Include="files\**\*" CopyToPublishDirectory="PreserveNewest" /> <None Include="publishnotes.txt" CopyToPublishDirectory="Always" /> <!-- CopyToPublishDirectory = { Always, PreserveNewest, Never } --> <!-- you can set both copy output and publish directories--> <None Include="testasset.txt" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" /> <!-- alternatively, use nested XML attributes. They're functionally the same--> <None Include="testasset2.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToPublishDirectory>Always</CopyToPublishDirectory> </None> </ItemGroup>

单元测试#

xunit#

Copy
{ "testRunner": "xunit", "dependencies": { "dotnet-test-xunit": "<any>" } }
Copy
<ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> <PackageReference Include="xunit" Version="2.2.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" /> </ItemGroup>

mstest#

Copy
{ "testRunner": "mstest", "dependencies": { "dotnet-test-mstest": "<any>" } }
Copy
<ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> <PackageReference Include="MSTest.TestAdapter" Version="1.1.12" /> <PackageReference Include="MSTest.TestFramework" Version="1.1.11" /> </ItemGroup>

三、结语

说实话MSBuild的项目配置系统还是比较灵活的,以后整个dotnet体系的构建过程也都得到了统一。在dotnet cli中也集成了msbuild,即dotnet build。

.NET Core 开源学习群:214741894

GitHub:https://github.com/maxzhang1985/YOYOFx 如果觉还可以请Star下, 欢迎一起交流。

posted @   YOYOFx  阅读(2604)  评论(2编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· 开发者新选择:用DeepSeek实现Cursor级智能编程的免费方案
· 【译】.NET 升级助手现在支持升级到集中式包管理
· 独立开发经验谈:如何通过 Docker 让潜在客户快速体验你的系统
· Tinyfox 发生重大改版
点击右上角即可分享
微信分享提示
CONTENTS