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

[regression/8.0.3] [Bug] .net8 Android not building because Resources from resx not found. #9163

Closed
Larhei opened this issue Nov 29, 2023 · 35 comments · Fixed by #9057
Closed
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects.

Comments

@Larhei
Copy link

Larhei commented Nov 29, 2023

Description

While migrating from .net7 to .net8 i was facing the issue that my app is not compiling in vs code and vs4mac on my mac.

I get a lot of errors like:
error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)

caused by code like this:
var x = StringResourcesBug.Resources.Strings.Resource.Test;

After a lot of trial an error, I found out the reason for this is the name of the class in the Resource.Designer.cs file.
If you create a rest file with the name Resource.resx you are running into this issue.
Renaming the file to Resources.resx and the Class to Resources fixes the issue

But the project was building on .net6 and .net7. Also iOs version in .net8 with Resouce.resx is building and is able to run.
So I looks like a Android specific thing to me.

Steps to Reproduce

  1. Clone the Repo
  2. Open the Solution in VSCode or VS4Mac
  3. Compile the Solution while Targeting Android Emulator

Link to public reproduction project repository

https://github.com/Larhei/Maui-Issues/tree/main/StringResourcesBug

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

7.0.101

Affected platforms

Android

Affected platform versions

all android

Did you find any workaround?

Renaming the resx file and the name of the class in *.Designer.cs

Relevant log output

No response

@mattleibow
Copy link
Member

@jonathanpeppers thoughts?

@jonathanpeppers
Copy link
Member

Having a Resource.resx could certainly conflict with the Android Resource.designer.cs:

https://github.com/Larhei/Maui-Issues/blob/main/StringResourcesBug/StringResourcesBug/Resources/Strings/Resource.resx

This is the same as if you created a plain C# Resource class yourself with the same namespace.

I don't think this actually changed in .NET 8 at all, would have happened back in Xamarin.Android as well? @dellis1972 do you think the same?

@Larhei
Copy link
Author

Larhei commented Nov 29, 2023

@jonathanpeppers

That my git diff tells me the changes to my csproj are:
<TargetFrameworks>net7.0-android;net7.0-ios</TargetFrameworks> changed to <TargetFrameworks>net8.0-android;net8.0-ios</TargetFrameworks>

added
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" /> <PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
and changed

<Compile Update="Resources\Strings\Resource.Designer.cs"> <DesignTime>True</DesignTime> <AutoGen>True</AutoGen> <DependentUpon>Resource.resx</DependentUpon> </Compile>
<EmbeddedResource Update="Resources\Strings\Resource.resx"> <Generator>PublicResXFileCodeGenerator</Generator> <LastGenOutput>Resource.Designer.cs</LastGenOutput> </EmbeddedResource>

to

<Compile Update="Resources\Strings\Resources.Designer.cs"> <DependentUpon>Resources.resx</DependentUpon> </Compile>
<EmbeddedResource Update="Resources\Strings\Resources.resx"> <Generator>ResXFileCodeGenerator</Generator> <LastGenOutput>Resources.Designer.cs</LastGenOutput> </EmbeddedResource>

And the old Code was building on Mac with .net7 and is in Android and iOS store.

@jonathanpeppers
Copy link
Member

@Larhei can you share a .binlog of when it worked (and doesn't now?) https://aka.ms/binlog

@Larhei
Copy link
Author

Larhei commented Nov 29, 2023

@jonathanpeppers

Well I will try my best ;-)

@ghost
Copy link

ghost commented Nov 29, 2023

Hi @Larhei. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@Larhei
Copy link
Author

Larhei commented Nov 29, 2023

@jonathanpeppers

here we go
Binlogs.zip

Same Machine
Same VS
Same Project
Only difference is TFM 7 and TFM 8

@dellis1972
Copy link
Contributor

Probably conflicting with obj/Debug/net8.0-android/__Microsoft.Android.Resource.Designer.cs . Which in itself is a partial class, so if the resx code is also partial it should have worked.

@jonathanpeppers
Copy link
Member

I think both .NET 7/8 were partial, though:

> cat .\obj\Debug\net7.0-android\Resource.designer.cs | select -First 25
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

[assembly: global::Android.Runtime.ResourceDesignerAttribute("testlib.Resource", IsApplication=false)]

namespace testlib
{


        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.1.99.94")]
        public partial class Resource

vs:

> cat obj\Debug\net8.0-android\__Microsoft.Android.Resource.Designer.cs
//------------------------------------------------------------------------------
// <auto-generated>
//      This code was generated by a tool. DO NOT EDIT
// </auto-generated>
//------------------------------------------------------------------------------
using System;

namespace testlib {
        #pragma warning disable IDE0002
        public partial class Resource : _Microsoft.Android.Resource.Designer.ResourceConstant {
        }
        #pragma warning restore IDE0002
}

It's weird that 7 works somehow?

@dellis1972
Copy link
Contributor

I know. Its the inheritance, doh 🤦

@dellis1972
Copy link
Contributor

dellis1972 commented Nov 29, 2023

I bet the resx class, does not inherit from anything. That would throw off the compiler maybe.

@dellis1972
Copy link
Contributor

actually that should not clash as its in a different namespace StringResourcesBug.Resources.Strings. The android designer will be in StringResourcesBug.Resource.

@the-gozo
Copy link

Do you have .NET Upgrade Assistant extension installed in VS? What is the build propety of your .resx files? It should be MauiResource or something similar. For me I had a similar issue: the Assistant extension somehow set my resources files build property to AndroidResource. If this is the case, chek all your other resources(images, ttf, icons).

@last-Programmer
Copy link

I am also having this issue with Android resources. Resource.Designer.cs file is not beging created for Android resources. I am getting the error in the IDE CS0117 but when i build it it is building. I have the old Resource.designer.cs from xamarin android project and it is never getting updated with newly address reosurces.

@dellis1972
Copy link
Contributor

@last-Programmer if you are targetting .net 8 the old Resource.designer.cs is now redundant and can be deleted. See https://devblogs.microsoft.com/dotnet/android-resource-designer-dotnet-8/ for details.

@last-Programmer
Copy link

@dellis1972 Thank You very much. I missed that part. Wont i get the intellisense for resource ids any more? because in vs for mac i get the ide error CS0117 at present. Is there a way to get around this. ? In the article it does not say anything about intellisense or error CS0117

@dellis1972
Copy link
Contributor

@last-Programmer if you have the full details of the CS0117 error please post them here.

@last-Programmer
Copy link

@dellis1972 It seems to be that the error CS0117 is happening only in VS for MAC and not in VS for Windows with newly created .net8 Android application

Steps to reproduce in VS for Mac.

Create a new net8.0 android application and open MainActivity.cs and you can see that at Resource.Layout.* error CS0117 is shown. However it builds fine. I suspect because .net 8.0 is only preview support in VS for Mac and it is not supported fully. Any workarounds?

@dellis1972
Copy link
Contributor

@last-Programmer not that I'm aware of. Its likely that VSForMac is not handling the new system, it might still be trying to make use of the old system. I'll mention it to my collegue on the IDE team see if they can take a look.

@samhouts samhouts changed the title [Bug] .net8 Android not building because Resources from resx not found. [regression/8.0.3] [Bug] .net8 Android not building because Resources from resx not found. Dec 7, 2023
@ninachen03
Copy link

I used the Repo project and reproduced the problem in 17.6.9 build (415 )on android platform.
image

@jonpryor
Copy link
Member

@dellis1972, @moljac

@dellis1972
Copy link
Contributor

dellis1972 commented Jun 25, 2024

//Removed as it was incorrect

@Larhei
Copy link
Author

Larhei commented Jun 25, 2024

@dellis1972
But my Resource.resx generates the namespace
namespace StringResourcesBug.Resources.Strings

and __Microsoft.Android.Resource.Designer
namespace StringResourcesBug

for me this looks like 2 different namespaces

so i would say that there are 2 different classes named Resource in separate namespaces..

@dellis1972
Copy link
Contributor

Ok ignore ALL of what I said. This is the actual problem

Target "_RemoveLegacyDesigner: (TargetId:213)" in file "/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/34.0.79/tools/Xamarin.Android.Common.targets" from project "/Users/dean/Documents/Sandbox/Repos/customer-repoductions/StringResourcesBug/C/C.csproj" (target "UpdateGeneratedFiles" depends on it):
                   Added Item(s): CorrectCasedItem=Resources/Strings/Resource.Designer.cs
                   Removed Item(s): 
                       Compile=
                           Resources/Strings/Resource.Designer.cs
                                   DependentUpon=Resource.resx

The new system has a target which removes the old legacy resource designer. In this case it is incorrectly removing the one which is for the Resource.resx from the Compile group.

@dellis1972
Copy link
Contributor

Its because they have the same filename. We need to make the target a bit less agressive and ignore items which have the DependentUpon. metadata I think.

@dellis1972
Copy link
Contributor

So fixing the issue by checking for DependentUpon metadata works but then you end up with the following error

 error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists

This is because the two Resource classes have different declarations public partial Resource vs internal Resource.
The Resource.designer.cs will need to have its modifier changed to public partial in order for the app to compile. Once that is done it will work as expected.

@Larhei
Copy link
Author

Larhei commented Jun 26, 2024

@dellis1972

Sorry to bother you again. But something seems to be fishy here.
The documentation of CS0260 states:

This error also occurs if you declare a class and accidentally give it the same name as a partial class that's declared elsewhere in the same namespace.

When doing some sample like this:

{
    private static void Main(string[] args)
    {
        Console.WriteLine("Hello, World!");
        var x = new Test.A();
        var y = new Test1.A();
        Console.WriteLine($"{x.Test} {x.Test1}");
        Console.WriteLine($"{y.Test} {y.Test1}");
    }
}

namespace Test
{
    public partial class A
    {
        public string Test { get; set; } = "ATest";
    }

    partial class A
    {

        public string Test1 { get; set; } = "ATest1";
    }
}

namespace Test1
{
    internal partial class A
    {
        public string Test { get; set; } = "A1Test";
    }

    internal partial class A
    {

        public string Test1 { get; set; } = "A1Test1";
    }
}

It compiles without an error. If i understand it correct, My internal partial class Resource is in an other namespace. So I don´t understand why we get CA0260.

If making my class public solves the issue. Fine. But I don´t understand why I should have to do that.

@dellis1972
Copy link
Contributor

This represents what the situation is.

{
    private static void Main(string[] args)
    {
        Console.WriteLine("Hello, World!");
        var y = new Test1.A();
        Console.WriteLine($"{y.Test} {y.Test1}");
    }
}

namespace Test
{
// this represents the code in the auto generated _Microsoft.Android.Resource.Designer.dll
    public partial class Base1
    {
        public string Test { get; set; } = "ATest";
    }
}

namespace Test1
{
    public partial class A : Base1 // this represents the code in the auto generated __Microsoft.Android.Resource.Designer.cs file
    {
        public string Test { get; set; } = "A1Test";
    }

    internal class A // This is the Resource.designer.cs for the resx
    {

        public string Test1 { get; set; } = "A1Test1";
    }
}

@Larhei
Copy link
Author

Larhei commented Jun 26, 2024

@dellis1972
What is even more interesting, in my sample my Resource class is not even a partial class.
it is

namespace StringResourcesBug.Resources.Strings {
internal class Resource {
}
}

vs

namespace StringResourcesBug {
public partial class Resource : _Microsoft.Android.Resource.Designer.ResourceConstant {
}
}

@dellis1972
Copy link
Contributor

I'm adding a new MSbuild properrty to allow the access modifier of the Resource : _Microsoft.Android.Resource.Designer.ResourceConstant class to be changed. It will still be partail, but it could be made internal or private or public in the application project. For Library projects it will always need to be public for legacy reasons.

That said if someone wants to change it an it breaks their code because they did Library1.Resource.Id.foo from their main application and the Library1.Resource class is no longer public (because they changed it) then its not really our issue.

@dellis1972
Copy link
Contributor

@Larhei actually given your classes are in different namespaces it might be ok for you. It was just something that I came up agsinst while trying to implement a unit test.

@Larhei
Copy link
Author

Larhei commented Jun 26, 2024

@dellis1972
So if i got you correct

My

namespace StringResourcesBug.Resources.Strings {
internal class Resource {
}
}

Gets an generated

namespace StringResourcesBug.Resources.Strings {
public partial class Resource : _Microsoft.Android.Resource.Designer.ResourceConstant{
}
}

Correct?

If so. That´s explaining why we get CS0260.

If this is the case.. On other option would be to generate all Propties from the internal class Resource into the public partial class Resource : _Microsoft.Android.Resource.Designer.ResourceConstant and remove internal class Resource from MsBuild... But this is also giving me a headache...

@dellis1972
Copy link
Contributor

@dellis1972 So if i got you correct

My

namespace StringResourcesBug.Resources.Strings {
internal class Resource {
}
}

Gets an generated

namespace StringResourcesBug.Resources.Strings {
public partial class Resource : _Microsoft.Android.Resource.Designer.ResourceConstant{
}
}

Correct?

If so. That´s explaining why we get CS0260.

If this is the case.. On other option would be to generate all Propties from the internal class Resource into the public partial class Resource : _Microsoft.Android.Resource.Designer.ResourceConstant and remove internal class Resource from MsBuild... But this is also giving me a headache...

Sorry there was some confusion, you probably won't hit the CS0260 (but I was in my unit test)

you will be getting

namespace StringResourcesBug.Resources.Strings {
internal class Resource {
}
}

Gets an generated (note the namespace is different)

namespace StringResourcesBug{
public partial class Resource : _Microsoft.Android.Resource.Designer.ResourceConstant{
}
}

Which will work once I get the fix in.
My test was testing classes in the same namespace, which is why I was getting the CS0260.

dellis1972 referenced this issue in dellis1972/xamarin-android Jun 26, 2024
Fixes https://github.com/dotnet/maui/issues/19117

With the release of the new Resource Designer assembly we purposely
removed the existing legacy `Resource.designer.cs` file from the
`@(Compile)` ItemGroup. This is so that we did not get any clashes
with the new system.

Unfortunately the name `Resource.designer.cs` is also used by
developers as the name for the generated class when using `.resx` files.
As a result we got the above bug report because the class was disappearing.

```
error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)
```

It turns out that the `_RemoveLegacyDesigner` was being a bit too aggressive
with its removal of files. Because it was matching on filename only it was
removing files which had nothing to do with Android Resources. This would
cause the above error.

The fix in this case is to check for additional metadata. In the case of
`.resx` file designers they typically have a `DependentUpon` metadata to
signal that they are generated from the `.resx`. So we should check this
metadata to make sure it is NOT set before removing a file.

A new unit test was added to test this fix and it worked. But it did show
up one other issue. In certain cases we would end up with two `Resource`
classes in the same namespace. This would then cause the following
build error.

```
error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists
```

This is because the two classes had different modifiers. We could also get
an error if the access modifiers are different (public vs internal).
So lets add a new MSBuild property `AndroidResourceDesignerClassModifier`.
This property defaults to `public`, but can be overridden by the user to
control the access modifier of the generated class.
@Larhei
Copy link
Author

Larhei commented Jun 26, 2024

@dellis1972
Tanks for clarifications

dellis1972 referenced this issue in dellis1972/xamarin-android Jul 1, 2024
Fixes https://github.com/dotnet/maui/issues/19117

With the release of the new Resource Designer assembly we purposely
removed the existing legacy `Resource.designer.cs` file from the
`@(Compile)` ItemGroup. This is so that we did not get any clashes
with the new system.

Unfortunately the name `Resource.designer.cs` is also used by
developers as the name for the generated class when using `.resx` files.
As a result we got the above bug report because the class was disappearing.

```
error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)
```

It turns out that the `_RemoveLegacyDesigner` was being a bit too aggressive
with its removal of files. Because it was matching on filename only it was
removing files which had nothing to do with Android Resources. This would
cause the above error.

The fix in this case is to check for additional metadata. In the case of
`.resx` file designers they typically have a `DependentUpon` metadata to
signal that they are generated from the `.resx`. So we should check this
metadata to make sure it is NOT set before removing a file.

A new unit test was added to test this fix and it worked. But it did show
up one other issue. In certain cases we would end up with two `Resource`
classes in the same namespace. This would then cause the following
build error.

```
error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists
```

This is because the two classes had different modifiers. We could also get
an error if the access modifiers are different (public vs internal).
So lets add a new MSBuild property `AndroidResourceDesignerClassModifier`.
This property defaults to `public`, but can be overridden by the user to
control the access modifier of the generated class.
dellis1972 referenced this issue in dellis1972/xamarin-android Jul 2, 2024
Fixes https://github.com/dotnet/maui/issues/19117

With the release of the new Resource Designer assembly we purposely
removed the existing legacy `Resource.designer.cs` file from the
`@(Compile)` ItemGroup. This is so that we did not get any clashes
with the new system.

Unfortunately the name `Resource.designer.cs` is also used by
developers as the name for the generated class when using `.resx` files.
As a result we got the above bug report because the class was disappearing.

```
error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)
```

It turns out that the `_RemoveLegacyDesigner` was being a bit too aggressive
with its removal of files. Because it was matching on filename only it was
removing files which had nothing to do with Android Resources. This would
cause the above error.

The fix in this case is to check for additional metadata. In the case of
`.resx` file designers they typically have a `DependentUpon` metadata to
signal that they are generated from the `.resx`. So we should check this
metadata to make sure it is NOT set before removing a file.

A new unit test was added to test this fix and it worked. But it did show
up one other issue. In certain cases we would end up with two `Resource`
classes in the same namespace. This would then cause the following
build error.

```
error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists
```

This is because the two classes had different modifiers. We could also get
an error if the access modifiers are different (public vs internal).
So lets add a new MSBuild property `AndroidResourceDesignerClassModifier`.
This property defaults to `public`, but can be overridden by the user to
control the access modifier of the generated class.
dellis1972 referenced this issue in dellis1972/xamarin-android Jul 3, 2024
Fixes https://github.com/dotnet/maui/issues/19117

With the release of the new Resource Designer assembly we purposely
removed the existing legacy `Resource.designer.cs` file from the
`@(Compile)` ItemGroup. This is so that we did not get any clashes
with the new system.

Unfortunately the name `Resource.designer.cs` is also used by
developers as the name for the generated class when using `.resx` files.
As a result we got the above bug report because the class was disappearing.

```
error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)
```

It turns out that the `_RemoveLegacyDesigner` was being a bit too aggressive
with its removal of files. Because it was matching on filename only it was
removing files which had nothing to do with Android Resources. This would
cause the above error.

The fix in this case is to check for additional metadata. In the case of
`.resx` file designers they typically have a `DependentUpon` metadata to
signal that they are generated from the `.resx`. So we should check this
metadata to make sure it is NOT set before removing a file.

A new unit test was added to test this fix and it worked. But it did show
up one other issue. In certain cases we would end up with two `Resource`
classes in the same namespace. This would then cause the following
build error.

```
error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists
```

This is because the two classes had different modifiers. We could also get
an error if the access modifiers are different (public vs internal).
So lets add a new MSBuild property `AndroidResourceDesignerClassModifier`.
This property defaults to `public`, but can be overridden by the user to
control the access modifier of the generated class.
dellis1972 referenced this issue in dellis1972/xamarin-android Jul 9, 2024
Fixes https://github.com/dotnet/maui/issues/19117

With the release of the new Resource Designer assembly we purposely
removed the existing legacy `Resource.designer.cs` file from the
`@(Compile)` ItemGroup. This is so that we did not get any clashes
with the new system.

Unfortunately the name `Resource.designer.cs` is also used by
developers as the name for the generated class when using `.resx` files.
As a result we got the above bug report because the class was disappearing.

```
error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)
```

It turns out that the `_RemoveLegacyDesigner` was being a bit too aggressive
with its removal of files. Because it was matching on filename only it was
removing files which had nothing to do with Android Resources. This would
cause the above error.

The fix in this case is to check for additional metadata. In the case of
`.resx` file designers they typically have a `DependentUpon` metadata to
signal that they are generated from the `.resx`. So we should check this
metadata to make sure it is NOT set before removing a file.

A new unit test was added to test this fix and it worked. But it did show
up one other issue. In certain cases we would end up with two `Resource`
classes in the same namespace. This would then cause the following
build error.

```
error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists
```

This is because the two classes had different modifiers. We could also get
an error if the access modifiers are different (public vs internal).
So lets add a new MSBuild property `AndroidResourceDesignerClassModifier`.
This property defaults to `public`, but can be overridden by the user to
control the access modifier of the generated class.
dellis1972 referenced this issue in dellis1972/xamarin-android Jul 16, 2024
Fixes https://github.com/dotnet/maui/issues/19117

With the release of the new Resource Designer assembly we purposely
removed the existing legacy `Resource.designer.cs` file from the
`@(Compile)` ItemGroup. This is so that we did not get any clashes
with the new system.

Unfortunately the name `Resource.designer.cs` is also used by
developers as the name for the generated class when using `.resx` files.
As a result we got the above bug report because the class was disappearing.

```
error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)
```

It turns out that the `_RemoveLegacyDesigner` was being a bit too aggressive
with its removal of files. Because it was matching on filename only it was
removing files which had nothing to do with Android Resources. This would
cause the above error.

The fix in this case is to check for additional metadata. In the case of
`.resx` file designers they typically have a `DependentUpon` metadata to
signal that they are generated from the `.resx`. So we should check this
metadata to make sure it is NOT set before removing a file.

A new unit test was added to test this fix and it worked. But it did show
up one other issue. In certain cases we would end up with two `Resource`
classes in the same namespace. This would then cause the following
build error.

```
error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists
```

This is because the two classes had different modifiers. We could also get
an error if the access modifiers are different (public vs internal).
So lets add a new MSBuild property `AndroidResourceDesignerClassModifier`.
This property defaults to `public`, but can be overridden by the user to
control the access modifier of the generated class.
@PureWeen PureWeen transferred this issue from dotnet/maui Aug 2, 2024
@dotnet-policy-service dotnet-policy-service bot added the needs-triage Issues that need to be assigned. label Aug 2, 2024
@jpobst jpobst added Area: App+Library Build Issues when building Library projects or Application projects. and removed needs-triage Issues that need to be assigned. labels Aug 16, 2024
jonpryor pushed a commit that referenced this issue Oct 15, 2024
…9057)

Fixes: #9163

Context: dc3ccf2
Context: 3ec1b15

With the release of the new Resource Designer assembly (dc3ccf2)
purposely removed the existing legacy `Resource.designer.cs` file
from the `@(Compile)` ItemGroup.  This is so that we did not get any
clashes with the new system.

Unfortunately the name `Resource.designer.cs` is also used by
developers as the name for the generated class when using `.resx`
files.  As a result we got the following CS0234 error because the
class was disappearing:

	error CS0234: The type or namespace name 'Resources' does not exist in the namespace 'StringResourcesBug' (are you missing an assembly reference?)

It turns out that the `_RemoveLegacyDesigner` was being a bit too
aggressive with its removal of files.  Because it was matching on
filename only it was removing files which had nothing to do with
Android Resources.  This would cause the above CS0234 error.

The fix in this case is to check for additional metadata.  In the
case of `.resx` file designers they typically have `%(DependentUpon)`
metadata to signal that they are generated from the `.resx`.

We should check `%(DependentUpon)` to make sure it is NOT set before
removing a file from the `@(Compile)` item group.

A new unit test was added to test this fix and it worked.  But it did
show up one other issue: in certain cases we would end up with two
`Resource` classes in the same namespace. This would then cause the
following build error.

	error CS0260: Missing partial modifier on declaration of type 'Resource'; another partial declaration of this type exists

This is because the two classes had different modifiers.  We could
also get an error if the access modifiers are different (`public` vs
`internal`).

Add a new MSBuild property `$(AndroidResourceDesignerClassModifier)`.
This property defaults to `public`, but can be overridden by the user
to control the access modifier of the generated class.

Also we have to remove the `[GeneratedCode]` Attribute usage on the
generated `Resource` class, as it can conflict with the one that is
auto added to the `Resource.designer.cs` generated by the `resx` code
generator.  If we leave this in place we get the following error.

	__Microsoft.Android.Resource.Designer.cs(15,3,15,16): error CS0579: Duplicate 'GeneratedCode' attribute

Unfortunately [`GeneratedCodeAttribute`][1] is marked as
`AllowMultiple=false` and in this case there is no way to know if it
exists on the class already as its a `partial` class.

[1]: https://learn.microsoft.com/en-us/dotnet/api/system.codedom.compiler.generatedcodeattribute?view=net-8.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: App+Library Build Issues when building Library projects or Application projects.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants