Forum Xamarin.iOS

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

MTouchLink can break BSON HTTP Requests

ScottDavisScottDavis USMember ✭✭
edited February 2016 in Xamarin.iOS

I'm sharing this in the hopes that it saves someone else the 4 days I lost on this issue.

At some point in the previous week one of my developers checked in a change to the csproj file for our iOS project. Piled on top of that check-in was many Android and Windows phone commits to our source tree. A week later, when we went back to test iOS, we found our BSON api was now sending and receiving empty objects for iOS only. Same code in all three projects, but only iOS was broken. No exceptions, no errors, but all objects contained either no data or mostly incomplete data. Something had broken BSON serialization. It took 4 days of debugging, tracing, and finally rolling back dozes of commits one at a time to find the problem.

The iOS project csproj file included a new directive <MTouchLink>Full</MTouchLink> This single setting broke BSON serialization, but did not cause any errors. The reasons are more clear now, but this was perhaps the most obscure bug to track down and I hope no one else hits it. We aren't sure how the setting got switch, it was probably a simple mistake, but the cost was very high.

I emailed support for an explanation, which I've included below. Thank you to Jon Goldberger for his explanation.

-----Start email copy------------

<MtouchLink>Full</MtouchLink>
is likely what caused your issue, and why it was added with value "Full" I do not know. I suspect the developer who added the binding project changed that setting, perhaps misunderstanding the meaning of what "Link All" is (this is the name of the option in the GUI Project Properties editor that adds that element with that value). What this setting does is set how the linker will optimize the assemblies to shrink them by removing code from referenced assemblies that is not used in your iOS project. These XML elements in the .csproj file correlate to the Linker Behavior options in the project Options(Xamarin Studio)/Properties(VisualStudio) in the iOS Build settings page. There are three options seen in the GUI editor for the Project Options/.Properties:

"Don't Link"

This is the default (and recommended) setting for Debug or simulator builds. If this is set in the GUI, the element in the .csproj file will be:
<MtouchLink>None</MtouchLink>
With this setting no assemblies will have unused code stripped away and you will have a needlessly large app size. However this option allows for much faster builds and thus is recommended during development for Debug and simulator builds.

"Link SDK Frameworks Only" ("Link SDK Assemblies Only" in Visual Studio)
This is the default (and recommended) setting) for Release and device builds (although the "Don't Link" option is fine for Debug device builds too). If this is set in the GUI, there will be no <MTouchLink> element in the .csproj as this is the default when that element is missing.
With this setting, only the Xamarin SDK assemblies (Xamarin.iOS, Mono.Android, and the System.* references included with the Xamarin SDK) will ave code stripped from them based on what is not used in your code. this is a very safe option to use as we can be very careful about what we strip out, and any 3rd party or user assemblies are not "linked" (read "optimized"... yes, the nomenclature is confusing). This is the setting you had before the change that made your app not work. (XML MTouchLink element was missing in .csproj file).

"Link All" ("Link All assemblies" in Visual Studio)
This setting should only be used if you have to reduce your final app size and must be used with care. If this is set in the GUI, the element in the .csproj file will be:
<MtouchLink>Full</MtouchLink>
With this setting the Linker will try to optimize all assemblies, including user and 3rd party referenced assemblies, i.e. NuGet packages, referenced PCLs, referenced projects in the same solution. etc. The problem here is that the Linker can only use static code analysis to try to determine what code is used from the 3rd party/user assemblies and will often miss things, especially if types, methods, etc. are accessed using reflection or other similar mechanisms from your source code. If you need to use the Link All option, be prepared to have to manually preserve types, methods, etc. that you know will need from the 3rd party/user assemblies. So with this option selected, as you indicated, some needed types, methods, etc. were stripped from your referenced assemblies causing the issues you described, like breaking an http request likely due to http code having been stripped out of one of your referenced assemblies, whether your own or a NuGet package, etc.

Posts

  • Thanks for sharing - very useful information!

  • fhintschfhintsch Member

    Four years later – and still or again (?) a problem with MtouchLink?

    If I run my app on iOS with the Debug|iPhone configuration, it is working well.
    If I switch to Ad-hoc|iPhone or Release|iPhone configuration, the app is loaded and started on the iPhone but crashes immediately (not really - it seems to be forced into background). After adding

    <MtouchLink>None</MtouchLink>

    to the configuration the problem is gone.

Sign In or Register to comment.