dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.21k stars 1.35k forks source link

Detect architecture-specific task assemblies and infer taskhost #6357

Open rainersigwald opened 3 years ago

rainersigwald commented 3 years ago

Today, if you have a task that is built for 32-bit or 64-bit, but does not specify architecture in its UsingTask, you get an error message:

S:\work\cross-arch-tasks\TaskUse.proj(8,5): error MSB4062: The "Task32" task
could not be loaded from the assembly
S:\work\cross-arch-tasks\Task32\bin\Debug\net472\Task32.dll. Could not load file
or assembly
'file:///S:\work\cross-arch-tasks\Task32\bin\Debug\net472\Task32.dll' or one of
its dependencies. An attempt was made to load a program with an incorrect
format. Confirm that the <UsingTask> declaration is correct, that the assembly
and all its dependencies are available, and that the task contains a public
class that implements Microsoft.Build.Framework.ITask.

This isn't very actionable.

MSBuild could examine the task assembly before loading it and infer an Architecture requirement if the assembly isn't MSIL. If we don't infer, we could at least emit a more-specific error message like

The task assembly XXX specifies the x86 architecture but the currently-loaded .NET runtime is x64. Consider adding an Architecture requirement to the UsingTask.

rainersigwald commented 3 years ago

Repro project: msbuild6357.zip

Build the solution, then build TaskUse.proj in 32- or 64-bit MSBuild. The task compiled for the other assembly will fail.

AArnott commented 3 years ago

if the assembly isn't MSIL

Strictly speaking, compiling with the x64 or x86 platforms still produces MSIL. The only change is to a flag in the PE header I think.

marcpopMSFT commented 3 years ago

@clairernovotny since you're working on the documentation we want to send out to help customers get their tasks 64bit compliant. This is probably something we should do in the 17.0 timeframe.

clairernovotny commented 3 years ago

This makes sense to me. @KathleenDollard mentioned this to me earlier today.

Forgind commented 2 years ago

Small note for anyone trying to reproduce this with the provided repro: You also have to rename Task64\Task32.csproj to Task64\Task64.csproj.

yfilipov commented 2 years ago

Hi, I have been following this issue for a while, because it is causing very serious impediments at our company.

We have created a Builder CLI for our projects that is heavily reliant on the MsBuild executable. However, we cannot upgrade our Builder to .NET 6 because of this issue, and it is coming from the Nuget.Build.Tasks.dll that is shipped with the latest version of the dotnet SDK. More specifically, it fails to load the GetRestoreSolutionProjectsTask task when trying to restore a solution:

C:\Program Files\dotnet\sdk\6.0.300\NuGet.targets(227,5): error MSB4062:
The "NuGet.Build.Tasks.GetRestoreSolutionProjectsTask" task could not be loaded from the assembly
C:\Program Files\dotnet\sdk\6.0.300\NuGet.Build.Tasks.dll. Could not load file or assembly
'NuGet.Build.Tasks, Version=6.2.0.146, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 
or one of its dependencies. An attempt was made to load a program with an incorrect format. 
Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, 
and that the task contains a public class that implements Microsoft.Build.Framework.ITask.

We cannot switch to dotnet build because we have multiple C++ projects, producing native code.

I am also aware of #5541, but that one has not been released yet as well.

Any idea on when we could expect this issue to be resolved and released? Sadly, all I am seeing lately is how the issue is getting bumped from one milestone to the next, although, at least to us, it really is a huge impediment.

Thanks!