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

"extern alias" added to auto generated Resource.designer.cs causes syntax errors #4542

Closed
bzd3y opened this issue Apr 8, 2020 · 10 comments · Fixed by #4554
Closed

"extern alias" added to auto generated Resource.designer.cs causes syntax errors #4542

bzd3y opened this issue Apr 8, 2020 · 10 comments · Fixed by #4554
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects.

Comments

@bzd3y
Copy link

bzd3y commented Apr 8, 2020

I've attached a sample project and the diagnostic build output when building in Visual Studio 16.4.6/Xamarin.Android.10.1 and VS 16.5.3/Xamarin.Android.10.2. The problematic behavior is also seen in VS 16.5.2.

When built with 10.1 the project builds as expected. No extern alias lines are added to the generated resource file.

When built with 10.2 the project fails to build because extern alias lines (in my sample there are 2) with invalid syntax from the project file are added to the generated resource file.

I understand this may be connected to #3808 and #4409 and their fixes, but it seems there is still an issue with how these lines are added or that they are added at all as they seem to be unnecessary. The aliased libraries are not referenced in the resource file and the project builds fine without them in 10.1.

I modeled my sample project after the real project that has <Aliases> tags added for references to the same two nuget packages used in my sample project. I didn't write this code, so there may be something else going on. It might be that it is not even correct and that is the root cause of the problem, but there is definitely a difference in the way it is handled between 10.1 and 10.2 that is less than ideal.

EDIT: One more thing that I should probably mention is that this behavior isn't seen when the packages are added as <PackageReference> tags in the project file. When they are added the "old way" with a package.config file and are added to the project file with a <Reference> tag the issue appears.

It might also be worth pointing out that I was hoping to update to 10.2 to avoid this issue: #18106 so right it seems like I am between a rock and a hard place.

xamarin.android.10.1.txt
xamarin.android.10.2.txt
App1.zip

@dellis1972
Copy link
Contributor

I think I know the problem. One of the Aliases is global.. That is a reserved word in C# and is already defined as an implicit alias.

The global alias, which is the global namespace alias. The global namespace is the namespace that contains namespaces and types that are not declared inside a named namespace. When used with the :: qualifier, the global alias always references the global namespace, even if there is the user-defined global namespace alias.

I think we might need to skip an alias if it is global otherwise we get this error

Error CS1681: You cannot redefine the global extern alias (CS1681)

To work around it, you can remove the global from the Aliases in the csproj. namespaces are automatically added to the global alias anyway, so it is redundant.

@bzd3y
Copy link
Author

bzd3y commented Apr 9, 2020

@dellis1972 Thanks for the response. You're right that global is the problem, but I can't remove it (I reverted to VS16.4.6 in the mean time, so I'm fine for now). Doing so breaks the areas of the project that actually use those aliases (you can't see this in the sample project because nothing actually uses them in that, sorry about that). It's defined as an implicit alias, but not all aliases are implicitly added to it which I believe was the intent of it being added to the project file. I suppose it's possible that I could refactor those parts to solve the problem, but that's not a decision I can make on my own with this code and, frankly, it seems like a large change to be forced to make.

I think you are right that the global needs to be ignored, so if that is a fix you guys are considering then that sounds good.

But beyond that, and in my perhaps unsolicited opinion, it seems like the extern alias statements should just not be added unconditionally to the resource file (it's unclear to me how they could even be used in a file that is automatically generated, I assume an XML file could reference it or something like that?). I don't know how realistic of a change that is and maybe there's really no harm in having them added and not used, but it seems like they could introduce errors to a file the developer has no control over, like identifier collisions or something like that. Off the top of my head, the first possibility that comes to mind would be adding a custom property to the resource file that lets the developer add a list of aliases to add to the generated file.

Just to be clear, I'm just throwing an idea out there. If the decision is that it always adds the aliases but ignores global then that seems like it will be good enough for most cases.

Thanks again!

@bzd3y
Copy link
Author

bzd3y commented Apr 13, 2020

@dellis1972 Sorry to seem impatient, but do you have a timeline on this? These two issues

mono/mono#18106
xamarin/xamarin-macios#7882

are forcing me to need to update to the newest VS sooner rather than later.

dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Apr 14, 2020
Fixes dotnet#4542

Our previous fix did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Apr 14, 2020
Fixes dotnet#4542

Our previous fix d18c824 did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
@dellis1972
Copy link
Contributor

I added a PR to fix this issue #4554. We will try to get this into master as soon as possible. I will check to see which release we can get this int.

With regards to the Aliases and the Designer.cs file, we have no way if knowing at generation time which ones will be used in the C# code since our file is generated before the code is compiled.
Also users a quite able to add this following

<Aliases>foo</Aliases>

We have code which calls a method in the referenced project such as

global::SomeLibrary.Resource.Color.searchBarTextHighlightColorDark = global::Fool.Resource.Color.searchBarTextHighlightColorDark;

this code ensures that the library project resource id's match those in the app.
If the user uses an alias (say Bar) but does not include the global one, the above code will not compile. This was the problem #3972 was fixing. We would need to emit

Bar::SomeLibrary.Resource.Color.searchBarTextHighlightColorDark = global::Fool.Resource.Color.searchBarTextHighlightColorDark;

When I did that fix, I didn't realise that you could add global to that list as well. That is probably why your code used to work fine since the type was added to the global as well as your custom one. That was not the case in #3972.

I guess if we wanted to only use the aliases when it was required, we might check the list for global and if it is not present then we need to emit one of the aliases so that code will compile. But if global is present in that list (or there are no aliases at all) then we don't need to emit that code. That might work.

@bzd3y
Copy link
Author

bzd3y commented Apr 14, 2020

Okay, thanks a lot. I appreciate how quickly you put the PR in.

I get your point about knowing when the aliases are used and I think you are right that it would be smart to have it not emit the aliases if global is in the list.

@brendanzagaeski
Copy link
Contributor

A little idea came to mind about a workaround you could use while waiting for the release of #4554. The idea is to add the following lines to the end of the app project .csproj file, just above the closing </Project> tag:

  <PropertyGroup>
    <CoreResolveReferencesDependsOn>
      $(CoreResolveReferencesDependsOn);
      _RemoveAliases
    </CoreResolveReferencesDependsOn>
  </PropertyGroup>
  <Target Name="_RemoveAliases">
    <ItemGroup>
      <_MonoAndroidReferencePathNew Include="@(_MonoAndroidReferencePath)" RemoveMetadata="Aliases" />
      <_MonoAndroidReferencePath Remove="@(_MonoAndroidReferencePath)" />
      <_MonoAndroidReferencePath Include="@(_MonoAndroidReferencePathNew)" />
    </ItemGroup>
  </Target>
</Project>

The @(_MonoAndroidReferencePath) items are a copied subset of the @(ReferencePath) items that are specific to the Xamarin.Android build tasks, and the only place the Aliases metadata from those items is used right now is when generating Resource.designer.cs. So it's safe to remove the Aliases metadata entirely from them for projects that don't need any extern alias lines in Resource.designer.cs.

One small caution with this approach is that the underscore prefix on _MonoAndroidReferencePath indicates that it isn't "public," so it might not always exist or have the same name across different Xamarin.Android versions. But since you'll only need the workaround until #4554 is available, that shouldn't be a problem.

Removing the Aliases metadata from the _MonoAndroidReferencePath items doesn't affect the ReferencePath items that the C# build process sees, so the C# build process will still uses the aliases as expected.

@bzd3y
Copy link
Author

bzd3y commented Apr 15, 2020

Okay, thanks. That makes sense. If it comes to it, I will try that. Right now I have the iPhone side mostly working with the workaround for the macOS issue. My colleague is running into this same problem now, so he might want to try this workout around instead.

I also just now saw an 16.5.4 update for VS. I didn't see this fix listed, but I wasn't sure if Xamarin issues would be listed under the VS release notes.

Either way, thanks for working on this.

dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Apr 22, 2020
Fixes dotnet#4542

Our previous fix d18c824 did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Apr 27, 2020
Fixes dotnet#4542

Our previous fix d18c824 did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Apr 28, 2020
Fixes dotnet#4542

Our previous fix d18c824 did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Apr 30, 2020
Fixes dotnet#4542

Our previous fix d18c824 did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Apr 30, 2020
Fixes dotnet#4542

Our previous fix d18c824 did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue May 5, 2020
Fixes dotnet#4542

Our previous fix d18c824 did not take into account that users might
need to add `global` to their list of aliases in the `ProjectReferece`
MetaData. This then causes the following error

	Error CS1681: You cannot redefine the global extern alias (CS1681)

So to fix this we need to ignore the `global` entry if one is present.
jonpryor pushed a commit that referenced this issue May 20, 2020
…e. (#4554)

Fixes: #4542

Our previous fix in d18c824 did not take into account that users
might need to add `global` to their list of aliases in the
`%(ProjectReference.Aliases)` metadata.  This then causes the
following error:

	Error CS1681: You cannot redefine the global extern alias (CS1681)

Fix this by ignoring the `global` entry if one is present.
jonpryor pushed a commit that referenced this issue May 26, 2020
…e. (#4554)

Fixes: #4542

Our previous fix in d18c824 did not take into account that users
might need to add `global` to their list of aliases in the
`%(ProjectReference.Aliases)` metadata.  This then causes the
following error:

	Error CS1681: You cannot redefine the global extern alias (CS1681)

Fix this by ignoring the `global` entry if one is present.
@brendanzagaeski
Copy link
Contributor

Release status update

A new Preview version of Xamarin.Android has now been published that includes the fix for this item. The fix is not yet included in a Release version. I will update this again when a Release version is available that includes the fix.

Fix included in Xamarin.Android 10.4.0.0.

Fix included on Windows in Visual Studio 2019 version 16.7 Preview 3. To try the Preview version that includes the fix, check for the latest updates in Visual Studio Preview.

Fix included on macOS in Visual Studio 2019 for Mac version 8.7 Preview 3. To try the Preview version that includes the fix, check for the latest updates on the Preview updater channel.

@brendanzagaeski
Copy link
Contributor

Release status update

A new Release version of Xamarin.Android has now been published that includes the fix for this item.

Fix included in Xamarin.Android SDK version 11.0.0.3.

Fix included on Windows in Visual Studio 2019 version 16.7. To get the new version that includes the fix, check for the latest updates or install the most recent release from https://visualstudio.microsoft.com/downloads/.

Fix included on macOS in Visual Studio 2019 for Mac version 8.7. To get the new version that includes the fix, check for the latest updates on the Stable updater channel.

@bzd3y
Copy link
Author

bzd3y commented Sep 15, 2020

Thanks everybody for working on this. I updated to this version a few days ago and everything works.

@ghost ghost locked as resolved and limited conversation to collaborators Jun 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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.

4 participants