* [registrar] Make a copy of the static registrar for Xamarin.Mac/Classic.
Make a copy of the static registrar for Xamarin.Mac/Classic, one which is
compatible with the binary artifacts we ship for Xamarin.Mac/Classic
(libxammac, XamMac.dll).
This way the static registrar can evolve in the future, without breaking
Xamarin.Mac/Classic.
* [runtime] Make a copy of the runtime headers too.
* Update comment.
* [mmp] Delay creating a Target instance until we know if we're a Classic or Unified app.
Otherwise the wrong static registrar might be created.
According to Rolf it's fine to always add since the native linker will
figure out if it's really needed and so customers don't need to do
anything when using -all_load.
* [linker] Remove non-bitcode compatible code, and show a warning.
Remove code not currently compatible with bitcode and replace it with an
exception instead (otherwise we'll assert at runtime).
Also show a warning when we detect this.
This is quite helpful when looking at watch device test runs to filter out
failures we already know about.
This fixes point #2 in #4763.
* Improve documentation.
* Simplify linker code by using a substep.
* Fix whitespace issues.
* Improve reporting.
* Add support for reporting more than one MT2105 at the same time when making
the errors instead of warnings.
* Only report MT2105 for methods that haven't been linked away.
* Format the error message nicer for properties.
* Tweak a bit for warning tests to pass.
* Use ExceptionalSubStep to provide better error information.
* Adjust where linker warnings/errors are reported from to avoid a NullReferenceException.
Improved linker to:
* Not mark protocol interfaces by the mere virtue of having a type that
implements them. This is implemented by not marking protocol interfaces when
they're implementing a class, but instead when a method implementation is
found to implement a method from a protocol interface.
* Mark the wrapper type for protocols (this allows us to remove the Protocol
attribute, since that's the link between the protocol and its wrapper type).
* Remove the [Protocol], [ProtocolMember] and [Adopts] attributes.
The static registrar still needs some of the information linked away, so a few
changes are required to make it available post linker.
You were the preprocessor we wished C# had natively
Removing PMCS requires these changes:
* Remove XamCore from src/
* Remove XamCore from tools/
* Remove XamCore from runtime/
* nint/nuint enum conversion
* _compat_ enum conversion
* NSAction conversion
* Hand fix single API incorrectly converted by PMCS to unbreak compatibility
- Due to a bug in PMCS, the nuint was incorrectly converted in this API.
- However, as that ship as sailed, we must "fix" it until XAMCORE_4_0
* Update readme
* Bump macios-binaries
* [linker] Implement a generic method of storing attributes that may be removed by the linker.
Implement a generic method of storing attributes that may be removed by the
linker, so that those attributes can be accessed after the linker has linked
them away.
* [linker] Store availability attributes using the new generic location.
* [linker] Store the CompilerGenerated attribute using the new generic location.
Previous behavior
=================
* The linker would determine if a class is a generated binding class or not.
This was determined by the presence of a constructor taking a single IntPtr
argument, and with a [CompilerGenerated] attribute.
* If a class was not a generated binding class, then that class and all its
superclasses were marked as not optimizable (in the context of inlining the
IsDirectBinding check).
* The end result was that all classes with a [CompilerGenerated] IntPtr
constructor that weren't subclassed, were optimized (the IsDirectBinding
value was implied to be 'true').
Unfortunately this does not match how the IsDirectBinding value is actually
computed, and is in many cases quite wrong.
Background
==========
The authorative value for the IsDirectBinding value is the register attribute:
```csharp
[Register ("MyClass", true)] // the second parameter specifies the IsDirectBinding value
class MyClass : NSObject {}
```
Due to history this second parameter is called `IsWrapper` and not
`IsDirectBinding`, but it's the exact same thing.
Unfortunately looking up this attribute every time a class is instantiated is
slow (since fetching attributes is slow), so we guess this value in NSObject's
initialization: if the actual type of the object is in the platform assembly,
then we assume IsDirectBinding=true:
```csharp
IsDirectBinding = (this.GetType ().Assembly == PlatformAssembly);
```
and any subclasses in the platform assembly which is not a direct binding have
to set the correct value in their constructors.
New behavior
============
In the linker we now track three states for the IsDirectBinding value for each
class: if it can be inlined into a constant true or false, or if it has to be
checked at runtime (a nullable bool is used, and null corresponds with this
last undetermined state).
* The linker will look at the `[Register]` attribute for a class, and:
* If the type is CIFilter, store that IsDirectBinding=undetermined.
* If IsWrapper=False, store that IsDirectBinding=False for that class, and
that IsDirectBinding=undetermined for all super classes where
IsWrapper=True.
* If IsWrapper=True, tentatively assume IsDirectBinding=True in that class
unless already determined to be undetermined (which will be overruled if
a non-wrapper subclass is found later).
Results
=======
For monotouch-test, the changes are as follows:
* Classes we can now assume IsDirectBinding=true: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L1-L25
* Classes we previously assumed incorrectly that IsDirectBinding=true: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L27-L645
* Classes we can now assume IsDirectBinding=false: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L647-L2281
There are also minor size improvements (in the iPhone/Debug64 configuration):
The executable is 17.632 bytes smaller:
-rwxr-xr-x 1 rolf staff 73038384 Jan 12 12:40 /Users/rolf/test/old/monotouchtest.app/monotouchtest
-rwxr-xr-x 1 rolf staff 73020752 Jan 12 12:50 /Users/rolf/test/new/monotouchtest.app/monotouchtest
Xamarin.iOS.dll is 3.072 bytes smaller (this will probably be 0 on a release (stripped) build).
-rw-r--r-- 1 rolf staff 2522624 Jan 12 12:40 /Users/rolf/test/old/monotouchtest.app/Xamarin.iOS.dll
-rw-r--r-- 1 rolf staff 2519552 Jan 12 12:50 /Users/rolf/test/new/monotouchtest.app/Xamarin.iOS.dll
CIFilter
========
There's a complication with CIFilters [1] [2], their implementation is
somewhat special, so we do not want to optimize anything for those classes to
not risk getting anything wrong.
[1] https://github.com/xamarin/xamarin-macios/pull/3055
[2] https://bugzilla.xamarin.com/show_bug.cgi?id=15465
* [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes#51710 and #54417.
* Refactor required symbol collection to store more information about each
symbol (field, function, Objective-C class), and in general make the code
more straight forward.
* Implement support for generating source code that references these symbols,
and do this whenever we can't ask the native linker to keep these symbols
(when using bitcode). Additionally make it possible to do this manually, so
that the source code can be generated for non-bitcode platforms too (which
is useful if the number of symbols is enormous, in which case we might
surpass the maximum command-line length).
* Also make it possible to completely ignore native symbols, or ignore them on
a per-symbol basis. This provides a fallback for users if we get something
right and we try to preserve something that shouldn't be preserved (for
instance if it doesn't exist), and the user ends up with unfixable linker
errors.
* Don't collect Objective-C classes unless they're in an assembly with
LinkWith attributes. We don't need to preserve Objective-C classes in any
other circumstances.
* Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the
code between them.
* Remove previous workaround for bug #51710, since it's no longer needed.
* Add tests.
https://bugzilla.xamarin.com/show_bug.cgi?id=54417https://bugzilla.xamarin.com/show_bug.cgi?id=51710
* [mtouch] Make sure to only keep symbols from the current app when code sharing.
This fixes a build problem with the interdependent-binding-projects test when
testing in Today Extension mode.
The native linker treats object files (.o) and static libraries (.a files,
which are archives of .o files) differently.
The native linker will always include object files into the executable:
$ echo "void xxx () {}" > foo.m
$ clang -c foo.m -o foo.o -arch x86_64
$ ld foo.o -dylib -o foo.dylib -macosx_version_min 10.12 -arch x86_64
$ nm foo.dylib
0000000000000fe0 T _xxx
However, if the object file is inside a static library:
$ echo "void xxx () {}" > foo.m
$ clang -c foo.m -o foo.o -arch x86_64
$ ar cru foo.a foo.o
$ ld foo.a -dylib -o foo.dylib -macosx_version_min 10.12 -arch x86_64
$ nm foo.dylib
<no output>
This means that our testing library (libtest.a) which is a fat library of
_object files_, do not show the problems reported in bug #51548.
So:
a) I've fixed the creation of libtest.a to be a fat library of _static
libraries_. This causes the `FastDev_LinkWithTest` test to fail exactly
like in bug #51548.
b) I've made mtouch pass `-u <native symbol>` to the native linker, for every
native symbol referenced in a managed assembly, when creating a dylib.
Amazingly this seems to work fine even with symbols to Objective-C classes
(`_OBJC_CLASS_$_<class name>`).
c) This also required adding support for collecting the Objective-C names of
all managed types registered with Objective-C to the linker. The
information is already available in the static registrar, but that would
require us to make sure the static registrar is executed before compiling
dylibs, which means those two tasks won't be able to run in parallel (also
there's no guarantee we'll even run the static registrar).
https://bugzilla.xamarin.com/show_bug.cgi?id=51548