Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build multi-target solution on .NET Core on Mac or linux?

I have solution with multi-targeted csproj files:

<PropertyGroup>
  <TargetFrameworks>net45;netstandard1.6</TargetFrameworks>
</PropertyGroup>

or

<PropertyGroup>
  <TargetFrameworks>net45;netcoreapp1.1</TargetFrameworks>
</PropertyGroup>

I'm trying to build .NET Core part of this solution on Linux, but can't manage it. If I run

dotnet build

It builds all targets: netcoreapp1.1, netstandard1.6 and net45 and fails on the net45, because .NET Core does not provide .NET 4.5 platform on Linux. I tried to workaround this issue by specifying mono as a framework for building, but solution is complex and not all .NET 4.5 things are supported in mono. However this could help somebody else to avoid can't find .NETFramework v4.5 just run:

FrameworkPathOverride=/usr/lib/mono/4.5/ dotnet restore
FrameworkPathOverride=/usr/lib/mono/4.5/ dotnet build

When I run dotnet build /p:TargetFramework=netcoreapp1.1 I get alot of errors, I think because projects with netstandard1.6 was not built.

If I pass

  dotnet build /p:TargetFrameworks=netcoreapp1.1\;netstandard1.6

I get

MSBUILD : error MSB1006: Property is not valid.
Switch: netstandard1.6

How can I pass netcoreapp1.1 and netstandard1.6 target frameworks simultaneously to msbuild from command line?

I know that I can add additional property and make conditional compilation depending on it, but I don't want to change csproj to make this workaround.

like image 722
Sergey Zhukov Avatar asked Apr 22 '17 04:04

Sergey Zhukov


3 Answers

If you really don't want to even try building full framework or PCL versions on linux and just want a .net core app or .net standard library, you can modify the project file (.csproj) to only multi-target on windows and behave like a project targeting a single framework on non-windows like this:

<PropertyGroup>
  <TargetFrameworks>netcoreapp1.1;net45</TargetFrameworks>
  <TargetFrameworks Condition="'$(OS)' != 'Windows_NT'">netcoreapp1.1</TargetFrameworks>
</PropertyGroup>

This allows specifying netstandard* and netcoreapp* for non-windows individually for all projects and the .net core only versions of your app will be able to build using just plain dotnet restore / dotnet build commands.

like image 159
Martin Ullrich Avatar answered Oct 23 '22 04:10

Martin Ullrich


RefferenceAssembly package is now stable and all you have to do is to reference it after setting up all targets you need by running:

dotnet add package Microsoft.NETFramework.ReferenceAssemblies --version 1.0.0

Or manually in your project:

<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0">
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    <PrivateAssets>all</PrivateAssets>
</PackageReference>
like image 4
Ivan Temchenko Avatar answered Oct 23 '22 05:10

Ivan Temchenko


Make sure mono is up-to-date and then paste this bit of boilerplate into your project. I'm pretty confident this doesn't break the intellisense or tooling.

<PropertyGroup Condition="$(TargetFramework.StartsWith('net4')) and '$(OS)' == 'Unix'">
  <!-- When compiling .NET SDK 2.0 projects targeting .NET 4.x on Mono using 'dotnet build' you -->
  <!-- have to teach MSBuild where the Mono copy of the reference asssemblies is -->
  <!-- Look in the standard install locations -->
  <BaseFrameworkPathOverrideForMono Condition="'$(BaseFrameworkPathOverrideForMono)' == '' AND EXISTS('/Library/Frameworks/Mono.framework/Versions/Current/lib/mono')">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono</BaseFrameworkPathOverrideForMono>
  <BaseFrameworkPathOverrideForMono Condition="'$(BaseFrameworkPathOverrideForMono)' == '' AND EXISTS('/usr/lib/mono')">/usr/lib/mono</BaseFrameworkPathOverrideForMono>
  <BaseFrameworkPathOverrideForMono Condition="'$(BaseFrameworkPathOverrideForMono)' == '' AND EXISTS('/usr/local/lib/mono')">/usr/local/lib/mono</BaseFrameworkPathOverrideForMono>
  <!-- If we found Mono reference assemblies, then use them -->
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net40'">$(BaseFrameworkPathOverrideForMono)/4.0-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net45'">$(BaseFrameworkPathOverrideForMono)/4.5-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net451'">$(BaseFrameworkPathOverrideForMono)/4.5.1-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net452'">$(BaseFrameworkPathOverrideForMono)/4.5.2-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net46'">$(BaseFrameworkPathOverrideForMono)/4.6-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net461'">$(BaseFrameworkPathOverrideForMono)/4.6.1-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net462'">$(BaseFrameworkPathOverrideForMono)/4.6.2-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net47'">$(BaseFrameworkPathOverrideForMono)/4.7-api</FrameworkPathOverride>
  <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net471'">$(BaseFrameworkPathOverrideForMono)/4.7.1-api</FrameworkPathOverride>
  <EnableFrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != ''">true</EnableFrameworkPathOverride>
  <!-- Add the Facades directory.  Not sure how else to do this. Necessary at least for .NET 4.5 -->
  <AssemblySearchPaths Condition="'$(BaseFrameworkPathOverrideForMono)' != ''">$(FrameworkPathOverride)/Facades;$(AssemblySearchPaths)</AssemblySearchPaths>
</PropertyGroup>

From https://www.cafe-encounter.net/p2312/multi-targetting-net-framework-and-net-core-in-a-single-project / https://github.com/dotnet/sdk/issues/335#issuecomment-368669050

like image 2
Chris F Carroll Avatar answered Oct 23 '22 04:10

Chris F Carroll