Inferred outputs of task's input/output parameter assume no change during execution
- Dominant language
- C#
- Stars
- 5.5k
- Forks
- 1.5k
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 141
Description
### Steps to reproduce
I am suspecting this is not a bug, and even it it is, it's already a feature because I reproduce it with MSBuild 2.0. But here's a stunningly simple project that escapes any explanation. The name `test.xxproj` is hardcoded because MSBuild v2.0 did not have `$(MsBuildThisFile)`, apparently. Any existing normal file will work instead.
So the target T1, which never runs, calls a task that does not even exist, and the task happily returns the list of outputs it did not even see. If you think that sounded like a Zen koan, I'm entirely with you!
```xml
```
The `ThisTaskDoesNotExist` task does not exist (hat tip to Dr. Quine), and I'd expect the `T1` never be ran, and `@(OutOfDateFiles)` be empty. The former is true, but as for the latter, all items from `@(Files)` end up in the `@(OutOfDateFiles)` list. The key part is the name `Foo` is both an input and an output property. Change one of them to `Bar`. and then `@(OutOfDateFiles)` will be empty.
What is going on?
```
C:\Users\kkm\work\msbuildxx>"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
Microsoft (R) Build Engine version 15.4.8.50001 for .NET Framework
Project "C:\Users\kkm\work\msbuildxx\test.xxproj" on node 1 (default targets).
T1:
Skipping target "T1" because all output files are up-to-date with respect to the input files.
Build:
Files out of date: 'test.xxproj'
Done Building Project "C:\Users\kkm\work\msbuildxx\test.xxproj" (default targets).
```
MSBuild 4:
```
C:\Users\kkm\work\msbuildxx>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
Microsoft (R) Build Engine version 4.7.2053.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Project "C:\Users\kkm\work\msbuildxx\test.xxproj" on node 1 (default targets).
T1:
Skipping target "T1" because all output files are up-to-date with respect to the input files.
Build:
Files out of date: 'test.xxproj'
Done Building Project "C:\Users\kkm\work\msbuildxx\test.xxproj" (default targets).
```
MSBuild 2:
```
C:\Users\kkm\work\msbuildxx>C:\Windows\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe
Microsoft (R) Build Engine Version 2.0.50727.5483
[Microsoft .NET Framework, Version 2.0.50727.8762]
Project "C:\Users\kkm\work\msbuildxx\test.xxproj" (default targets):
Target T1:
Skipping target "T1" because all output files are up-to-date with respect to the input files.
Target Build:
Files out of date: 'test.xxproj'
```
----
My real intention was to filter lists with quite complex dependencies (I am automating a compiler that generates multiple outputs, and I do not even know which of them will be generated until it is actually run. Fortunately, it also produces a file with the list of outputs it actually wrote, so I can simply `` those it did not generate, for dependency check not to recompile next time. So in the batched compile target, I subtract the (sub-batched) list of actually produced outputs from the sub-batch of expected outputs, and add them to a list to touch later (used also for something else, so I *need* them per-batch with marked metadata, unfortunately, otherwise I'd ran the `` in the same target/batch as the compiler, and Bob's your uncle). The 'ThisTaskDoesNotExist' is née 'CreateItem', naturally; first I replaced it with the one of my my own that I could debug, but when I never hit the breakpoints, I realized the task is even irrelevant. But when a particular batch is not run, as in the pared down example above, I incorrectly get all files in this expected but not generated file list.
I worked around this behavior by creating by own version of CreateItem, with differing input and output property names. But this feels like quite a hack to me. I cannot think of a more idiomatic way of minimizing batched collections using MSBuild dependency up-to-date checks and also collecting some task outputs per batch without hitting this issue though.
----
Here's a bit more realistic, less pared down variant that behaves similarly
```xml
```
```
Microsoft (R) Build Engine version 15.4.8.50001 for .NET Framework
Project "C:\Users\kkm\work\msbuildxx\test.xxproj" on node 1 (default targets).
T1:
Skipping target "T1" because all output files are up-to-date with respect to the input files.
T1:
Adding 'nosuchfile' to OutOfDateFiles
Build:
Files out of date: 'test.xxproj;nosuchfile'
Done Building Project "C:\Users\kkm\work\msbuildxx\test.xxproj" (default targets).
```
---
### Addendum
After some debugger poking [I found this](https://github.com/Microsoft/msbuild/blob/ee6a3f7856a92884b12fe63cea5111509620b14d/src/Build/BackEnd/Components/RequestBuilder/TargetEntry.cs#L535-L547), so my best guess this behavior is expected and correct. But oh boy, if it is, does not it deserve a separate chapter in the MsBuild docs, so very not obvious it is!
And it would be amazing to have a way to distinguish inferred items from up-to-date buckets from those actually generated by executed bucket's tasks!
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.