使用.NET Standard和便携式库的.NET多目标MSBuild 15

4
转到.NET标准版本后,您的源代码可能与便携式库相同,但支持的平台可能不同。
例如,.NET Standard 1.6 可能是从可移植 Profile47 中获得您的API的最低版本。Profile47 支持 .Net 4.5或更高版本,但 .NET Standard 1.6 仅支持 4.6.1及更高版本
通过新的多目标与新的 msbuild 15 csproj/fsproj (也是VS2017),可以同时编译便携式库和.NET标准版本,以使转换更容易。
2个回答

6
是的,但与使用.net45.net40交叉编译.netstandard一样明显是不可能的,因为它们并不是易于预定义您的可移植库的简单标识符。
在新的SDK的Microsoft.NET.TargetFrameworkInference.targets中,它说:
对于不支持推断的情况,可以如下明确指定标识符、版本和配置文件:
   <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>

目标框架配置文件,你可以从旧的csproj/fsproj中获取。这是你可移植库的配置文件标识符。你也可以在Nuget目标框架中查找。

目标框架标识符很容易,它是.NETPortable

目标框架配置文件可能也可以从旧的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的最新版本,但似乎想在别名中的portable中添加TargetFrameworkVersion。因此,对于Profile47,它实际上应该是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# 示例

*注意:为了运行此fsproj文件,F#需要Mac上的beta版本Mono或Visual Studio 2017 preview 15.3。另外,与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>

4
之前的回答是准确的,但并不足够。您需要参考可移植语言目标以获得正确的行为。还可能有其他SDK参考,您可能需要隐式定义的 ifdef ,如 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 文件会是什么样子呢? - jbtule
1
这是它的样子: - Claire Novotny
1
很酷,我会在我的几个项目上再次检查一下,然后将其标记为答案! - jbtule
1
唯一需要注意的是,它对可移植性中使用的 TFM 有特定要求 - 它必须是有效的组合,因为 TFM 不是任意的。它们必须映射到此处枚举的配置文件之一。字符串中它们的顺序并不重要。: https://portablelibraryprofiles.stephencleary.com/ - Claire Novotny
我认为这些与便携式类库的完整名称相同,请参见此处:https://learn.microsoft.com/en-us/nuget/schema/target-frameworks - jbtule
是的,同一个列表。 - Claire Novotny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接