-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Cannot use MSBuild API from a dotnet-CLI project tool #1097
Comments
I'll need to know more about the layout of these project tools. Who is the best person to give me a primer in order to come up with a fix? cc @eerhardt |
I'll ping you offline. |
I see two options:
The latter is how standalone applications would work. What's creating this |
NuGet creates the .tools folder during restore. CLI reads the csproj/.tools folder to launch the tool. AFAIK there aren't any plans to change this. cref NuGet/Home#3462. cc @emgarten @eerhardt Regardless of how a CLI tools finds or distributes MSBuild, we need some sort of API so that BuildEnvironmentHelper.Initialize knows where to find MSBuild.exe. |
@piotrpMSFT - do you have any opinions on option 1 above? @jeffkl - we've discussed before enabling MSBuild to "run out of a NuGet cache", in order for every tool to not need its own private copy of MSBuild. Has any progress been made in this area? |
@eerhardt The blockers for making MSBuild run out of the NuGet cache remain: either smarter loading behavior (load our assemblies out of a folder whose layout we totally control) or a full-featured "find files from the nuget cache" feature baked into the framework. Neither seems forthcoming. |
There are possible changes coming soon to NuGet/CLI which may solve this issue independently of changes to MSBuild. cc @yishaigalatzer @rrelyea - the discussion we had about location of a CLI tool's .deps.json file. |
In our meeting this morning, we discussed this and the answer was: The CLI will set an environment variable when invoking a tool that will point to the location of it's MSBuild install. The CLI Tool can read this environment variable to find out the path to MSBuild's installation. |
🔔 Any update on this? Running into the same issue. |
In preview3, the SDK will set the env variable MSBUILD_EXE_PATH to the location of MSBuild.dll. FWIW, in most cases, CLI tools are better off invoking "dotnet-msbuild" with a custom target instead of invoking MSBuild APIs directly. |
Got it to work, thanks to @rainersigwald :) In powershell -
Here C:\Program Files\dotnet\sdk\1.0.0-preview4-004079 is the install path for dotnet sdk on my machine |
@mishra14 this is very fragile. The code makes assumptions on where CLI installs MSBuild.dll which are quite certain to be broken in upcoming releases. As @natemcmaster says, the CLI already has an environment variable which it passes to processes it creates to identify the msbuild exe path. Even this should only be used in critical scenarios where invoking I know the self-created environment variable you suggest is straightforward and works at the moment, but do expect it to fail from release to release. |
@piotrpMSFT : @rainersigwald mentioned that the workaround
|
It's a subtlety. Dotnet SDK does not set any persistent environment variables. It only passes some environment variables to processes that it itself creates. Tools that need access to this value from the CLI need to be invoked by the CLI, giving the product the opportunity to redefine its own internal layout/implementation without breaking existing extensions :) |
@piotrpMSFT It's worse than that. When you're developing the tool, you can't rely on the CLI setting that variable, because it's not set in (the need for |
@mishra14 using Are you getting the error that MSBuild cannot find itself?
Or are you getting a different error? The |
@jeffkl : I have dotnet core sdk preview4 installed.
Are you getting the error that MSBuild cannot find itself? Yes |
@livarcocc can comment on where we expose the env var. If adding it to |
@mishra14 are you getting the error when you do |
We only expose it in the ProjectToolsCommandResolver and ProjectDependenciesCommandResolver right now. I think exposing it during run may make sense for people developing tools. |
@jeffkl : are you getting the error when you do dotnet run?: Yes on dotnet run and also from within dev15. Can you check to see if files like MSBuild.dll, Microsoft.Common.targets are in your output folder: No. I thinks that why I needed to set the env vars. So that dotnet could pick up the correcxt place where msbuild exists. |
@mishra14 What packages are you referencing? The |
@jeffkl : I do have runtime.
|
@emgarten is this a bug in NuGet? The project.assets.json has the correct stuff: "Microsoft.Build.Runtime/15.1.0-preview-000370-00": {
"type": "package",
"dependencies": {
"Microsoft.Build": "[15.1.0-preview-000370-00]",
"Microsoft.Build.Framework": "[15.1.0-preview-000370-00]",
"Microsoft.Build.Tasks.Core": "[15.1.0-preview-000370-00]",
"Microsoft.Build.Utilities.Core": "[15.1.0-preview-000370-00]"
},
"contentFiles": {
"contentFiles/any/netcoreapp1.0/15.0/Microsoft.Common.props": {
"buildAction": "None",
"codeLanguage": "any",
"copyToOutput": true,
"outputPath": "15.0/Microsoft.Common.props"
},
"contentFiles/any/netcoreapp1.0/MSBuild.dll": {
"buildAction": "None",
"codeLanguage": "any",
"copyToOutput": true,
"outputPath": "MSBuild.dll"
},
"contentFiles/any/netcoreapp1.0/MSBuild.runtimeconfig.json": {
"buildAction": "None",
"codeLanguage": "any",
"copyToOutput": true,
"outputPath": "MSBuild.runtimeconfig.json"
},
"contentFiles/any/netcoreapp1.0/Microsoft.CSharp.CrossTargeting.targets": {
"buildAction": "None",
"codeLanguage": "any",
"copyToOutput": true,
"outputPath": "Microsoft.CSharp.CrossTargeting.targets"
},
// (etc)
}
}, But the files are not in the output folder after doing
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>1.0.0-alpha-20161104-2</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
+ <PackageReference Include="Microsoft.Build.Runtime">
+ <Version>15.1.0-preview-000370-00</Version>
+ </PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
|
Okay this is currently blocked by NuGet/Home#3683 because our contentFiles are not being copied to the output directory. The workaround is to set |
@jeffkl What's the current state of this for a tool? My understanding is that it should work fine since |
I haven't tested lately. We decided that ASP.NET Core CLI tools should not use MSBuild APIs for project evaluation. AFAIK the only tool using MSBuild object model programmatically is Instead, ASP.NET Core CLI tools accomplish indirect project evaluation by abusing the imports from |
I'm not sure, I should probably set up a repro so I can test solutions. We didn't really want people taking a dependency on |
Ping on a really old thread. At this point, all of the tools I have created workaround this limitation by invoking a new MSBuild process instead of calling on MSBuild API directly. It's a less-than-ideal programming experience though. I recently saw this: https://github.com/daveaglick/Buildalyzer. Is this kind of API something MSBuild would every provide as a 1st class thing? If not, I suugest we just close this as "wontfix" and invite tool authors to use something like https://github.com/daveaglick/Buildalyzer if they want to use MSBuild in-proc. |
Using MSBuild API for in-proj project evaluation in a dotnet-CLI project tool throws this excpetion:
IIUC the problem is that BuildEnvironmentHelperSingleton looks in
AppContext.BaseDirectory
(and a few other locations) for MSBuild.exe. When dotnet-CLI invokes a project tool, the AppContext.BaseDirectory will be$(NuGetPackages)/.tools/$(ToolName)/$(ToolVersion)/netcoreapp1.0/
. The only content NuGet/CLI will put into this directory is the *.deps.json file and project.lock.json file for the tool.Using Microsoft.Build.Runtime 15.1.262-preview5.
cc @piotrpMSFT
The text was updated successfully, but these errors were encountered: