【问题标题】:.NET Multi-Target with .NET Standard and Portable Library MSBuild 15.NET 多目标与 .NET Standard 和便携式库 MSBuild 15
【发布时间】:2017-07-07 20:53:20
【问题描述】:

移植到 .NET 标准版本,您的源可能与可移植库相同,但支持的平台可能不一样。

例如,.NET standard 1.6 可能是可从便携式Profile47 获得您的 api 的最低版本。 Profile47 支持.net 4.5 或更高版本,坚果.NET Standard 1.6 仅支持4.6.1 及更高版本

使用新的 msbuild 15 csproj/fsproj (也是 VS2017) 的新多目标,是否可以同时为 Portable Library 进行编译strong> 和 .Net Standard 以使过渡更容易?

【问题讨论】:

    标签: c# f# visual-studio-2017 portable-class-library msbuild-15


    【解决方案1】:

    是的,但它并不像交叉编译 .netstandard.net45.net40 那样明显,因为对于预定义的可移植库来说,这并不容易命名。

    在新 sdk 的 Microsoft.NET.TargetFrameworkInference.targets 中写着:

    对于不支持推理的情况,标识符、版本和 profile 可以明确指定如下:

       <PropertyGroup>
         <TargetFrameworks>portable-net451+win81;xyz1.0</TargetFrameworks>
       <PropertyGroup>
       <PropertyGroup Condition="'$(TargetFramework)' == 'portable-net451+win81'">
         <TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
         <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
         <TargetFrameworkProfile>Profile44</TargetFrameworkProfile>
       </PropertyGroup>
       <PropertyGroup Condition="'$(TargetFramework)' == 'xyz1.0'">
         <TargetFrameworkIdentifier>Xyz</TargetFrameworkVersion>
       <PropertyGroup>
    

    TargetFrameworkProfile 您可以从旧的 csproj/fsproj 中获得它。那是您的便携式库的配置文件标识符。您也可以从Nuget Target Frameworks 查找。

    TargetFrameworkIdentifier 很简单,就是.NETPortable

    TargetFrameworkProfile 可能也可以从您的旧 csproj/fsprog 中获取。但您也可以检查C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\ 并检查v4.0v4.5v4.6 配置文件目录并找到您的配置文件。这些目录的列表如下:

    v4.0

    Profile1/    Profile143/  Profile2/    Profile3/    Profile4/   Profile6/
    Profile102/  Profile147/  Profile225/  Profile328/  Profile41/  Profile88/
    Profile104/  Profile154/  Profile23/   Profile336/  Profile42/  Profile92/
    Profile131/  Profile158/  Profile24/   Profile344/  Profile46/  Profile95/
    Profile136/  Profile18/   Profile240/  Profile36/   Profile47/  Profile96/
    Profile14/   Profile19/   Profile255/  Profile37/   Profile5/
    

    v4.5

    Profile111/  Profile259/  Profile49/  Profile7/  Profile75/  Profile78/
    

    v4.6

    Profile151/  Profile157/  Profile31/  Profile32/  Profile44/  Profile84/
    

    您是否为便携式目标选择了绰号?是也不是,自动打包 nuget 很重要,因此最好使用 Nuget Target Frameworks 中的值,但要注意一点。我不确定这是否是因为最新版本的 nuget,但它似乎希望将 TargetFrameworkVersion 添加到名称中的 portable 中。所以对于Profile47,即v4.0,实际上应该是portable40-net45+sl5+win8

    另一个添加编译器定义的项目,您可能会发现使用 DefineConstants 很有用。您可以随意制作它,它在历史上一直是大写的 PROFILEXXX,只需将其添加到条件组即可。

    <DefineConstants>$(DefineConstants);PROFILE47</DefineConstants>
    

    最后要注意的是,没有提供默认的参考,因此您必须添加自己的。

    <ItemGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8'">
      <Reference Include="System" />
      <Reference Include="System.Core" />
      <Reference Include="System.Windows" />
    </ItemGroup>
    

    CSharp 示例

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFrameworks>netstandard1.6;portable40-net45+sl5+win8</TargetFrameworks>
        <Description>YOUR DESCRIPTION</Description>
        <Company>YOUR COMPANY</Company>
        <Authors> YOUR AUTHORS </Authors>
        <Copyright>YOUR COPYRIGHT</Copyright>
        <AssemblyVersion>YOUR VERSION</AssemblyVersion>
        <FileVersion>YOUR VERSION</FileVersion>
        <PackageProjectUrl>YOUR PROJECT URL</PackageProjectUrl>
        <PackageLicenseUrl>YOUR LICENSE</PackageLicenseUrl>
        <PackageTags>YOUR TAGS</PackageTags>
        <IncludeSymbols>True</IncludeSymbols>
        <IncludeSource>True</IncludeSource>
        <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
        <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
        <Version>YOUR NUGET VERSION</Version>
      </PropertyGroup>
    
      <PropertyGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8'">
         <TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
         <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
         <TargetFrameworkProfile>Profile47</TargetFrameworkProfile>
         <DefineConstants>$(DefineConstants);PROFILE47</DefineConstants>
       </PropertyGroup>
    
      <ItemGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8'">
        <Reference Include="System" />
        <Reference Include="System.Core" />
        <Reference Include="System.Windows" />
      </ItemGroup>
    
    </Project>
    

    F# 示例

    *警告:F# 需要 Mac 版 Mono 或 Visual Studio 2017 预览版 15.3 目前用于此 fsproj。此外,从 examples 的更改包括对 FSharp.Compiler.ToolsFSharp.Core 4.1 的 PackageReference 的最新支持的 FSharp 版本(这是相对较新的版本)。

    <Project Sdk="FSharp.NET.Sdk;Microsoft.NET.Sdk" ToolsVersion="15.0">
    
      <PropertyGroup>
        <TargetFrameworks>netstandard1.6;portable40-net45+sl5+win8</TargetFrameworks>
        <Description>YOUR DESCRIPTION</Description>
        <Company>YOUR COMPANY</Company>
        <Authors> YOUR AUTHORS </Authors>
        <Copyright>YOUR COPYRIGHT</Copyright>
        <AssemblyVersion>YOUR VERSION</AssemblyVersion>
        <FileVersion>YOUR VERSION</FileVersion>
        <PackageProjectUrl>YOUR PROJECT URL</PackageProjectUrl>
        <PackageLicenseUrl>YOUR LICENSE</PackageLicenseUrl>
        <PackageTags>YOUR TAGS</PackageTags>
        <IncludeSymbols>True</IncludeSymbols>
        <IncludeSource>True</IncludeSource>
        <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
        <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
        <Version>YOUR NUGET VERSION</Version>
      </PropertyGroup>
    
      <PropertyGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8'">
         <TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
         <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
         <TargetFrameworkProfile>Profile47</TargetFrameworkProfile>
         <DefineConstants>$(DefineConstants);PROFILE47</DefineConstants>
       </PropertyGroup>
    
      <ItemGroup Condition="'$(TargetFramework)'=='portable40-net45+sl5+win8'">
        <Reference Include="System" />
        <Reference Include="System.Core" />
        <Reference Include="System.Windows" />
      </ItemGroup>
    
      <ItemGroup>
        <PackageReference Include="FSharp.Core" Version="4.1.*" />
        <PackageReference Include="FSharp.Compiler.Tools" Version="4.1.*" PrivateAssets="All" 
        />
        <PackageReference Include="FSharp.NET.Sdk" Version="1.0.*" PrivateAssets="All" 
        />
      </ItemGroup>
    
      <ItemGroup>
        <Compile Include="YourModule1.fs" />
        <Compile Include="YourModule2.fs" />
      </ItemGroup>
    
    </Project>
    

    【讨论】:

      【解决方案2】:

      先前的答案是准确的,但实际上还不够。您需要参考可移植语言目标以获得正确的行为。可能还有其他 SDK 引用,您可能希望隐式定义 ifdefs,如 PROFILE328

      我编写了一个 NuGet 包,您可以将其添加到您的项目中,在这里“做正确的事”:

      https://github.com/onovotny/MSBuildSdkExtras

      编辑:csproj 看起来像这样:

      <Project Sdk="Microsoft.NET.Sdk">
      
        <PropertyGroup>
          <TargetFrameworks>netstandard1.6;portable-net45+sl5+win8</TargetFrameworks>
          <Description>YOUR DESCRIPTION</Description>
          <Company>YOUR COMPANY</Company>
          <Authors> YOUR AUTHORS </Authors>
          <Copyright>YOUR COPYRIGHT</Copyright>
          <AssemblyVersion>YOUR VERSION</AssemblyVersion>
          <FileVersion>YOUR VERSION</FileVersion>
          <PackageProjectUrl>YOUR PROJECT URL</PackageProjectUrl>
          <PackageLicenseUrl>YOUR LICENSE</PackageLicenseUrl>
          <PackageTags>YOUR TAGS</PackageTags>
          <IncludeSymbols>True</IncludeSymbols>
          <IncludeSource>True</IncludeSource>
          <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
          <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
          <Version>YOUR NUGET VERSION</Version>
        </PropertyGroup>
      
        <ItemGroup>
          <PackageReference Include="MSBuild.Sdk.Extras" Version="1.0.5" PrivateAssets="all" />
        </ItemGroup>
      
        <Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />
      </Project>
      

      【讨论】:

      • 那么如果我使用你的 NuGet 包,那么我的 csproj 会是什么样子?
      • 这是它的样子:
      • 酷,我将在我的几个项目中仔细检查这个问题,然后将其标记为答案!
      • 唯一的“陷阱”是它对您在便携式设备中使用的 TFM 的特殊性 - 它必须是有效的组合,因为 TFM 不是任意的。他们必须映射到此处列举的配置文件之一。它们在字符串中的顺序无关紧要。:portablelibraryprofiles.stephencleary.com
      • 我假设与此处的可移植类库全名相同:docs.microsoft.com/en-us/nuget/schema/target-frameworks
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多