Bug 1416 - Linker in 1.9.1 removing override methods?
Summary: Linker in 1.9.1 removing override methods?
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: MSBuild ()
Version: 1.0
Hardware: PC Windows
: High normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-10-11 08:03 UTC by andrew
Modified: 2012-03-23 15:49 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Sample solution (769.39 KB, application/x-zip-compressed)
2011-11-02 16:38 UTC, andrew
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description andrew 2011-10-11 08:03:40 UTC
I installed 1.9.1 and built a project that was working fine with 1.9.0.

The OnDraw method of a custom view was no longer invoked. It looked like:

        protected override void OnDraw(Canvas canvas)
        {
            // blah
        }

I uninstalled 1.9.1 and put 1.9.0 back - the method was invoked.

I'm guessing that this is related to the smarter linker in 1.9.1?

I'm also guessing that I can use the Preserve attribute to prevent the method from being stripped, but it's going to be a pain to go through all such methods and do this.
Comment 1 Jonathan Pobst 2011-10-11 12:48:45 UTC
For Linking options, do you have "Link SDK Only" or "Link SDK and User Assemblies"?

If you are doing both, does changing it to Link SDK Only fix it?
Comment 2 Jonathan Pobst 2011-10-14 10:59:59 UTC
I tried running our sample "Snake" which uses a custom view with an OnDraw method, but I am not seeing this behavior:

https://github.com/xamarin/monodroid-samples/tree/master/Snake

https://github.com/xamarin/monodroid-samples/blob/master/Snake/Classes/TileView.cs

Can you produce a test case that shows this behavior?
Comment 3 andrew 2011-10-14 12:19:36 UTC
I'll try and re-install 1.9.1 and create a test case.

There are 2 things which might complicate matters in my case:
a) the whole method is surrounded by a #if/#endif
b) the class declaration uses a using:

using Control = Android.Views.View;
eg. public class MyView : Control

But I think both of these would've been resolved by the time the linker takes effect. And everything works fine as-is with 1.9.0.

I'll get back to you when I can.
Comment 4 andrew 2011-11-02 12:09:31 UTC
I've now tried this on 1.9.2 and get the same issue. There are some complicating factors like the .NET dlls being obfuscated, but I've narrowed it down a bit:

At the _LinkAssemblies stage the dll containing OnDraw is contained in obj\Release\assemblies - this dll has the method all present and correct.

The msbuild log then says:

    Target _LinkAssemblies:
        LinkAssemblies Task
          UseSharedRuntime: False
          MainAssembly: obj\Release\assemblies\magic5.dll
          OutputDirectory: obj\Release\android\assets\
          I18nAssemblies: 
          LinkMode: Full
          ResolvedAssemblies:
            obj\Release\assemblies\magic5.dll
            obj\Release\assemblies\Mono.Android.dll
            obj\Release\assemblies\mscorlib.dll
            obj\Release\assemblies\System.Core.dll
            obj\Release\assemblies\System.dll
            obj\Release\assemblies\Mono.Security.dll
            obj\Release\assemblies\AndroidUIMD.dll
            obj\Release\assemblies\System.Xml.dll
            obj\Release\assemblies\Mono.Data.Sqlite.dll
            obj\Release\assemblies\System.Data.dll
            obj\Release\assemblies\Mono.Data.Tds.dll
            obj\Release\assemblies\System.Transactions.dll
            obj\Release\assemblies\ICSharpCode.SharpZipLib.dll
        Creating "obj\Release\link.flag" because "AlwaysCreate" was specified.
    Target _PrepareAssemblies:
          Files
            obj\Release\android\assets\magic5.dll
            obj\Release\android\assets\Mono.Android.dll
            obj\Release\android\assets\mscorlib.dll
            obj\Release\android\assets\System.Core.dll
            obj\Release\android\assets\System.dll
            obj\Release\android\assets\Mono.Security.dll
            obj\Release\android\assets\AndroidUIMD.dll
            obj\Release\android\assets\System.Xml.dll
            obj\Release\android\assets\Mono.Data.Sqlite.dll
            obj\Release\android\assets\System.Data.dll
            obj\Release\android\assets\Mono.Data.Tds.dll
            obj\Release\android\assets\System.Transactions.dll
            obj\Release\android\assets\ICSharpCode.SharpZipLib.dll
          [Output] FilesThatExist
            obj\Release\android\assets\magic5.dll
            obj\Release\android\assets\Mono.Android.dll
            obj\Release\android\assets\mscorlib.dll
            obj\Release\android\assets\System.Core.dll
            obj\Release\android\assets\System.dll
            obj\Release\android\assets\Mono.Security.dll
            obj\Release\android\assets\AndroidUIMD.dll
            obj\Release\android\assets\System.Xml.dll
            obj\Release\android\assets\Mono.Data.Sqlite.dll
            obj\Release\android\assets\System.Data.dll
            obj\Release\android\assets\System.Transactions.dll
            obj\Release\android\assets\ICSharpCode.SharpZipLib.dll
          Files
            obj\Release\android\assets\Mono.Android.dll.mdb
            obj\Release\android\assets\mscorlib.dll.mdb
            obj\Release\android\assets\System.Core.dll.mdb
            obj\Release\android\assets\System.dll.mdb
            obj\Release\android\assets\Mono.Security.dll.mdb
            obj\Release\android\assets\System.Xml.dll.mdb
            obj\Release\android\assets\Mono.Data.Sqlite.dll.mdb
            obj\Release\android\assets\System.Data.dll.mdb
            obj\Release\android\assets\Mono.Data.Tds.dll.mdb
            obj\Release\android\assets\System.Transactions.dll.mdb
          [Output] FilesThatExist
            obj\Release\android\assets\Mono.Android.dll.mdb
            obj\Release\android\assets\mscorlib.dll.mdb
            obj\Release\android\assets\System.Core.dll.mdb
            obj\Release\android\assets\System.dll.mdb
            obj\Release\android\assets\Mono.Security.dll.mdb
            obj\Release\android\assets\System.Xml.dll.mdb
            obj\Release\android\assets\Mono.Data.Sqlite.dll.mdb
            obj\Release\android\assets\System.Data.dll.mdb
            obj\Release\android\assets\System.Transactions.dll.mdb
          Files
            obj\Release\android\assets\magic5.dll
            obj\Release\android\assets\AndroidUIMD.dll
            obj\Release\android\assets\ICSharpCode.SharpZipLib.dll
          [Output] FilesThatExist
            obj\Release\android\assets\magic5.dll
            obj\Release\android\assets\AndroidUIMD.dll
            obj\Release\android\assets\ICSharpCode.SharpZipLib.dll
          Files
            obj\Release\android\assets\Mono.Android.dll
            obj\Release\android\assets\mscorlib.dll
            obj\Release\android\assets\System.Core.dll
            obj\Release\android\assets\System.dll
            obj\Release\android\assets\Mono.Security.dll
            obj\Release\android\assets\System.Xml.dll
            obj\Release\android\assets\Mono.Data.Sqlite.dll
            obj\Release\android\assets\System.Data.dll
            obj\Release\android\assets\Mono.Data.Tds.dll
            obj\Release\android\assets\System.Transactions.dll
          [Output] FilesThatExist
            obj\Release\android\assets\Mono.Android.dll
            obj\Release\android\assets\mscorlib.dll
            obj\Release\android\assets\System.Core.dll
            obj\Release\android\assets\System.dll
            obj\Release\android\assets\Mono.Security.dll
            obj\Release\android\assets\System.Xml.dll
            obj\Release\android\assets\Mono.Data.Sqlite.dll
            obj\Release\android\assets\System.Data.dll
            obj\Release\android\assets\System.Transactions.dll
    Target _GenerateJavaStubs:
          ResolvedAssemblies:
            obj\Release\android\assets\magic5.dll
            obj\Release\android\assets\Mono.Android.dll
            obj\Release\android\assets\mscorlib.dll
            obj\Release\android\assets\System.Core.dll
            obj\Release\android\assets\System.dll
            obj\Release\android\assets\Mono.Security.dll
            obj\Release\android\assets\AndroidUIMD.dll
            obj\Release\android\assets\System.Xml.dll
            obj\Release\android\assets\Mono.Data.Sqlite.dll
            obj\Release\android\assets\System.Data.dll
            obj\Release\android\assets\System.Transactions.dll
            obj\Release\android\assets\ICSharpCode.SharpZipLib.dll
          ResolvedUserAssemblies:
            obj\Release\android\assets\magic5.dll
            obj\Release\android\assets\AndroidUIMD.dll
            obj\Release\android\assets\ICSharpCode.SharpZipLib.dll
        RemoveRegisterAttribute Task
          ResolvedFrameworkAssemblies:
            obj\Release\android\assets\Mono.Android.dll
            obj\Release\android\assets\mscorlib.dll
            obj\Release\android\assets\System.Core.dll
            obj\Release\android\assets\System.dll
            obj\Release\android\assets\Mono.Security.dll
            obj\Release\android\assets\System.Xml.dll
            obj\Release\android\assets\Mono.Data.Sqlite.dll
            obj\Release\android\assets\System.Data.dll
            obj\Release\android\assets\System.Transactions.dll
        Touching "obj\Release\android\AndroidManifest.xml".

and the dll in obj\Release\android\assets no longer has the method.

As I mentioned before, this only fails in 1.9.1 and 1.9.2. Is there anything in the project setting that I can change? As you can see from the log, link mode is set to Full.
Comment 5 Jonathan Pobst 2011-11-02 12:12:41 UTC
You can try setting link mode to SDK Only, and then it will no longer link your assemblies, so that should work.  I would also love to fix this, but I cannot reproduce it, so I need a test case that demonstrates the issue.
Comment 6 andrew 2011-11-02 12:32:23 UTC
If I send you the dll would that be enough?
Comment 7 Jonathan Pobst 2011-11-02 14:38:30 UTC
Really I need the source, but I just need the source of the class that is misbehaving.  And you can take all your interesting logic out of it.  I just need to see how how the OnDraw is being called, and maybe how the custom View is being created.

I posted above an example of a custom View that works, so I need to see how yours is different.
Comment 8 andrew 2011-11-02 16:37:12 UTC
I've created (surprisingly easily) a reproduction of this in a much smaller solution. I'll attach it shortly.

There are two projects - the main exe and a class library dll. The custom View class is in the dll. I did a release build and deploy with linking of user assemblies. The final dll (pre-Java) doesn't contain OnDraw.

Just to clarify, now I come to think of it... in the original, large project there all sorts of other methods which are missing, mostly things like OnTouchEvent, OnSizeChanged - methods which aren't invoked directly by the application, only by the Android framework.

Anyway, I'll upload the solution, have a look for OnDraw in the TestWithOnDraw class of ClassLibrary.
Comment 9 andrew 2011-11-02 16:38:05 UTC
Created attachment 811 [details]
Sample solution
Comment 10 Jonathan Pobst 2011-11-03 11:44:54 UTC
Seems like this is caused by the custom View being in a class library instead of the main application.

This can be worked around by moving the class to the main application, or using "Link Sdk Assemblies" instead of "Link Sdk and User Assemblies".
Comment 11 andrew 2011-11-03 11:49:49 UTC
OK, I can work around it in that way, that's not a problem.

Are you planning to revert things to pre-1.9.1 and allow such classes to be in the class library and "Link Sdk and User Assemblies"? Or is this how it's going to remain from now on?
Comment 12 Jonathan Pobst 2011-11-03 11:52:08 UTC
We won't revert the linker changes, as it was a big win, reducing Marketplace apk sizes by over a megabyte.  But we do consider this behavior regression a bug, and will work to fix it in a future version.
Comment 13 Atsushi Eno 2011-11-04 13:25:10 UTC
Your sample in comment #9 contained the following line in Activity2.cs:

            ViewGroup main = (ViewGroup) this.FindViewById(1);

But I believe this is wrong. When I rewrote it to 

            TestWithOnDraw test = new TestWithOnDraw(this, null);
            EditText b = (EditText) this.FindViewById(Resource.Id.tb1);
            ViewGroup main = (ViewGroup) b.Parent;

The Activity2 just launched.

Don't you have similar wrong ID reference in your project? Please make sure to use valid ID.
Comment 14 andrew 2011-11-04 13:28:49 UTC
Hi,

Yes, I just put the 1 in there to make it compile, I was in a hurry to get a solution that would build and which would show that methods went missing during the compilation and linking.

So... the application probably doesn't run at all, it was only the absence of OnDraw in the dll that I was trying to illustrate.

Apologies if this has wasted your time.
Comment 15 Atsushi Eno 2011-11-04 22:02:49 UTC
No worries. If you still have problem in your app apart from the example repro, please come up with another repro and we'll have a look.
Comment 16 Jonathan Pobst 2011-11-05 00:13:44 UTC
It's fine, I already fixed the sample locally and can reproduce the problem.
Comment 17 Atsushi Eno 2011-11-07 04:18:03 UTC
That's weird. I cannot reproduce the problem on either device (ASUS transformer) or emulator i.e. I can see "Test" outputs on the logs.
Comment 18 andrew 2011-11-07 04:22:45 UTC
Atsushi,

The sample that I produced probably doesn't show anything when it's run, so there's nothing to see in terms of running the app... I just made it so that when it was compiled the OnDraw method wasn't in the .apk. I assume that if the method is in the compiled apk then it'll be called OK at runtime, but if it isn't then that's a different bug.

Hope that helps, sorry for any confusion.

Andrew
Comment 19 Atsushi Eno 2011-11-14 16:27:30 UTC
Sorry but I cannot parse what you said. If there isn't code for OnDraw() in the resulting .apk, it must not print "Test". But it does print "Test", so it must exist (at least on my machine and environment).
Comment 20 andrew 2011-11-17 04:50:14 UTC
Atsushi,

Sorry that my reply made no sense. If you can see the Test message then your environment isn't showing the same problem that mine is.

In his message above Jonathan says that he can reproduce the problem, so can it be left with him?
Comment 21 Eric Beisecker 2012-03-15 16:44:06 UTC
Hello Andrew,

Are you still experiencing this issue with our most current version of Mono for Android?
Comment 25 Jonathan Pobst 2012-03-23 15:49:26 UTC
Fixed for 4.2.

713f4fdcaee71ecdb64f4b09d10cc96ba639b39a