José Pedro
José Pedro

Reputation: 1095

MSBuild - integrating a cross-platform compiler in the build

There's a compiler, and I need to integrate it in project builds in MSBuild. For that I have a task and a targets file, which calls the task.

Currently, the task is a ToolTask which will invoke the compiler, and supports command line arguments with GenerateCommandLineCommands.

The compiler is a .NET Core app, and I want to be able to use it from the dotnet tooling (.NET Core MSBuild) and Visual Studio (.NET Framework MSBuild).

  1. How should the compiler be called from the task?
  2. If I'm right, I will need a task property to know if it's Core or Full MSBuild, but then how would the compiler be executed by Core MSBuild? dotnet compiler.dll ?
  3. The task and targets should ship with the compiler as a tool nuget package?

Upvotes: 2

Views: 963

Answers (1)

José Pedro
José Pedro

Reputation: 1095

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)" />

Upvotes: 1

Related Questions