Exact Behaviour of the Linker in Xamarin Studio

matt1701matt1701 Mathew ThampiUSMember
edited January 2014 in Xamarin.iOS

Hi
I posted this originally in the Studio forum but posting it here as well since it's specific to IOS development too.
Under Options->IOS Build there is a section for "Linker Behaviour". I always thought that if you set it to Link All Assemblies that Xamarin Studio would include all the referenced libraries when its compiling. However, now that I have read some documents, am I right in assuming that actually the linker behaves the opposite way and that the option Don't Link is the one that will include all the referenced libraries? I read somewhere that the linker actually strips stuff out rather than including stuff - am I right in this? I came upon this problem when building release builds and I always got the warning message shown in the screenshot below. However by setting the Linker Behaviour to Don't link these messages go away. I understand that the executable becomes bigger when you set the option to Don't Link but surely this is better than the Linker accidentally stripping away stuff you need? Hope someone can clarify this for me.

Posts

  • adamkempadamkemp Adam Kemp USInsider, Developer Group Leader mod

    The Xamarin "linker" has the opposite meaning from just about every other "linker" in the industry. I don't know why they named it that. It should be called "dead code eliminator" because that's what it does. When you choose "link all assemblies" that means "strip dead code from all assemblies", which has the effect of possibly removing code from the final product, not adding code. "Link None", on the other hand, will never strip dead code, thus possibly making your app bigger.

  • SebastienPouliotSebastienPouliot Sebastien Pouliot CAXamarin Team Xamurai

    It can be a bit confusing. Part of it is history and some of the confusion exists because the default option is to partially link (which is not a conventional use case for a regular linker).

    Still it's really close to a native linker, i.e. the goal of a linker is to produce a final executable and remove the unused symbols.

    It's also worth noting that both native and managed linkers suffers from the same main inconvenient, e.g. if you load symbols dynamically (e.g. GetProcAddress or dlsym) then you need to instruct the linker about those symbols (so they are not removed) or you'll experience issues at runtime. The managed linker needs the same help if you do things like reflection.

    IMO the main confusion comes from the linker definition become murky with dynamic loading and linking (DLL in Windows universe) to the point where, for most .NET/Java-only developers, a linker does not exists.

    The three options behave like this:

    • Don't link : Do not run the linker -> no unused symbol will be removed

    • Link SDK : Apply the linker on SDK assemblies only -> unused symbols in the Xamarin.iOS assemblies will be removed

    • Link all : Apply the linker on every assemblies -> unused symbols in the application will be removed

    Note: what's being done is not Dead Code Elimination (DCE) since it mostly does not work on code but on symbols (like a real linker does). Naming it DCE would only be confusing in another way ;-)

  • adamkempadamkemp Adam Kemp USInsider, Developer Group Leader mod

    Sebastien, I'm going to pick on you a bit because you responded, but don't take that personally. I see this as a Xamarin issue, not an issue with you. :)

    First, I think this comes down to just terrible wording in a dialog. I honestly don't know or have any reason to care what the actual Xamarin linker does, and I'm sure it does more than what this switch indicates. Maybe it really does behave at some level just like a native linker. The problem is that the UI implies that the "linker" is 1. optional, and 2. has the opposite effect as every other linker. That's confusing as hell. I'm not asking you to rename the component in mono or anything, but that dialog wording is atrocious, and something should be done about it. It's a consistent source of headaches for new developers at my company, and I don't think we're alone.

    I don't think it's fair to characterize a native linker's goal as "to remove unused symbols". That is an optional side effect of a linker's job, which is to pull in symbols and link them together in the binary. The Xamarin "linker" as described by the UI in the dialog doesn't do that.

    In a "native" linker there is no such option as "don't link". That would mean "don't give me a usable output file". Obviously that's not what Xamarin's option means, though. If the whole linker is optional in Xamarin then obviously it can't serve the same purpose as a native linker, which is not at all optional for building a useful executable from multiple object files. If it's not optional then "don't link" is absolutely the wrong name for this option. It should be "force include all" or something.

    In a native linker if you disabled an option labeled "link SDK" you would expect to be missing symbols, whereas adding an option called "link SDK" would add symbols. The Xamarin option means the the opposite, though.

    The reason I'm nitpicking is because this seems to be a consistent source of confusion for Xamarin users (in my company, as well as outside, as shown here). I think at some point rather than trying to continue to make this bad analogy in order to try to explain it Xamarin should just rename the feature so that it stops being so confusing.

    The confusion you're talking about is actually the problem of dealing with dynamic code when you do use this dead code stripping feature, but understanding that would be much more straightforward if the feature had a clear name that indicated its actual effect. The confusion I'm talking about is knowing based on the name what the feature actually does.

    Based on my experience trying to explain to people what this feature does (and backed up again on this thread) trying to compare it to a native linker only confuses people. After all, if you're coming from a native code background, and you find that some code from the SDK wasn't included in the final product, the natural thing to do would be to choose "link SDK". It seems obvious, but it's definitely wrong. Few things in UX are certain, but "the name of these options lead people to choose the opposite from what they need" is a pretty clear cut case of "you named it wrong".

    If you don't like the name "dead code elimination" then something like this would also suffice:

    "Don't link" -> "Force include all"
    "SDK only" -> "Force include my code"
    "Link all" -> "Force include nothing"

    /rant

  • matt1701matt1701 Mathew Thampi USMember

    Sebastien, is there any possibility that the linker is stripping out vital libraries? I keep getting warning messages during a build that XML and JSON dependancies aren't found (see the image at the start of this thread). So, sometimes when I deploy to the device the application just crashes on startup. If I build a few times eventually I may get a build where the warnings do not come up and then it runs fine. These warnings go away when the Linker option is set to Don't Link. The problem is when you use Don't link, the binary becomes too big to upload to the App store (you get an error message when you use the Application Loader).
    Usually I uncheck the references for JSON and XML and the recheck them and do a build again. Sometimes the warning messages stay and sometimes they disappear. This inconstancy during the build means there must be something unstable in Xamarin Studio.If the linker is stripping out essential stuff then this is a big problem as there is no way to check if everything is working until Apple rejects your app.
    Someone else on another thread said these warnings do not appear in the next alpha build so maybe its something you are already aware of but could you just confirm whether or not there is a problem here.
    Thanks

  • SebastienPouliotSebastienPouliot Sebastien Pouliot CAXamarin Team Xamurai

    @matt1701 The warnings from your screenshot are likely related to bug #16213 which is fixed in 7.0.6 (alpha, soon to be beta).

    If I build a few times eventually I may get a build where the warnings do not come up and then it runs fine.

    However it might not be the cause of your issue. The linker output is not random, i.e. the same input will produce the same output. If you need to build several times to get a working application then something else (not the linker) is wrong (but it could be incorrect caching due to the same bug - even if this is not how the issue was reported).

    To be sure we will need more information (version numbers, warnings, crash reports...) to investigate the issue and you should open a bug report for this. You might also want to try 7.0.6 first since creating a test case might be difficult.

  • SebastienPouliotSebastienPouliot Sebastien Pouliot CAXamarin Team Xamurai

    @adamkemp I think I better understand your point now. Running the linker (process) is optional while the SDK assemblies (data) are not optional. So "Don't link" and "Link SDK" can be interpreted quite differently.

    I do not own the addin but I'll ask around for alternative wording suggestions and file this.

  • adamkempadamkemp Adam Kemp USInsider, Developer Group Leader mod

    Thanks, Sebastien. :)

  • matt1701matt1701 Mathew Thampi USMember

    Thanks for clearing that up Sebastien. I'll try and get some more details and submit a bug report. Cheers

Sign In or Register to comment.