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


    一、前言

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

    二、XML定义

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

    项目名称 (ProjectName)

    {
      "name": "MyProjectName"
    }
    

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

    程序集版本 (Version)

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

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

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

    程序集描述

    {
      "authors": [ "Anne", "Bob" ],
      "company": "Contoso",
      "language": "en-US",
      "title": "My library",
      "description": "This is my library.
    And it's really great!",
      "copyright": "Nugetizer 3000",
      "userSecretsId": "xyz123"
    }
    
    <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 (单目标框架)

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

    frameworks (多目标框架)

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

    dependencies (框架依赖)

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

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

    {
      "framework": {
        "net451": {
          "dependencies": {
            "System.Collections.Immutable": "1.3.1"
          }
        },
        "netstandard1.5": {
          "dependencies": {
            "Newtonsoft.Json": "9.0.1"
          }
        }
      }
    }
    
    <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 (兼容导入)

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

    依赖类型 (dependency type)

    type: build

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

    type: platform

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

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

    <TargetFramework>netcoreapp1.1</TargetFramework>
    

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

    独立发布定义 (runtimes)

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

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

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

    DOTNET CLI工具 (tools)

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

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

    编译可执行 (emitEntryPoint)

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

    程序集强命名签名 (keyFile)

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

    其它编译设置

    {
      "buildOptions": {
        "warningsAsErrors": true,
        "nowarn": ["CS0168", "CS0219"],
        "xmlDoc": true,
        "preserveCompilationContext": true,
        "outputName": "Different.AssemblyName",
        "debugType": "portable",
        "allowUnsafe": true,
        "define": ["TEST", "OTHERCONDITION"]
      }
    }
    
    <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)

    {
      "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"
        }
      }
    }
    
    <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脚本

    {
      "scripts": {
        "precompile": "generateCode.cmd",
        "postpublish": [ "obfuscate.cmd", "removeTempFiles.cmd" ]
      }
    }
    
    <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)

    {
      "runtimeOptions": {
        "configProperties": {
          "System.GC.Server": true,
          "System.GC.Concurrent": true,
          "System.GC.RetainVM": true,
          "System.Threading.ThreadPool.MinThreads": 10,
          "System.Threading.ThreadPool.MaxThreads": 100
        }
      }
    }
    
    <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。

    项目文件管理

    {
      "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"
        ]
      }
    }
    
    <ItemGroup>
      <Compile Include="..Shared*.cs" Exclude="..SharedNot*.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

    {
      "testRunner": "xunit",
      "dependencies": {
        "dotnet-test-xunit": "<any>"
      }
    }
    
    <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

    {
      "testRunner": "mstest",
      "dependencies": {
        "dotnet-test-mstest": "<any>"
      }
    }
    
    <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下, 欢迎一起交流。

  • 相关阅读:
    Java连接MySql报错—— com.mysql.cj.exceptions.InvalidConnectionAttributeException
    Java——XML基础知识
    Java——多线程基础知识
    Java——线程安全的集合
    Java——集合
    dom4j——使用dom4j生成xml
    Java——用程序编译一个文件夹下所有java文件到另一个文件夹下
    Java——DOS命令窗口用命令编译文件夹下所有.java文件
    Java——删除Map集合中key-value值
    python 枚举Enum
  • 原文地址:https://www.cnblogs.com/maxzhang1985/p/6550001.html
Copyright © 2020-2023  润新知