I've been attempting to get Microsoft Entity Framework Core 2.0 working in a Xamarin.iOS application with full linking enabled. EF Core is a large library — exactly the kind that could benefit from linking. Discovering all the critical types/methods to preserve in a LinkDescription XML file has been tedious, owing to extensive reflection and use of DI in EF Core 2.0, but I've been making progress, one crash at a time. (There's also hope that ER Core could one day have linker hints built in.)
However, I hit a major blocker: When EF Core creates a database from a model, it reads its own AssemblyInformationalVersion attribute to preserve in generated metadata. But the Xamarin.iOS linker strips assembly attributes from an assembly that is not link-skipped. So, in an app with full linking enabled, EF Core is crashing as it gets nothing back from reading the desired attribute value.
This behaviour appears to be an intentional linker feature, perhaps desirable and harmless in many cases — but for cases where it is a problem, there exists no fine-grained directive to preserve assembly attributes, as one could do with plain types/methods in a LinkDescription XML file.
The only workaround at present is to go back to link-skipping the large EF Core main assembly, and put up with the resulting bloat. For a small app that doesn't use EF Core's more advanced features, the unnecessary bloat may be considerable. (I haven't measured potential avoidable bloat yet, as I'm blocked from getting to the point where I could compare a working iOS app with full linking vs. one that link-skips EF Core.)
Steps to Reproduce (without EF Core; just the essential issue)
- Create a new Xamarin.iOS project using the Single View app template.
- In the project's iOS build settings for platform "iPhone" (real device), set linker behavior to "Link All".
- In AppDelegate.cs'
FinishedLaunching() method, add the following line before the return:
System.Diagnostics.Debug.WriteLine("TODO");
- Change the build to target a real iOS device, then build and run with debugging. Notice "TODO" is printed in the debug output. i.e. The basic application works with full linking.
- In Properties/AssemblyInfo.cs, append the following line:
[assembly: AssemblyInformationalVersion("1.0.0.0")]
- From the ProductInfo.cs file from the EF Core 2.0.0 repository, copy and paste just the ProductInfo class definition into AppDelegate.cs, before the AppDelegate class definition.
- Change the
Debug.WriteLine() call added in step 1 to read:
System.Diagnostics.Debug.WriteLine("Version: " + ProductInfo.GetVersion());.
- Build and run with debugging. Instead of seeing "Informational version: 1.0.0.0" in the debugger output, the application crashes with
System.NullReferenceException: Object reference not set to an instance of an object.
If you were to expand the one-liner from EF Core's GetVersion() method into multiple statements and intermediate values instead, you would see that the null reference is the attribute object from which the InformationalVersion property would have been accessed. If you were to change linking back to "Link SDK Assemblies Only", you would avoid the crash and see the expected output.
Expected Behavior
It should be possible to configure the linker to specifically preserve assembly attributes when the need arises — i.e. without completely opting out of linking an assembly.
Developers of .NET Standard class libraries should be able to rely on reading their own assembly's attribute information. Linking should aim to exclude only unnecessary types, methods, and other data from an assembly. Beyond types and methods, when the linker assumes that a kind of thing can safely be excluded, it should provide a fine-grained directive to preserve some or all of the kinds-of-things, for cases where the assumption has been proven unsafe for a specific assembly.
Actual Behavior
Crash. The present workaround requires completely opting out of linking for an assembly that relies on reading its own assembly attributes.
However, linking remains highly desirable for large library dependencies used in mobile applications. The case in point is not only a very large .NET Standard library, but a popular data access framework promoted by Microsoft as cross-platform capable, which ideally would include mobile applications with on-device data access needs.
Environment
Microsoft Visual Studio Community 2017
Version 15.5.7
VisualStudio.15.Release/15.5.7+27130.2036
Microsoft .NET Framework
Version 4.7.02556
Installed Version: Community
Visual Basic 2017 00369-60000-00001-AA398
Microsoft Visual Basic 2017
Visual C# 2017 00369-60000-00001-AA398
Microsoft Visual C# 2017
Visual C++ 2017 00369-60000-00001-AA398
Microsoft Visual C++ 2017
Visual F# 4.1 00369-60000-00001-AA398
Microsoft Visual F# 4.1
Add New File 3.5
The fastest and easiest way to add new files to any project - including files that start with a dot
Application Insights Tools for Visual Studio Package 8.10.01106.1
Application Insights Tools for Visual Studio
ASP.NET and Web Tools 2017 15.0.31129.0
ASP.NET and Web Tools 2017
ASP.NET Core Razor Language Services 1.0
Provides languages services for ASP.NET Core Razor.
ASP.NET Web Frameworks and Tools 2012 4.0.20601.0
For additional information, visit https://www.asp.net/
ASP.NET Web Frameworks and Tools 2017 5.2.51007.0
For additional information, visit https://www.asp.net/
Azure App Service Tools v3.0.0 15.0.31106.0
Azure App Service Tools v3.0.0
CodeMaid 10.4.53
CodeMaid is an open source Visual Studio extension to cleanup and simplify our C#, C++, F#, VB, PHP, PowerShell, R, JSON, XAML, XML, ASP, HTML, CSS, LESS, SCSS, JavaScript and TypeScript coding.
Common Azure Tools 1.10
Provides common services for use by Azure Mobile Services and Microsoft Azure Tools.
GitHub.VisualStudio 2.4.2.1331
A Visual Studio Extension that brings the GitHub Flow into Visual Studio.
JavaScript Language Service 2.0
JavaScript Language Service
JavaScript Project System 2.0
JavaScript Project System
JavaScript UWP Project System 2.0
JavaScript UWP Project System
JetBrains ReSharper Ultimate 2017.2.2 Build 109.0.20171006.122324
JetBrains ReSharper Ultimate package for Microsoft Visual Studio. For more information about ReSharper Ultimate, visit http://www.jetbrains.com/resharper. Copyright © 2018 JetBrains, Inc.
Merq 1.1.17-rc (cba4571)
Command Bus, Event Stream and Async Manager for Visual Studio extensions.
Microsoft Continuous Delivery Tools for Visual Studio 0.3
Simplifying the configuration of continuous build integration and continuous build delivery from within the Visual Studio IDE.
Microsoft JVM Debugger 1.0
Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines
Microsoft MI-Based Debugger 1.0
Provides support for connecting Visual Studio to MI compatible debuggers
Microsoft Visual C++ Wizards 1.0
Microsoft Visual C++ Wizards
Microsoft Visual Studio Tools for Containers 1.1
Develop, run, validate your ASP.NET Core applications in the target environment. F5 your application directly into a container with debugging, or CTRL + F5 to edit & refresh your app without having to rebuild the container.
Microsoft Visual Studio VC Package 1.0
Microsoft Visual Studio VC Package
Mono Debugging for Visual Studio 4.8.4-pre (3fe64e3)
Support for debugging Mono processes with Visual Studio.
Node.js Tools 1.4.11025.7
Adds support for developing and debugging Node.js apps in Visual Studio
NuGet Package Manager 4.5.0
NuGet Package Manager in Visual Studio. For more information about NuGet, visit http://docs.nuget.org/.
Open Command Line 2.1.179
Opens a command line at the root of the project. Support for all consoles such as CMD, PowerShell, Bash etc. Provides syntax highlighting, Intellisense and execution of .cmd and .bat files.
Search in Velocity by Silverlake Software LLC 0.7.1
Provides a command to search in Velocity the offline documentation and docset viewer for Windows
SQL Server Data Tools 15.1.61710.120
Microsoft SQL Server Data Tools
SQLite & SQL Server Compact Toolbox 4.7
SQLite & SQL Server Compact Toolbox adds scripting, import, export, rename, query execution and much more to SQL Server Compact & SQLite Data Connections.
Syntax Visualizer 1.0
An extension for visualizing Roslyn SyntaxTrees.
TypeScript Tools 15.5.11025.1
TypeScript Tools for Microsoft Visual Studio
Visual Studio Code Debug Adapter Host Package 1.0
Interop layer for hosting Visual Studio Code debug adapters in Visual Studio
Visual Studio Tools for Universal Windows Apps 15.0.27130.2036
The Visual Studio Tools for Universal Windows apps allow you to build a single universal app experience that can reach every device running Windows 10: phone, tablet, PC, and more. It includes the Microsoft Windows 10 Software Development Kit.
VisualStudio.Mac 1.0
Mac Extension for Visual Studio
VSColorOutput 2.5.1
Color output for build and debug windows - http://mike-ward.net/vscoloroutput
Xamarin 4.8.0.760 (fc93f3f5b)
Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.
Xamarin Designer 4.8.188 (c5813fa34)
Visual Studio extension to enable Xamarin Designer tools in Visual Studio.
Xamarin.Android SDK 8.1.5.0 (HEAD/75f8c6838)
Xamarin.Android Reference Assemblies and MSBuild support.
Xamarin.iOS and Xamarin.Mac SDK 11.6.1.4 (db807ec)
Xamarin.iOS and Xamarin.Mac Reference Assemblies and MSBuild support.
Build Logs
1>------ Rebuild All started: Project: TestXamLinkIssue, Configuration: Debug iPhone ------
1> Connecting to Mac server cwrea-mini...
1> TestXamLinkIssue -> D:\Projects\TestXamLinkIssueSoln\TestXamLinkIssue\bin\iPhone\Debug\TestXamLinkIssue.exe
1> Detected signing identity:
1> Code Signing Key: "iPhone Developer: [...]" (...)
1> Provisioning Profile: "cwrea iOS Dev Prov. Profile" (...)
1> Bundle Id: com.companyname.TestXamLinkIssue
1> App Id: J7ADM89KY9.com.companyname.TestXamLinkIssue
1> /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip: removing global symbols from a final linked no longer supported. Use -exported_symbols_list at link time when building: /Users/cwrea/Library/Caches/Xamarin/mtbs/builds/TestXamLinkIssue/a101bae86211f0bd1960357a25c90492/bin/iPhone/Debug/TestXamLinkIssue.app/TestXamLinkIssue
1> bin/iPhone/Debug/TestXamLinkIssue.app: valid on disk
1> bin/iPhone/Debug/TestXamLinkIssue.app: satisfies its Designated Requirement
1> bin/iPhone/Debug/TestXamLinkIssue.app: explicit requirement satisfied
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
Projects build report:
Status | Project [Config|platform]
-----------|---------------------------------------------------------------------------------------------------
Succeeded | TestXamLinkIssue\TestXamLinkIssue.csproj [Debug|iPhone]
Time Elapsed 00:00:22.323
I've been attempting to get Microsoft Entity Framework Core 2.0 working in a Xamarin.iOS application with full linking enabled. EF Core is a large library — exactly the kind that could benefit from linking. Discovering all the critical types/methods to preserve in a LinkDescription XML file has been tedious, owing to extensive reflection and use of DI in EF Core 2.0, but I've been making progress, one crash at a time. (There's also hope that ER Core could one day have linker hints built in.)
However, I hit a major blocker: When EF Core creates a database from a model, it reads its own
AssemblyInformationalVersionattribute to preserve in generated metadata. But the Xamarin.iOS linker strips assembly attributes from an assembly that is not link-skipped. So, in an app with full linking enabled, EF Core is crashing as it gets nothing back from reading the desired attribute value.This behaviour appears to be an intentional linker feature, perhaps desirable and harmless in many cases — but for cases where it is a problem, there exists no fine-grained directive to preserve assembly attributes, as one could do with plain types/methods in a LinkDescription XML file.
The only workaround at present is to go back to link-skipping the large EF Core main assembly, and put up with the resulting bloat. For a small app that doesn't use EF Core's more advanced features, the unnecessary bloat may be considerable. (I haven't measured potential avoidable bloat yet, as I'm blocked from getting to the point where I could compare a working iOS app with full linking vs. one that link-skips EF Core.)
Steps to Reproduce (without EF Core; just the essential issue)
FinishedLaunching()method, add the following line before the return:System.Diagnostics.Debug.WriteLine("TODO");[assembly: AssemblyInformationalVersion("1.0.0.0")]Debug.WriteLine()call added in step 1 to read:System.Diagnostics.Debug.WriteLine("Version: " + ProductInfo.GetVersion());.System.NullReferenceException: Object reference not set to an instance of an object.If you were to expand the one-liner from EF Core's
GetVersion()method into multiple statements and intermediate values instead, you would see that the null reference is the attribute object from which the InformationalVersion property would have been accessed. If you were to change linking back to "Link SDK Assemblies Only", you would avoid the crash and see the expected output.Expected Behavior
It should be possible to configure the linker to specifically preserve assembly attributes when the need arises — i.e. without completely opting out of linking an assembly.
Developers of .NET Standard class libraries should be able to rely on reading their own assembly's attribute information. Linking should aim to exclude only unnecessary types, methods, and other data from an assembly. Beyond types and methods, when the linker assumes that a kind of thing can safely be excluded, it should provide a fine-grained directive to preserve some or all of the kinds-of-things, for cases where the assumption has been proven unsafe for a specific assembly.
Actual Behavior
Crash. The present workaround requires completely opting out of linking for an assembly that relies on reading its own assembly attributes.
However, linking remains highly desirable for large library dependencies used in mobile applications. The case in point is not only a very large .NET Standard library, but a popular data access framework promoted by Microsoft as cross-platform capable, which ideally would include mobile applications with on-device data access needs.
Environment
Build Logs