In a previous post, I made a recommendation of additionally targeting
net461 in addition to
netstandard2.0 in certain scenarios, however one of the nice things about targeting
netstandard2.x is that on macOS you can install the .NET Core SDK, build it, and "it just works".
net4x however, when you run
dotnet build you might see this error:
error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.6.1" were not found.
And that makes a lot of sense because in order to compile for
net461 in this case, we need the reference assemblies of that framework, these are dlls that are the same as the runtime assemblies, but just the signatures, no implementation. On Windows these are called "Targeting Packs" and you would have these ship with Visual Studio, or packaged via standalone installers called "Developer Packs".
On macOS, there are 2 ways to reference these reference assemblies that I know of;
If you have Visual Studio for Mac or Rider installed, then you probably already have this installed, and otherwise, it's a good idea to get the latest stable version installed from here. You will probably be able to find the reference assemblies located under version folders within
Now the MSBuild that comes with the .NET Core SDK needs to know where to find the reference assemblies. I found a solution here, however, I'm not sure where it originates from (maybe it was from there?).
You can include a file named
netfx.props with this content, and import it into your project like this:
<Project Sdk="Microsoft.NET.Sdk"> <Import Project="netfx.props" /> <PropertyGroup> <Description>...
And now you are good to go!
An alternative approach that doesn't require having mono installed is to obtain them via nuget, however, they are not available on nuget.org as of today, there is a GitHub issue that can be tracked regarding this. They currently exist on a MyGet feed (from version 4.5 and up). These are official Microsoft packages, here's an example for 4.6.1.
First, you need to add the feed like this:
<PropertyGroup> <TargetFrameworks>net461;netstandard2.0</TargetFrameworks> <RestoreAdditionalProjectSources> https://dotnet.myget.org/F/dotnet-core/api/v3/index.json </RestoreAdditionalProjectSources> </PropertyGroup>
You may have also seen this done via
NuGet.config (which is just less cool), or you may have seen this using the
RestoreSources property, which would require you to append it to the existing source like this:
You can read more about that here.
Now we can import the package:
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' "> <PackageReference Include="Microsoft.TargetingPack.NETFramework.v4.6.1" Version="1.0.1" ExcludeAssets="All" PrivateAssets="All" /> </ItemGroup>
Finally, we need to point the
FrameworkPathOverride to the assemblies from this package:
<PropertyGroup Condition="'$(TargetFramework)'== 'net461'"> <FrameworkPathOverride>$(NuGetPackageRoot)microsoft.targetingpack.netframework.v4.6.1/1.0.1/lib/net461/</FrameworkPathOverride> </PropertyGroup>
And that's it. There is always the option of using
msbuild shipped with mono too by running it just for the
net4x tfm, and using
dotnet build for other tfms, but where's the fun in that? Let me know if you have other ways of approaching this in the comments.