Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't override the MSBuild ToolPath with a new version now the net5 MSBuild is a dotnet tool #2554

Closed
SteveGilham opened this issue Nov 16, 2020 · 6 comments

Comments

@SteveGilham
Copy link
Contributor

SteveGilham commented Nov 16, 2020

Description

MSBuildParams.ToolPath is a plain string; now that the .net5 SDK ships with an dotnet executable MSBuild.dll (and puts the facade MSBuild.exe into VisualStudio 16.8+), overriding the tool path no longer works

Repro steps

Please provide the steps required to reproduce the problem

MSBuild.build (fun p ->
    { p with
        ToolPath = "dotnet C:\Program Files\dotnet\sdk/5.0.100/MSBuild.dll" }

Desired behavior

To be able to supply a Fake.DotNet.ToolType instead

Actual behavior

Can only supply a string which is interpreted as a file path, which results in things like

-> One or more errors occurred. (Start of process 'dotnet C:\Program Files\dotnet\sdk/5.0.100/MSBuild.dll' failed.)
-> Start of process 'dotnet C:\Program Files\dotnet\sdk/5.0.100/MSBuild.dll' failed.
-> Win32Exception: The system cannot find the file specified

Known workarounds

None as yet See below

Related information

  • Operating system : linux, windows w/o Visual Studio 16.8
  • Branch: release 5.20.3
  • .NET Runtime, CoreCLR or Mono Version: net5 SDK
  • Indications of severity: Impedes CI builds when supplied machines are less than cutting edge Windows
  • Version of FAKE (4.X, 5.X): release 5.20.3
@SteveGilham
Copy link
Contributor Author

SteveGilham commented Nov 16, 2020

An approximation to the desired functionality can be achieved by replacing

MSBuild.build f proj

with something like

let (_,args) = MSBuild.buildArgs f
let cmdargs = "\"" +<path to msbuild.dll> + "\" "  + args + " " + proj
CreateProcess.fromRawCommandLine <path to dotnet.exe> cmdargs
|> Proc.run
|> <do something about error returns>

Note: a fully general workround would use BlackFox to unpick the generated command line and then use `.fromRawCommand` to ensure proper quoting

@baronfel
Copy link
Contributor

If you're using the sdk, why not use the Fake.Dotnet.Cli module to execute 'dotnet msbuild' for you and skip the assembly probing and such?

@SteveGilham
Copy link
Contributor Author

@baronfel Because I was too busy reducing to the previous problem.

Having taken a look at that API, though, it's annoying that DotNet.msbuild differs in signature from both MSBuild.build and DotNet.build. Making the change for some, but not all projects doesn't reduce to something simple like feeding an extra argument into the mix so as to be able to set a field

          ToolPath = if Option.isSome MSBuildPath
                     then ... // make dotnet executable ToolType from MSBuildPath.value
                     else p.ToolPath // presume classic path

to switch between old-style MSBuild and dotnet msbuild. There isn't even -- that I can spot -- a typesafe way to feed in build configuration to DotNet.msbuild, unlike the other cases.

I'm feeling a new issue about similar-but-different APIs lurking under all this.

@SteveGilham
Copy link
Contributor Author

Also, it turns out, "C:\Program Files\dotnet\dotnet.EXE" msbuild ... and "C:\Program Files\dotnet\dotnet.EXE" "C:\Program Files\dotnet\sdk/5.0.100/MSBuild.dll" ... are in fact two different operations; the former provokes a known problem also seen with dotnet build when building an F# project against an older compiler version via

<PackageReference Include="FSharp.Compiler.Tools" Version="10.2.3" />

on a machine with the net5 SDK & VS2019 16.8, whereas the latter, like plain msbuild on such a machine, avoids it.

@github-actions
Copy link
Contributor

There has not been any activity in this issue for the last 3 months so it will be closed in 14 days if there is no activity.

@github-actions github-actions bot added the stale label Feb 15, 2021
@SteveGilham
Copy link
Contributor Author

SteveGilham commented Feb 18, 2021

Having experimented with possible amendments to the MSBuild.build function, I have concluded that it is simplest to explicitly do this

let doMSBuild overrider dotnetOptions setParams project =
  let splitCommandLine line =
    line
    |> if Environment.isWindows
       then BlackFox.CommandLine.MsvcrCommandLine.parse
       else BlackFox.CommandLine.MonoUnixCommandLine.parse
    |> Seq.toList

  match overrider with
  | None -> MSBuild.build setParams project
  | Some dll -> let (_, args) = MSBuild.buildArgs setParams 
                let arglist = (splitCommandLine args) @ [project]
                CreateProcess.fromRawCommand dll arglist
                |> DotNet.prefixProcess dotnetOptions [dll] 
                |> Proc.run
                |> fun p -> Assert.That(p.ExitCode, Is.EqualTo 0)  // Or other exception of your choice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants