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

New command line argument for evaluating properties / items #6071

Closed
jairbubbles opened this issue Jan 22, 2021 · 14 comments
Closed

New command line argument for evaluating properties / items #6071

jairbubbles opened this issue Jan 22, 2021 · 14 comments
Labels
closed-by-bot Closed due to lack of activity needs-more-info Issues that need more info to continue investigation. stale For issues that haven't had activity in some time. triaged

Comments

@jairbubbles
Copy link

For a while we've been using the MsBuild lib to evaluate properties & items for C# and C++ projects. It's used in internal tools and CI sripts to introspect the projects and do stuffs.

We've been using the NuGet package lib but is has been problematic (SDK not resolved, assembly loading issues...).

We recently try to use locator but it didn't improve the situation.

Also the switch to .NET Core seems like we're being in a dead end with the current solution. Indeed a .NET Core application is not able to parse projects with the current tool chain.

I'm currently trying to use preprocess command line but sadly it doesn't match exactly our needs.

So I was wondering if adding a new kind of preprocessor could be considered?

I made a small prototype to show case the idea: https://github.com/jairbubbles/MsBuildEvaluator

The idea is to dump an .xml with the evaluated values of the properties / items (and not the chains of import). The good thing about it is that it's really simple, the generated .xml does contain any variable at all and is super easy to parse.

The (simplified) output would look like that:

<Project>
  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>
    <Platform>AnyCPU</Platform>
    <CopyDependencies>true</CopyDependencies>
    <IsPackable>True</IsPackable>
    <NoWarn>1570,1573,1574,1591,1712,NU1701</NoWarn>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
    <OutputType>winexe</OutputType>
    <UseWindowsForms>true</UseWindowsForms>
    <!-- and many more! -->
  </PropertyGroup>
  <ItemGroup>
     <!-- Package references -->
    <PackageReference Include="RestSharp">
      <Version>106.11.7</Version>
    </PackageReference>
     <!-- Project references -->
    <ProjectReference Include="../test.csproj">
      <Targets></Targets>
      <OutputItemType></OutputItemType>
      <ReferenceSourceTarget>ProjectReference</ReferenceSourceTarget>
      <Private>false</Private>
      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
    </ProjectReference>
    <!-- Project files -->
    <Compile Include="File.cs"/>
    <!-- and many more! -->
</Project>

Thanks!

Please note that some discussions happened with @rainersigwald here prior to filling that issue.

@jairbubbles jairbubbles added the needs-triage Have yet to determine what bucket this goes in. label Jan 22, 2021
@jairbubbles jairbubbles changed the title New preprocessor for evaluating properties / items New command line argument for evaluating properties / items Jan 22, 2021
@benvillalobos
Copy link
Member

Team Triage: @cdmihai you recently added a feature for static graph and not building. @ladipro suggested that if you use that in conjunction with a binlog, you can see the evaluated project. Does this sound right?

@jairbubbles
Copy link
Author

jairbubbles commented Feb 12, 2021

Thx @benvillalobos!

After testing a bit more my POC it appeared clear that for performance reasons it's a nogo: evaluating one project at a time is too slow, bootstrapping MsBuild each time is a price too high to pay.

So binlog seems like a better approach and would allow to evaluate a .sln at once.

@cdmihai Do you have more info about the "feature for static graph"?

@jairbubbles
Copy link
Author

Nevermind, just found it! (#6016)

I guess my main problem will be that it's not available on older versions...

@cdmihai
Copy link
Contributor

cdmihai commented Feb 16, 2021

@jairbubbles
Is the information in the binlog sufficient for your purpose? If not, then there's a couple of options:

  • (my preference) build your own dotnet console app that uses the ProjectGraph APIs to evaluate the entire dependency graph and then transform each ProjectInstance into your desired format. I like this option because every msbuild user might need a different output format for their specific use cases.
  • change msbuild to emit more events during evaluation to have them in the binlog and then use /graph:noBuild.
  • change msbuild to implement your desired preprocess output as a another /graph option, similar to noBuild.

evaluating one project at a time is too slow, bootstrapping MsBuild each time is a price too high to pay.

ProjectGraph evaluates in parallel.

@jairbubbles
Copy link
Author

build your own dotnet console app

Right now we have a library that consumes MsBuild dynamically, We just switched it from using Project to ProjectInstance which is a lot more friendly. We don't use ProjectGraph though, just a Parallel.ForEach on all .csproj to load. I'll take a look, thanks!

I could also create a CLI version and communicate with the lib but the idea being using MsBuild was to make sure we'll get the exact same results than when building. We had tons of problems with SDK resolving and assembly loading in the past.

@cdmihai
Copy link
Contributor

cdmihai commented Feb 18, 2021

We had tons of problems with SDK resolving and assembly loading in the past.

It would be interesting to find out why the locator didn't work, since that's the best solution for solving sdk import issues. Please open issues on the locator repo.

@jairbubbles
Copy link
Author

We first started with locator but we indeed had a bunch of issues. Here are some thoughts:

  • we needed more control over how the msbuild version is discovered.
  • we load msbuild .dlls explicitly to make sure they are loaded all in the same place.
  • we needed the same behavior with .NET Core. So far it's working whilst @rainersigwald told us it wouldn't work. (Discussed here)

@Forgind
Copy link
Member

Forgind commented Aug 26, 2021

We first started with locator but we indeed had a bunch of issues. Here are some thoughts:

  • we needed more control over how the msbuild version is discovered.

Locator has an option for choosing the exact path to MSBuild, so if you know where your MSBuild is, you can use Locator to bring in the relevant assemblies.

  • we load msbuild .dlls explicitly to make sure they are loaded all in the same place.

That's similar to what Locator does. Is adds them to the assembly resolver for the current app domain.

  • we needed the same behavior with .NET Core. So far it's working whilst @rainersigwald told us it wouldn't work. (Discussed here)

This is risky—you're both right. It can work. .NET Core MSBuild can run many of the tasks and targets used by Visual Studio. On the other hand, it can't run all of them, which means you may get into situations where you try to do something very reasonable that works on Framework, and it fails. If it's currently working, that sounds like it only uses APIs available on Core. Can you explain why you can't use Locator to locate a .NET Core version of MSBuild for your purposes?

@Forgind Forgind added needs-more-info Issues that need more info to continue investigation. and removed needs-triage Have yet to determine what bucket this goes in. labels Aug 26, 2021
@jairbubbles
Copy link
Author

Hi @Forgind!

Can you explain why you can't use Locator to locate a .NET Core version of MSBuild for your purposes?

I think it's resumed with microsoft/MSBuildLocator#105. When using the .NET Core it won't list the MsBuild from VisualStudio which are the ones I want to use.

On the other hand, it can't run all of them, which means you may get into situations where you try to do something very reasonable that works on Framework, and it fails.

I'm wondering how you envision the transition? At some point I imagine MsBuild will only be shipped as a .NET Core application.

NB: I'll try to see to get the code for our internal tool open-sourced, it will simplify a lot the discussion, it's called VsProjReader :-) (you can a look at the (outdated) README.md)

@Forgind
Copy link
Member

Forgind commented Aug 26, 2021

MSBuild from VS is .NET Framework MSBuild. We want MSBuildLocator to be "safe" meaning that if it recommends a particular version of MSBuild, we don't know of a reason it wouldn't work. That said, you can always use RegisterMSBuildPath instead to ignore what MSBuildLocator thinks is safe and just do what you want—BUT that's an unsupported usage, so if you do something like that, it is very unlikely we will be able to help if things go wrong.

Sorry for being unclear earlier, but I was curious why you can't use .NET Core with locator to find a .NET Core (i.e., not from VS) version of MSBuild and use its APIs. Looking through the readme you sent, I don't think any of the functionality you mentioned has to be framework-specific for any reason.

I'm wondering how you envision the transition? At some point I imagine MsBuild will only be shipped as a .NET Core application.

Great question! But I honestly have no idea. We've added some things that seem reasonable to Core even if they weren't there initially, so that might continue for a while, and if we provide reasonable alternatives, people can switch their projects to using those instead. I know there are at least some cases in which we intentionally decided not to include something because it was antiquated or a security hazard, but I'm sure there are cases that don't fit into any of the categories above...

@Forgind
Copy link
Member

Forgind commented Aug 26, 2021

Also,

I'll try to see to get the code for our internal tool open-sourced

💗 open-sourced

@jairbubbles
Copy link
Author

That said, you can always use RegisterMSBuildPath instead to ignore what MSBuildLocator thinks is safe

If we locate MsBuid ourselves, we didn't see the point to use Locator anymore (as you can see the README still say we're using it). I think we also had issues with the Resolve callback. To be honest the code on our side was so simple that at some point we didn't think it was useful to use the lib anymore.

Sorry for being unclear earlier, but I was curious why you can't use .NET Core with locator to find a .NET Core (i.e., not from VS) version of MSBuild and use its APIs.

We need to introspect .vcxproj too so using the MsBuild from dotnet didn't seem to be a good idea. I'm working in a game company so some projects also use game console SDKs. Our goal when porting to .NET Core was to make sure to have all our unit tests pass and it was clearly failing with Locator.

@ghost ghost added the stale For issues that haven't had activity in some time. label Sep 26, 2021
@ghost
Copy link

ghost commented Sep 26, 2021

This issue is marked as stale because feedback has been requested for 30 days with no response. Please respond within 14 days or this issue will be closed due to inactivity.

@ghost ghost closed this as completed Oct 10, 2021
@ghost
Copy link

ghost commented Oct 10, 2021

This issue was closed due to inactivity. If you can still reproduce this bug, please comment with the requested information, detailed steps to reproduce the problem, or any other notes that might help in the investigation.

@ghost ghost added the closed-by-bot Closed due to lack of activity label Oct 10, 2021
@AR-May AR-May added the triaged label Feb 21, 2024
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-by-bot Closed due to lack of activity needs-more-info Issues that need more info to continue investigation. stale For issues that haven't had activity in some time. triaged
Projects
None yet
Development

No branches or pull requests

5 participants