maui icon indicating copy to clipboard operation
maui copied to clipboard

PNG images are not generated from SVGs for MAUI libraries targeting Android or iOS

Open awalker-dsg opened this issue 3 years ago • 10 comments

Description

The MAUI documentation's Add images to a .NET MAUI app project page describes how SVG images are converted to PNG files for targeted platforms when the build action is set to MauiImage.

Although this works when adding SVGs to MAUI projects whose OutputType is Exe, this does not work when the OutputType is not set or is set to Library.

This issue was seen in VS 17.3.3 and VS 17.4.0 Preview 1.0.

Steps to Reproduce

  1. Use Visual Studio to create a new .NET MAUI Class Library project and solution.
  2. Add a Resources folder to the project.
  3. Add an Images Folder to the Resources folder.
  4. Add an SVG file to the Images folder added in the previous step. As noted here, the SVG file name must meet Android naming requirements.
  5. Set the SVG file's Build Action to MauiImage
  6. Build the solution.
  7. Use File Explorer to search the solution folder for files containing the root SVG file name. For example, if your SVG file is named my_image.svg, search for my_image.

If the MAUI build process is working correctly, there should be PNG files with the same root name as the SVG file in the Android and iOS obj folders. If it's not working, no PNG files will be generated.

Link to public reproduction project repository

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

Version with bug

6.0.400

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

iOS 15.4, Android 31.0

Did you find any workaround?

No, I did not find a work-around for this issue when building a library. It does work when building an app, but that's not really a workaround.

Relevant log output

No response

awalker-dsg avatar Sep 09 '22 15:09 awalker-dsg

@mattleibow @Redth do you have any additional thoughts?

PureWeen avatar Sep 14 '22 18:09 PureWeen

Is the svg valid?

It could be that it's not being parsed properly.

Redth avatar Sep 14 '22 19:09 Redth

Oh wait. In a library. That's not supported unless the library is referenced by an app project which is using Maui.

You'd have to include them as <MauiImage items from the app manually if you're not using both projects referenced together to start with.

Redth avatar Sep 14 '22 19:09 Redth

SVG-to-PNG conversion is not supported in libraries? Ugh.

Our library is distributed as a NuGet, and it seems less than ideal to ask our library's users to copy and paste SVG image files from some external source into their app projects in order to allow the library to render the images. So, we'll have to either find a way to use SVGs directly as we did with the old Xamarin.FFImageLoading.Svg Nuget (which is really what we wanted to do, anyway), or do the conversions from SVGs to PNGs ourselves for each target platform. This is not a show-stopper, just somewhat disappointing.

I went back and re-read the Add images to a .NET MAUI app project page, and it does say that SVG images "can be added to your app project". So, the "app project" reference does provide a hint that SVG-to-PNG conversion won't work for libraries. However, to avoid further questions from developers like me who miss subtle references like that, you might consider updating the page to explicitly say that the SVG-to-PNG magic only works in projects whose OutputType is Exe.

awalker-dsg avatar Sep 15 '22 11:09 awalker-dsg

If the app references the library, it should be collecting them all... I wonder if there is a problem somewhere in the targets...

mattleibow avatar Sep 15 '22 11:09 mattleibow

Unless I'm missing something, SVG-to-PNG conversion is effectively a pre-processing step done by Visual Studio that creates platform-specific PNGs for use during the build process for each platform. If that's the case, then when a NuGet gets created from the VS build output, there is no place for the SVGs in the distribution -- the NuGet would only contain the platform-specific PNGs (if they were there). As a result, there is no way for the MAUI app project that uses the NuGet to access the original SVG images.

awalker-dsg avatar Sep 15 '22 12:09 awalker-dsg

There are two scenarios for this:

  1. You are referencing the source library project from the app project directly.
  2. You are referencing the library from its nuget package or otherwise the .dll assembly directly.

The first one should work fine today with <MauiImage.

The second one will not automatically package up your .svg into the nuget and include them in the consuming projects.

BUT you certainly can include svg's in your nuget and have them included as MauiImage's in the consuming project, there's just a few more steps involved:

  1. Create a My.NuGet.Package.Id.targets (note the filename has to be the same as your actual package id).
<Project>
  <ItemGroup>
    <MauiImage Include="$(MSBuildThisFileDirectory)\Images\myimage.svg" />
    <MauiImage Include="$(MSBuildThisFileDirectory)\Images\anotherimage.svg" BaseSize="20,20" />
  </ItemGroup>
</Project>
  1. Next you need to ensure the targets file and the .svg image files are embedded in the appropriate folder within the nuget package of your library project. So, include them in your project like this:
<ItemGroup>
  <None Include="My.NuGet.Package.Id.targets" Pack="True" PackagePath="buildTransitive\" />
</ItemGroup>
<ItemGroup>
  <MauiImage Include="Resources\Images\myimage.svg" Pack="True" PackagePath="buildTransitive\Images\" />
  <MauiImage Include="Resources\Images\anotherimage.svg" BaseSize="20,20" Pack="True" PackagePath="buildTransitive\Images\" />
</ItemGroup>

The result should be that the targets and svg files will be contained inside the buildTransitive\ and the targets file due to its special name being that of your package id will be automatically imported into the project referencing the nuget.

The result should be that those images get processed and included in the apps referencing the library.

Redth avatar Sep 15 '22 12:09 Redth

Thanks, @Redth. I'll will give your suggestions a try.

awalker-dsg avatar Sep 15 '22 14:09 awalker-dsg

Hi @Redth. I implemented your suggested changes in the MauiTestLib_10019 test project; you can see the changes in the add_targets_file branch.

Using Visual Studio, I built the MauiTestLib_10019 project and created a .nuspec package before adding the .target file, and then repeated the process after adding the .target file. I then compared the contents of the two .nuspec packages. The 2nd .nuspec file does contain the .target file in a new buildTransitive folder. However, the .svg file is not included in the package's buildTransitive\Images folder as I would have expected.

Have I missed something? It's certainly possible I have misunderstood your instructions.

awalker-dsg avatar Sep 19 '22 20:09 awalker-dsg

Seems like maybe you need to include them in <None to use Pack=True afterall.

Try adding this item group item in addition to the ones you have already in your project:

<ItemGroup>
  <None Include="Resources\Images\question_mark.svg" Pack="True" PackagePath="buildTransitive\Images\" />
</ItemGroup>

Redth avatar Sep 19 '22 20:09 Redth

@Redth, your last suggestion worked. The images are now included in the NuGet package's buildTransitive\Images\ folder.

Now, how does the app referencing the NuGet library use those SVG images? In your earlier comments, you said the following:

The result should be that those images get processed and included in the apps referencing the library.

Does "get processed and included in the app" mean that VS should detect the SVGs in the NuGet package's buildTransitive\Images\ folder and do its pre-processing magic to convert them to PNGs for the target platforms? That does not appear to be happening. Are additional steps required to tell VS where to find the SVGs in any NuGets used by the app?

awalker-dsg avatar Sep 22 '22 10:09 awalker-dsg

@Redth, my mistake. It looks like this IS working after all.

Shortly after I posted my last comment, I realized that our app was including the NuGet containing the SVGs indirectly -- i.e. the app included a NuGet which in turn referenced the NuGet with the SVG images.

When I added an explicit reference to the NuGet containing the SVGs to the app, VS was able to process the NuGet's SVGs and convert them to PNGs.

Many thanks for your help.

awalker-dsg avatar Sep 22 '22 11:09 awalker-dsg