dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
21.99k stars 1.72k forks source link

MAUI .NET 8 "duplicate file names" build error when an app's libraries use NuGets that have .svg images #19840

Open awalker-dsg opened 8 months ago

awalker-dsg commented 8 months ago

Description

After migrating our MAUI app from net7.0 to net8.0, we started seeing the following build error:

One or more duplicate file names were detected.  All image output filenames must be unique.

This error is described in this MAUI known issues doc in a section titled Duplicate image filename errors.

However, the error is not caused by the scenario described in that doc. Instead, the duplicate image file errors in our app are being generated for image files that are included in NuGets we are importing into our app. The image files were added to the NuGets using a technique suggested by the MAUI team in this MAUI net7.0 issue.

Steps to Reproduce

To verify that this error wasn't due to some idiosyncrasy of our app, we created two test solutions using the VS new project wizard to reproduce the issue. The test solutions (found at the public repro project repo link below) consist of the following:

TestMauiImageNuGet.sln: This contains a single project named TestMauiImageNuGet. This was used to create a NuGet containing a single .svg image.

MauiDupImageTestApp.sln: This contains two projects. DoNothingAppLib1.csproj is a library project that contains a reference to the TestMauiImageNuGet NuGet. MauiDupImageTestApp.csproj is the main app project that is simply the standard "Hello, World!" app generated by the VS app wizard for net8.0. The app has a reference to the DoNothingAppLib1 project.

To summarize, the test code consists of a main app (MauiDupImageTestApp) that references a library (DoNothingAppLib1), which in turn references a NuGet (TestMauiImageNuGet) that contains an .svg image file.

Before attempting to build the app, you'll first need to add the test code's LocalNuGetRepo folder to your NuGet package sources. In Visual Studio, this is done as follows:

  1. Select "Tools" > "NuGet Package Manager" > "Package Manager Settings"
  2. Select "Package Sources"
  3. Click the "+" button
  4. Set the name to "DupImageTestSource" and the Source to full folder path to the test code's "LocalNuGetRepo" folder.

Once that is done, build the MauiDupImageTestApp.sln. If the error described here exists, the build will fail due to the "All image output filenames must be unique" error.

There are no actual references to the image in the NuGet in the code of either the DoNothingAppLib1 or the TestMauiImageNuGet projects. Merely including the NuGet with the image is enough to trigger the "duplicate file names" error.

This issue does not occur in the test projects if the target platforms are changed from net8.0 to net7.0. So clearly, this was introduced by the changes made for net8.0.

The test projects only target Android and iOS because those are the platforms we target in our MAUI apps.

Suggestion The duplicate image files being detected are in fact multiple references to the same image file. If that's the case, and the reason for having a duplicate filename check for image files in the build process is to ensure that one image isn't overwritten by a different image, then adding a binary comparison to determine if the "duplicate" files are really different files would eliminate the error for this scenario.

Link to public reproduction project repository

https://github.com/awalker-dsg/Net8_Dup_Image_Issue

Version with bug

8.0.3

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

This is a build error, not a runtime error. It may occur on other platforms, but we only target iOS and Android.

Did you find any workaround?

Adding ExcludeAssets="buildTransitive" to the NuGet PackageReference in a solution's library projects eliminates the build error. This workaround should not be applied to NuGets included in projects whose OutputType is Exe because otherwise the app will not be able to access the images.

An example of this workaround can be found in commented-out code in the repro code's DoNothingAppLib1.csproj project.

The workaround gets us past the build error. However, it requires developers to manually edit the .csproj files after adding NuGets that contain image references to their projects. In our case, the NuGets are usually added using the VS NuGet Package Manger, so the need for this workaround usually won't be known until developers get "duplicate file names" errors during the next build. And, unless the developer is already familiar with the error, they will likely waste time trying to figure out what broke the build before finding a reference to the workaround. This is less than ideal.

Relevant log output

2>C:\Users\xxxx\.nuget\packages\microsoft.maui.resizetizer\8.0.3\buildTransitive\Microsoft.Maui.Resizetizer.After.targets(619,9): error : One or more duplicate file names were detected.  All image output filenames must be unique: test_image_arrow (C:\Users\xxxx\.nuget\packages\testmauiimagenuget\8.0.0\buildTransitive\\Images\test_image_arrow.svg)
2>Done building project "MauiDupImageTestApp.csproj" -- FAILED.
2>C:\Users\xxxx\.nuget\packages\microsoft.maui.resizetizer\8.0.3\buildTransitive\Microsoft.Maui.Resizetizer.After.targets(619,9): error : One or more duplicate file names were detected.  All image output filenames must be unique: test_image_arrow (C:\Users\xxxx\.nuget\packages\testmauiimagenuget\8.0.0\buildTransitive\\Images\test_image_arrow.svg)
2>Done building project "MauiDupImageTestApp.csproj" -- FAILED.
phunkeler commented 8 months ago

The .svg is written twice to mauimage.inputs which appears to trigger the error during the ResizetizeImages task (in it's RemoveDuplicates method) and may indicate a problem in how MauiImage items are collected from referenced projects during the ResizetizeCollectItems target (Why is it included twice?).

Task "WriteLinesToFile" (TaskId:356)
  Task Parameter:
    Lines=
      File=Resources\Images\dotnet_bot.png;Link=;BaseSize=300,185;Resize=True;TintColor=;Color=;IsAppIcon=;ForegroundScale=;ForegroundFile=
      File=C:\Users\xxxx\.nuget\packages\testmauiimagenuget\8.0.0\buildTransitive\\Images\test_image_arrow.svg;Link=;BaseSize=;Resize=;TintColor=;Color=;IsAppIcon=;ForegroundScale=;ForegroundFile=
      File=C:\Users\xxxx\.nuget\packages\testmauiimagenuget\8.0.0\buildTransitive\\Images\test_image_arrow.svg;Link=;BaseSize=;Resize=;TintColor=;Color=;IsAppIcon=;ForegroundScale=;ForegroundFile=
      File=Resources\AppIcon\appicon.svg;Link=;BaseSize=;Resize=;TintColor=;Color=#512BD4;IsAppIcon=True;ForegroundScale=;ForegroundFile=Resources\AppIcon\appiconfg.svg (TaskId:356)

  Task Parameter:Overwrite=True (TaskId:356)
  Task Parameter:WriteOnlyWhenDifferent=True (TaskId:356)
  Task Parameter:File=obj\Debug\net8.0-android\mauiimage.inputs (TaskId:356)
Done executing task "WriteLinesToFile". (TaskId:356)

I'm not familiar with developing/debugging the resizetizer, so am stuck at the moment, but hope to learn more soon.

msbuild.binlog.zip

letscodewithkalyan commented 7 months ago

@awalker-dsg any workaround for this. I am facing issue while added nuget in ProjectA. And in ProjectB I referenced the nugets. getting build error. While in .NET 7.0 no error but in .NET 8.0 facing error.

awalker-dsg commented 7 months ago

@awalker-dsg any workaround for this. I am facing issue while added nuget in ProjectA. And in ProjectB I referenced the nugets. getting build error. While in .NET 7.0 no error but in .NET 8.0 facing error.

Yes, please see the "Did you find any workaround?" section of the OP.

ninachen03 commented 6 months ago

I used the Repo project and reproduced the problem on 17.10 Preview 1. image

Portikus commented 6 months ago

We have encountered a similar problem with the same error message. However, also under Windows and without nuget packages. Simply create the following project structure: MauiLib->MauiApp->MauiLib
When building, the message appears: Error: One or more duplicate file names were detected. All image output filenames must be unique: appicon (...\Resources\AppIcon\appicon.svg) (624, 10)

As soon as you remove the reference from MauiApp to MauiLib, the error message no longer appears. Unfortunately, the described workaround does not help with this problem.

vgocotta commented 4 months ago

I had the same problem and managed to solve it. In my case I set two MauiIcon tags and specified one with a condition for android <!-- App Icon -->

<MauiIcon Include="Resources\AppIcon\appicon_a.svg" Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'" ForegroundFile="Resources\AppIcon\appiconfg_a.svg" Color="#FCDABB" />

<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#FCDABB" />

In the Resources\AppIcon folder I did this: image

After I did this the project builded without the error