Reputation: 26505
If I build my app with "Link SDK only" for a release build (for beta testing on machines without Mono), it no longer starts up--it seems to crash immediately.
Here is the crash if I run my app command line:
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: An exception was thrown by the type initializer for System.Xml.Serialization.XmlSerializer ---> System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system. ---> System.MissingMethodException: Default constructor not found for type System.Configuration.ExeConfigurationHost.
at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in <filename unknown>:0
at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0
at System.Configuration.InternalConfigurationSystem.Init (System.Type typeConfigHost, System.Object[] hostInitParams) [0x00000] in <filename unknown>:0
at System.Configuration.InternalConfigurationFactory.Create (System.Type typeConfigHost, System.Object[] hostInitConfigurationParams) [0x00000] in <filename unknown>:0
at System.Configuration.ConfigurationManager.OpenExeConfigurationInternal (ConfigurationUserLevel userLevel, System.Reflection.Assembly calling_assembly, System.String exePath) [0x00000] in <filename unknown>:0
at System.Configuration.ClientConfigurationSystem.get_Configuration () [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at System.Configuration.ClientConfigurationSystem.get_Configuration () [0x00000] in <filename unknown>:0
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection (System.String configKey) [0x00000] in <filename unknown>:0
at System.Configuration.ConfigurationManager.GetSection (System.String sectionName) [0x00000] in <filename unknown>:0
at System.Configuration.ConfigurationSettings.GetConfig (System.String sectionName) [0x00000] in <filename unknown>:0
at System.Xml.Serialization.XmlSerializer..cctor () [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
Any way to add the appropriate [Preserve]
attribute here? Or maybe force the linker to keep this class?
Some more info:
Upvotes: 2
Views: 794
Reputation: 43553
A major difference for MMP (MonoMac Packer), when compared to MonoTouch's mtouch
, is that MonoMac uses the full .NET framework. That makes linking application a lot more complex.
Why ? mostly because of System.Configuration
(it's an assembly but it's also a namespace in several other assemblies). It uses reflection and .config
files to set itself up - and the linker can't know (since it can change between execution) exactly what's needed for your application.
MMP tries to cover the most common cases (e.g. System.Net) but it does not, currently, handle every case where System.Configuration is used inside the BCL.
Now to fix that... you need to tell the linker to include everything your application will need at runtime. E.g.
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException:
An exception was thrown by the type initializer for System.Xml.Serialization.XmlSerializer
---> System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system.
---> System.MissingMethodException: Default constructor not found for type System.Configuration.ExeConfigurationHost.
That means your application is using (even if indirectly) System.Configuration.ExeConfigurationHost
and the linker could not detect it (it's used thru reflection).
From there you need to build an XML file to teach the linker about those required types (there will be others, likely many others). That XML file is then fed back to MMP (--xml=FILE) so the linker won't try to remove those types/methods from your linked application.
Alternatives are not linking or not linking some assemblies (e.g. --linkskip=System
). YMMV.
UPDATE: The new Xamarin.Mac, a superset of MonoMac, contains an enhanced version of the linker that will solve this exception (but maybe not all the other ones, please fill bug report for them).
Upvotes: 4
Reputation: 1602
This happens because mmp (the MonoMac packager built into MonoDevelop) strips out too much from the framework. Especially when using XML.
I found you have to pass these additional arguments to mmp for XML to work:
--linkskip=System.Net --linkskip=System --linkskip=System.Configuration --linkskip=mscorlib
Unfortunately, the mmp arguments in the project config in monodevelop are not functional (do no save). I have reported these bugs and were fixed but don't seem like they will be available until a later version for some reason.
For now, you can run mmp from the command line. The build output shows the current command so you can use that but add the arguments above.
It is still quite worth while to do this, it took my app from 20mb down to 10mb even without linking those libraries.
Upvotes: 1
Reputation: 19345
A couple of ideas:
Upvotes: 1