First thing, it's recommended to target both .NET Framework and .NET Core in the compiler project.
For Core MSBuild, the compiler needs to be invoked through dotnet, which can be done using a script. This is how Roslyn and the F# compiler do it. There are two scripts, one for Windows (something like RunCompiler.cmd), like this:
@echo off dotnet %~dp0\compiler.dll %*
And another script for Unix (something like RunCompiler), like this:
#!/bin/sh THISDIR=$(dirname $0) dotnet $THISDIR/compiler.dll "$@"
The compiler task, something like Compiler, which extends ToolTask, is compiled to a separate assembly, which ships with the compiler package (where the scripts are shipped too). To allow using a different version of the compiler by installing that package, the tool path should be included like this (assuming that the .NET Core binaries are in the netcoreapp folder and the .NET Framework ones are in the win folder, in the same directory as the targets file):
<Choose> <When Condition="'$(MSBuildRuntimeType)' == 'Core'"> <PropertyGroup> <CompilerToolPath>$(MSBuildThisFileDirectory)netcoreapp\</CompilerToolPath> <CompilerToolExeCondition="'$(OS)' == 'Windows_NT'">RunCompiler.cmd</CompilerToolExe> <CompilerToolExeCondition="'$(OS)' != 'Windows_NT'">RunCompiler</CompilerToolExe> </PropertyGroup> </When> <Otherwise> <PropertyGroup> <CompilerToolPath>$(MSBuildThisFileDirectory)win\</CompilerToolPath> <CompilerToolExe>compiler.exe</CompilerToolExe> </PropertyGroup> </Otherwise> </Choose> <Target Name="MakeCompilerScriptsExecutable" BeforeTargets="CoreCompile" Condition="'$(MSBuildRuntimeType)' == 'Core' AND '$(OS)' != 'Windows_NT'"> <Exec Command="chmod +x '$(CompilerToolPath)/$(CompilerToolExe)'" /> </Target> <UsingTask TaskName="Compiler.Tasks.Compiler" AssemblyFile="Compiler.Tasks.dll" />
The task is then invoked in CoreCompile like this:
<Compiler Parameter1="$(Parameter1)" ToolPath="$(CompilerToolPath)" ToolExe="$(CompilerToolExe)" />