It's quite frustrating, I have a Portable Class Library (PCL) library that had to drop .NET 4.0 in the profile to have access to the right API's "in PCL land". However, these API's do exist in .NET 4.0, such that if the exact same code is in a .NET 4.0 project it compiles just fine.
I want a minimal ongoing maintenance way to recompile the code in this PCL project to .net 4.0 so I can include it in a Nuget package.
With minimal conditional adjustments to the .csproj
, an msbuild project can be created to compile a portable library solution to produce additional .net 4.0 profile binaries.
Build.proj:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectToBuild Include="MyPortableSolution.sln">
<Properties>Configuration=Release;</Properties>
</ProjectToBuild>
<ProjectToBuild Include="MyPortableSolution.sln">
<Properties>Configuration=Release;OutputPath=bin\Release.net40\;IntermediateOutputPath=obj\Release.net40\;UseNet40=true;</Properties>
</ProjectToBuild>
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="@(ProjectToBuild)"/>
</Target>
</Project>
Make changes in two areas of MyPortableProj.csproj:
First Replace:
<TargetFrameworkProfile>Profile46</TargetFrameworkProfile>
With:
<UseNet40 Condition=" '$(UseNet40)' == '' ">false</UseNet40>
<TargetFrameworkProfile Condition="$(UseNet40) == false">Profile46</TargetFrameworkProfile>
Second Replace:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
With:
<Import Condition="$(UseNet40) == true" Project="$(SolutionDir)\refs.targets" />
<Import Condition="$(UseNet40) == true" Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Condition="$(UseNet40) == false" Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
Include a refs.targets
This is a file with the assembly references you need (edit from project to project):
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
</Project>
note: using a separate file because Visual studio parses and displays it otherwise.
msbuild Build.proj
This will create your portable lib in bin\Release
and .net 40 specific lib in bin\Release.net40
I guess there isn't a 'one size fits all' answer to this problem.
As a first step, it might be useful to try the pcl analyser in order to see how many types and methods fall outside of a 4.0 profile
- if it's only a few methods then you might be able to find a way forwards using a lower profile pcl alongside a small number of platform specific abstractions.
- but if there are a lot of incompatibilities then you may need to find some file-linking or project file transforming solution.