Feature Request: Lazy ProjectReference Resolution
- Dominant language
- C#
- Stars
- 5.5k
- Forks
- 1.5k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 133
Description
It would be nice if MSBuild implemented an "XBuild-ism": in xbuild, Build/dependency graph generation does *not* "properly" load project files and referenced `` files.
Consider the following project:
[LazyProjectReferences.zip](https://github.com/Microsoft/msbuild/files/2673257/LazyProjectReferences.zip)
```bash
$ curl -o LazyProjectReferences.zip https://github.com/Microsoft/msbuild/files/2673257/LazyProjectReferences.zip
$ unzip LazyProjectReferences.zip
$ cd LazyProjectReferences
$ msbuild
```
This project is "special" in that `App.csproj` depends on "MSBuild artifacts" which are *created* by `Generator.csproj`: `Generator.csproj` copies `Generator.targets` and `Generator.dll` into `$(OutputPath)`, and `App.csproj` then attempts to `` `Generator.targets` and use the `` tasks which is declared within it.
This (bizarre?) build setup works with xbuild: [xbuild-log.txt](https://github.com/Microsoft/msbuild/files/2673272/xbuild-log.txt)
[It fails with `msbuild`](https://github.com/Microsoft/msbuild/files/2673280/msbuild.binlog.zip):
```
App\App.targets(9,5): error MSB4036: The "Generator" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with in the project file, or in the *.tasks files located in the "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin" directory.
```
The reason this works with xbuild is because xbuild is "lazy" and reads the MSBuild files *twice*: Once looking for `@(ProjectReference)`, in order to construct the project dependency graph and compute the build order. This is not a "real" project parsing; as such, not all syntax is fully evaluated. During this first parsing, the `` invocation within `App.targets` is *ignored*. (The `` is followed, but making the `` conditional on `Generator.targets` existing fixes the problem; during the first build, `$(OutputPath)Generator.targets` won't exist, but because `App.targets` isn't "fully" parsed, there is no issue with the "potentially invalid" `` invocation.)
Once the build order has been computed, *then* xbuild builds the project "for real". `Generator.csproj` is built, creating files into `$(OutputPath)`. Then `App.csproj` is loaded "for real," and because `Generator.csproj` *already built*, `$(OutputPath)Generator.targets` now exists and can be ``ed, which in turn allows the `` task to be used.
I would ***love*** it if MSBuild also did this.
Why? Becuase *right now* I need to separate out my unit test build from my "main" build, because the unit tests *depend upon* outputs produced by the main build:
* [`xamarin-android/Xamarin.Android.sln`](https://github.com/xamarin/xamarin-android/blob/master/Xamarin.Android.sln)
* [`xamarin-android/Xamarin.Android-Tests.sln`](https://github.com/xamarin/xamarin-android/blob/master/Xamarin.Android-Tests.sln)
Originally I had only one solution which contained both the unit tests and the "main product"; I had to [split them up](https://github.com/xamarin/xamarin-android/commit/7343965a0bbee3d192684dbb371789613bf5b830) in order to even *begin* building with proper MSBuild instead of xbuild. I'm still irate about this.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the failure with the attached LazyProjectReferences.zip, using App.csproj, Generator.csproj, App.targets, and the provided msbuild.binlog. Compare the behavior with xbuild-log.txt and investigate how dependency-graph parsing handles imports and task invocations; done means MSBuild can build this setup in the correct order without requiring separate solutions.
Written by the indexing model from the issue text.
Assessment
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100