[build] generate Errors.Designer.cs for runtime assemblies (#8763)

Fixes: https://github.com/xamarin/xamarin-macios/issues/8467
Fixes: https://github.com/xamarin/xamarin-macios/issues/8727

If you add this code to an `AppDelegate.cs`:

    [Export ("f:")]
    public void F (DateTime t) { }

This will cause an exception at runtime, on purpose.

Instead of the actual error string, you get:

    System.Resources.MissingManifestResourceException:
      Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "Errors.mtouch.resources" was correctly embedded or linked into assembly "Xamarin.iOS" at compile time, or that all the satellite assemblies required are loadable and fully signed.
      ...
      at Xamarin.Bundler.Errors.get_MT4102 () [0x00000] in tools/mtouch/Errors.Designer.cs:1582

In 00985a55, `mtouch/Errors.designer.cs` was added to various .NET
assemblies, so things would compile. Unfortunately, the `.resx` file
was not included as an `EmbeddedResource`.

*Compiled* `.resx` files are generated by MSBuild:

e3146f30df/src/Tasks/GenerateResource.cs

Or via `resgen.exe`:

https://docs.microsoft.com/dotnet/framework/resources/creating-resource-files-for-desktop-apps

Instead of using this, we could just generate `Errors.Designer.cs`
ourselves. I wrote a small `generate-errors.csharp` script that will
parse the `.resx` file generating `internal const` fields. This will
be more performant at runtime and work well with the linker. The `const`
strings will be compiled into the IL inline if done this way.

After doing this, I got the correct error message in VS for Mac:

    Could not register the assembly 'brokenlocalization': ObjCRuntime.RuntimeException: The registrar found an invalid type `System.DateTime` in signature for method `brokenlocalization.AppDelegate.F`. Use `Foundation.NSDate` instead.
      at Registrar.Registrar.ToSignature (System.Type type, Registrar.Registrar+ObjCMember member, System.Boolean& success, System.Boolean forProperty) [0x00380] in src/ObjCRuntime/Registrar.cs:2611
      at Registrar.Registrar.ComputeSignature (System.Type declaring_type, System.Boolean is_ctor, System.Type return_type, System.Type[] parameters, System.Reflection.MethodBase mi, Registrar.Registrar+ObjCMember member, System.Boolean isCategoryInstance, System.Boolean isBlockSignature) [0x00113] in src/ObjCRuntime/Registrar.cs:2526
      at Registrar.Registrar.ComputeSignature (System.Type DeclaringType, System.Reflection.MethodBase Method, Registrar.Registrar+ObjCMember member, System.Boolean isCategoryInstance, System.Boolean isBlockSignature) [0x00059] in src/ObjCRuntime/Registrar.cs:2492
      at Registrar.Registrar+ObjCMethod.ComputeSignature () [0x00000] in src/ObjCRuntime/Registrar.cs:923

Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
This commit is contained in:
Jonathan Peppers 2020-06-05 10:27:57 -05:00 коммит произвёл GitHub
Родитель d4bd5a5b4a
Коммит 050453fa4b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 46 добавлений и 4 удалений

Просмотреть файл

@ -98,6 +98,11 @@ ARGS_32 = -define:ARCH_32
ARGS_64 = -define:ARCH_64
SHARED_SYSTEM_DRAWING_SOURCES = System.Drawing/PointSizeRectangleTypeForwarders.cs
SHARED_RESX = $(TOP)/tools/mtouch/Errors.resx
SHARED_DESIGNER_CS = $(BUILD_DIR)/common/Errors.Designer.cs
$(SHARED_DESIGNER_CS): $(SHARED_RESX)
./generate-errors.csharp > $(SHARED_DESIGNER_CS)
#
# Xamarin.iOS
@ -109,7 +114,7 @@ IOS_EXTRA_SOURCES = \
$(IOS_OPENTK_1_0_CORE_SOURCES) \
$(IOS_BUILD_DIR)/Constants.cs \
$(IOS_BUILD_DIR)/AssemblyInfo.cs \
$(TOP)/tools/mtouch/Errors.Designer.cs \
$(SHARED_DESIGNER_CS) \
$(SHARED_SYSTEM_DRAWING_SOURCES) \
IOS_HTTP_SOURCES = \
@ -429,7 +434,7 @@ MAC_SOURCES += \
$(MAC_BUILD_DIR)/AssemblyInfo.cs \
Darwin/KernelNotification.cs \
Darwin/SystemLog.cs \
$(TOP)/tools/mtouch/Errors.Designer.cs \
$(SHARED_DESIGNER_CS) \
# CFNetwork is shipped:
# * In a separate library (XamMac.CFNetwork.dll) for Classic.
@ -722,7 +727,7 @@ WATCHOS_CORE_SOURCES += \
WATCHOS_SOURCES += \
$(WATCHOS_EXTRA_CORE_SOURCES) \
$(WATCHOS_HTTP_SOURCES) \
$(TOP)/tools/mtouch/Errors.Designer.cs \
$(SHARED_DESIGNER_CS) \
$(WATCH_BUILD_DIR)/Constants.cs: $(TOP)/src/Constants.watch.cs.in Makefile $(TOP)/Make.config.inc | $(WATCH_BUILD_DIR)
$(call Q_PROF_GEN,watch) sed \
@ -947,7 +952,7 @@ TVOS_HTTP_SOURCES = \
Foundation/NSUrlSessionHandler.cs \
System.Net.Http/CFContentStream.cs \
System.Net.Http/CFNetworkHandler.cs \
$(TOP)/tools/mtouch/Errors.Designer.cs \
$(SHARED_DESIGNER_CS) \
TVOS_SOURCES += \
$(TVOS_EXTRA_CORE_SOURCES) \

37
src/generate-errors.csharp Executable file
Просмотреть файл

@ -0,0 +1,37 @@
#!/usr/bin/env /Library/Frameworks/Mono.framework/Commands/csharp
using System.IO;
using System.Xml;
var args = Environment.GetCommandLineArgs ();
var dir = Path.GetDirectoryName (args [1]);
var file = Path.Combine (dir, "..", "tools", "mtouch", "Errors.resx");
var doc = new XmlDocument ();
doc.Load (file);
Console.Write (
@"//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool: generate-errors.csharp
// </auto-generated>
//------------------------------------------------------------------------------
namespace Xamarin.Bundler {
internal class Errors {
");
foreach (XmlNode node in doc.SelectNodes ("/root/data")) {
var name = node.Attributes ["name"].InnerText;
if (name == "default") {
name = "@" + name;
}
var value = node.ChildNodes [1].InnerText
.Trim ()
.Replace ("\\", "\\\\")
.Replace ("\"", "\\\"");
Console.WriteLine ($"\t\tinternal const string {name} = \"{value}\";");
}
Console.WriteLine ("\t}\n}");
Environment.Exit (0);