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

Files linked into ResX files are not checked by the FUTDC #9441

Open
drewnoakes opened this issue Apr 10, 2024 · 9 comments
Open

Files linked into ResX files are not checked by the FUTDC #9441

drewnoakes opened this issue Apr 10, 2024 · 9 comments
Labels
Feature-Up-to-date Build up-to-date check that avoids shelling out to MSBuild unless necessary. Parity-Legacy-Feature Missing features from the legacy project system. Triage-Approved Reviewed and prioritized
Milestone

Comments

@drewnoakes
Copy link
Member

drewnoakes commented Apr 10, 2024

When a None item (such as a text file) is linked into a .resx file, any changes to that None item do not trigger a build. This can lead to underbuild and confusion/frustration.

This problem did not exist with legacy projects as they explicitly list all project inputs in the .csproj file. SDK-style projects use globbing and do not include None items in the FUTDC for performance reasons.

Repro steps

  1. Open VS2022
  2. Create console app
  3. Add LinkedFile.txt
  4. Add Resources.resx with content prior
  5. Open the .resx file with the Managed Resources Editor
  6. In Files section, Add existing file and select the LinkedFile.txt
  7. Build a few times

Notice that LinkedFile.txt is not inspected at all by the FUTDC:

Comparing timestamps of inputs and outputs:
    Adding UpToDateCheckBuilt outputs:
        D:\MyProject\bin\Debug\net8.0\MyProject.dll
        D:\MyProject\obj\Debug\net8.0\MyProject.dll
        D:\MyProject\obj\Debug\net8.0\MyProject.pdb
        D:\MyProject\bin\Debug\net8.0\MyProject.pdb
    Adding newest import input:
        D:\MyProject\MyProject.csproj
    Adding EmbeddedResource inputs:
        D:\MyProject\Resources.resx
    Adding Compile inputs:
        D:\MyProject\Resources.Designer.cs
        D:\MyProject\Program.cs
    No inputs are newer than earliest output 'D:\MyProject\obj\Debug\net8.0\MyProject.pdb' (2024-04-10 14:05:24.168). Newest input is 'D:\MyProject\Resources.Designer.cs' (2024-04-10 14:05:17.707).
Checking items to copy to the output directory:
    Checking copy items from project 'D:\MyProject\MyProject.csproj':
        Checking PreserveNewest item
            Source      2024-04-10 14:05:24.203: 'D:\MyProject\obj\Debug\net8.0\apphost.exe'
            Destination 2024-04-10 14:05:24.203: 'D:\MyProject\bin\Debug\net8.0\MyProject.exe'
Project is up-to-date.
Up-to-date check completed in 0.7 ms
@drewnoakes drewnoakes added Feature-Up-to-date Build up-to-date check that avoids shelling out to MSBuild unless necessary. Parity-Legacy-Feature Missing features from the legacy project system. labels Apr 10, 2024
@softworkz
Copy link

Can it be true that I've been the first one to notice this`?
(I reported in #9440)

@drewnoakes
Copy link
Member Author

Triage notes:

This problem also occurs on the command line. Having Program.cs print out the resource to the console and running...

> echo updated >> LinkedFile.txt
> dotnet run
prior

...will print out the old version, not the new one. So this issue isn't limited to VS. Note however that forcing a rebuild does cause the value to be picked up:

> msbuild -t:Rebuild
> dotnet run
updated

As for a potential fix, files linked into .resx files are not available during design-time builds, so we'd either have to add that to DTBs (potentially regressing DTB perf) or find some other route for the data to reach the FUTDC. Looking at binlogs from the rebuild above shows:

image

i.e. nothing during the rebuild, related to resource generation, looks at the None input item. This will be why the problem exists on the command line as well. Only during a rebuild will the embedded item be picked up within the GenerateResource task. Linked files are not inputs to that task or its targets.

Note that GenerateResource exists in MSBuild's targets, not the SDK. So I'm unclear on how this could work for legacy projects either, given that linked files aren't inputs to the target. Perhaps the target always runs (it doesn't declare any inputs/outputs as far as I can see).

@drewnoakes
Copy link
Member Author

Can it be true that I've been the first one to notice this`?

I won't say you're the first to experience the issue, but this is certainly the first I've heard about it.

@drewnoakes
Copy link
Member Author

@merriemcgaw FYI, as this has potential impact for WinForms users migrating to .NET Core.

@rainersigwald have you seen this before?

@rainersigwald
Copy link
Member

Perhaps the target always runs (it doesn't declare any inputs/outputs as far as I can see).

It does, and the task has its own internal state lookup that tries to account for this case. Sounds like that's going awry here.

Can FUTDC inputs come from a full build or are they all computed at design time? I'm wondering if we should add an output to GenerateResource that lists the linked files we found so you can account for them on the next round.

@merriemcgaw
Copy link
Member

@JeremyKuhne and @lonitra for visibility.

@drewnoakes
Copy link
Member Author

Can FUTDC inputs come from a full build or are they all computed at design time? I'm wondering if we should add an output to GenerateResource that lists the linked files we found so you can account for them on the next round.

We only pull data from design-time builds. I think anything we did here would likely regress perf due to resx file parsing, and be a non-starter on that basis.

The work being done on improving resx editing does eagerly parse resx files and might be able to flow data into the FUTDC via a different channel. We'd have to think about it.

I can't see a great path forward here, so I'd like to understand the impact of the problem. It's existed for a long time and we haven't had reports about it, but that doesn't mean people don't struggle with this.

@softworkz
Copy link

I'd like to understand the impact of the problem. It's existed for a long time and we haven't had reports about it, but that doesn't mean people don't struggle with this.

I don't think this can be pushed away on the basis of "impact" consideration. It has always worked (in .netframework projects) and is clearly something that is suppposed to work. The MSBuild documentation leaves no doubt about it:

Because .resx files may contain links to other resource files, it is not sufficient to simply compare .resx and .resources file timestamps to see if the outputs are up to date. Instead, the GenerateResource task follows the links in the .resx files and checks the timestamps of the linked files as well. This means that you should not generally use Inputs and Outputs attributes on the target containing the GenerateResource task, as this may cause it to be skipped when it should actually run.
(https://learn.microsoft.com/en-us/visualstudio/msbuild/generateresource-task)

If the FUTDC doesn't handle it properly, then it's a bug.

A question of interest might be how the FUTDC in netframework projects is doing this..

@tmeschter tmeschter added this to the Backlog milestone Apr 25, 2024
@tmeschter tmeschter added the Triage-Approved Reviewed and prioritized label Apr 25, 2024
@toddwong
Copy link

Have to force rebuild every time. Really annoying

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature-Up-to-date Build up-to-date check that avoids shelling out to MSBuild unless necessary. Parity-Legacy-Feature Missing features from the legacy project system. Triage-Approved Reviewed and prioritized
Projects
None yet
Development

No branches or pull requests

6 participants