.NET Multi-Target с.NET Standard и переносимой библиотекой MSBuild 15
Портируя на стандартную версию.NET, вы можете быть источником, идентичным переносимой библиотеке, но поддерживаемые платформы могут и не быть.
Например .NET standard 1.6
может быть самая низкая версия, которая имеет ваш API доступен с портативного Profile47
, Profile47
поддерживает .net 4.5 или новее, гайка .NET Standard 1.6
поддерживает только 4.6.1 и более поздние версии!
С новым многоцелевым таргетингом с новым msbuild 15 csproj / fsproj (также VS2017) можно ли одновременно скомпилировать и Portable Library, и .Net Standard, чтобы упростить переход?
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>
Да, но это не так очевидно, как кросс-компиляция .netstandard
с .net45
или же .net40
как непростые названия для ваших портативных библиотек.
В новом 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>
TargetFrameworkProfile Вы получаете это от своего старого csproj/fsproj. Это идентификатор профиля вашей переносимой библиотеки. Вы также можете найти его в Nuget Target Frameworks.
TargetFrameworkIdentifier прост, это .NETPortable
TargetFrameworkProfile Возможно также может получить от вашего старого csproj/fsprog. Но вы также можете проверить C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\
и проверить v4.0
, v4.5
, а также v4.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# требует бета-версию Mono для Mac или Visual Studio 2017 Preview 15.3 в настоящее время для этого fsproj. Также изменение от примеров включает PackageReference к FSharp.Compiler.Tools
а также FSharp.Core
4.1 последние портативные поддерживаемые версии 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>