How to dotnet build and Target net4x on macOS
Published: 2019-03-10 13:02:41

---
title: How to dotnet build and Target net4x on macOS
published: true
tags: 
canonical_url: https://stu.dev/how-to-target-net4x-on-macos/
---

In [a previous post](https://dev.to/stuartblang/net-framework-support-for-net-standard-20-5a4i-temp-slug-9523411), 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".

With `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;

### 1. Using the mono reference assemblies

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](https://www.mono-project.com/download/stable/). You will probably be able to find the reference assemblies located under version folders within `/Library/Frameworks/Mono.framework/Versions/Current/lib/mono`.

Now the MSBuild that comes with the .NET Core SDK needs to know where to find the reference assemblies. I found a [solution here](https://github.com/dotnet/sdk/issues/335#issuecomment-368669050), 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](https://github.com/Microsoft/visualfsharp/blob/24a432f03219b62fa647777a531bb7e70fa044e0/fcs/netfx.props), and import it into your project like this:

```xml
<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="netfx.props" />
  <PropertyGroup>
    <Description>...
```

And now you are good to go!

### 2. Obtain the reference assemblies via MyGet

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](https://github.com/dotnet/designs/pull/33) 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](https://dotnet.myget.org/feed/dotnet-core/package/nuget/Microsoft.TargetingPack.NETFramework.v4.6.1).

First, you need to add the feed like this:

```xml
  <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: `<RestoreSources>$(RestoreSources);...</RestoreSources>`  
You can read more about that [here](https://github.com/NuGet/Home/wiki/%5BSpec%5D-NuGet-settings-in-MSBuild#project-properties).

Now we can import the package:

```xml
 <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:

```xml
  <PropertyGroup Condition="'$(TargetFramework)'== 'net461'">
      <FrameworkPathOverride>$(NuGetPackageRoot)microsoft.targetingpack.netframework.v4.6.1/1.0.1/lib/net461/</FrameworkPathOverride>
  </PropertyGroup>
```
### Conclusion

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.