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

[Traversal] Filtering projects solution files without kicking off evaluations #522

Open
ViktorHofer opened this issue Jan 4, 2024 · 2 comments

Comments

@ViktorHofer
Copy link
Member

ViktorHofer commented Jan 4, 2024

The new filter projects in solution files feature in Microsoft.Build.Traversal is phenomenal. I noticed that by default, it still kicks off evaluations for the projects in order to then invoke the custom ShouldSkipProject target. In my situation, I don't want to even trigger evaluations (and with also not trigger msbuild sdk resolver events). I was able to make that work with the following code:

Directory.Solution.targets

<Project>

  <Import Sdk="Microsoft.Build.Traversal" Project="Sdk.targets" />

  <!-- Overwrite target from Traversal Sdk.targets. -->
  <Target Name="GetProjectsToSkip">
    <ItemGroup>
      <ProjectToSkip Include="@(ProjectReference)"
                     Message=""
                     Condition="$([System.String]::new('%(ProjectReference.Identity)').EndsWith('.Tests.csproj'))"
                     OriginalItemSpec="%(Identity)" />
    </ItemGroup>
  </Target>

</Project>

Unfortunately this only works with normal restore and not static graph based restore: #521

Should we document this option? From my perspective, while this is a static mechanism to filter out projects, it's the only correct way as it doesn't even trigger evaluations of filtered out projects.

@ViktorHofer
Copy link
Member Author

ViktorHofer commented Jan 4, 2024

cc @jeffkl

I initially tried to do this without a target but the ItemGroup always gets embedded into the sln before the ItemGroup with the ProjectReference items. That's unfortunate as it would have solved the static graph restore issue.

Is there a hook to import stuff after the ProjectReference ItemGroup? Who would be the best contact on the msbuild/VS side to ask about this?

@jeffkl
Copy link
Contributor

jeffkl commented Jan 5, 2024

The original idea of dynamic skipping was for each project to indicate if it should be built. So obviously that works well if a target is run ahead of time which modifies the final ProjectReference items. But as you've noticed since static graph only does evaluations it won't quite work in that mode. Instead, the entry project would need to know ahead of time if a particular project reference should be included in the restore/build and your sample above is a good way to do it, based off of a naming convention.

My design came about because I introduced a Visual Studio extension to a repo that only needed to build on Windows and CI is building/testing on Linux and Mac which caused issues. It works pretty well when building solution files since they generally reference every project in the repo. Traversals are potentially more complicated since they represent what to build in that particular folder. So at the root you have a dirs.proj that points to just the next folder down's dirs.proj projects. The transitive closure isn't necessarily represented in that paradigm so skipping transitive projects on-the-fly isn't easy.

I wonder if MSBuild's static graph API needs a way for a project to communicate that it wants to be left out of a build? I suppose in that case the project would still get evaluated but be trimmed away from the final dependency tree. I'm conflicted on whether or not the fix for this needs to avoid the evaluation all together or just skip projects that opted out. What are your thoughts?

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