Search Unity

while custom package need a link.xml.

Discussion in 'Package Manager' started by wang37921, Aug 14, 2019.

  1. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    If a custom package need a link.xml, it support now? where put it?
    Unity will merge all the link.xml?
     
  2. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Unity does not support link.xml files in packages. You can find full details about managed code stripping and link.xml files in the Unity manual here: https://docs.unity3d.com/Manual/ManagedCodeStripping.html

    Can you elaborate on the need for a link.xml file in a package? Are you the author of a package that needs a link.xml file?
     
  3. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    Thanks,
    My custom package using a json framework, so i want convert the exist json to a upm.(more than one package need it.)
    the exist json framework just a dll, so i thought could i wrap it into a upm: https://github.com/mapotofu-fun/Json
    while i read the json framework, it says need a link.xml, so i post this thread.
     
  4. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    It looks like that JSON code normally requires the user put a link.xml file in their project. I think the same will be true of this library when it is shipped as a package then.
     
  5. wang37921

    wang37921

    Joined:
    Aug 1, 2014
    Posts:
    102
    hum... it's a solution..
    but i think keep self-integrity will be better. otherwise, i need keep the tips in README.
    maybe merge link.xml, gizmos...and other special folder and files is more intuition.
    personal option, if could be accept. it's very cool.
     
    neonblitzer likes this.
  6. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    I agree, the current situation is not great. We're still working out the best way to handle cases like this.
     
    EirikWahl likes this.
  7. z000z

    z000z

    Joined:
    Dec 31, 2014
    Posts:
    96
    @JoshPeterson has there been any updates on this, is there still no way to include a link.xml with a custom package?

    We're moving a bunch of our code to custom packages to better support re-use, which changes how il2cpp works (local code doesn't get stripped, but once you move it into a custom package it's subject to stripping) and it would be ideal if we could keep up with the stripping rules at the package level instead of figuring it all out at each end project.
     
    MaggerFabio likes this.
  8. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Unfortunately we don't have too much to say about this yet. I can offer two work arounds though.

    First, you can use the [Preserve] attribute in your source code to prevent the linker from removing any classes and methods you want to keep.

    Second, you can embed a link.xml as a resource in an assembly, and the linker will pick it up and use it as if it were a file in the project.
     
    EirikWahl likes this.
  9. z000z

    z000z

    Joined:
    Dec 31, 2014
    Posts:
    96
    Oh ok, that second option looks promising, if you have multiple assemblies with embedded link.xml is there any sort of merging that would happen or will it just pick one somewhat randomly?
     
  10. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    All of the link.xml files will be merged, similar to the way multiple link.xml files can be used in the same Unity project in different directories.
     
  11. mnavarro

    mnavarro

    Joined:
    Dec 29, 2011
    Posts:
    1
    Hi Josh,
    We can embed our package link.xml to the package assembly or a project assembly ?
     
  12. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    I'm unsure what you mean by the distinction between package assembly and project assembly. Can you clarify?
     
  13. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    You could use the package samples workflow to allow users to import a pre-written sample link.xml file into their assets directory which copies from the original in your package. not ideal but could get you by for now.
     
  14. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Is it planned to add support for link.xml into packages?
     
    JeromeGodboutAmotus likes this.
  15. MaggerFabio

    MaggerFabio

    Joined:
    Oct 17, 2017
    Posts:
    11
    Google recently released Firebase via UPM and they are also facing the same issue: https://github.com/firebase/quickstart-unity/issues/623

    This will become more and more frequent as more people and companies move towards UPM to manage private packages, so ideally we'd have some solution to this that gives control to who is publishing the package to manage it directly from the package.

    I understand we can use the [Preserve] attribute but this is not always an option (e.g. adding a third-party dependency that uses dlls, such as Json .NET for Unity 2.0.1, which will cause code stripping issues without its link.xml file). Another potential workaround is to copy the link.xml file from the package folder into the Assets folder, before building (Pre Processor) but this is not ideal.
     
    neonblitzer likes this.
  16. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    Thanks for the suggestion! Seems like the current solution is to write a preprocessor that goes through all the packages and copies (and ideally merges) all link.xml files it finds.

    We also had issues with JSON .Net and Firebase this week...
     
    Last edited: May 8, 2020
    MaggerFabio likes this.
  17. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    So I actually wrote an editor tool that extracts all link.xml files from packages, merges them and includes in the build.
    Place it in an Editor folder and it will do all the magic during build time.
    https://pastebin.com/m8i3xecr
     
    Rallix, EirikWahl, Gearmoon and 3 others like this.
  18. maksimbu

    maksimbu

    Joined:
    Dec 18, 2020
    Posts:
    2
    @JoshPeterson, could you provide with a more detailed instruction please?

    For example, there is a package MyCompany.MyComponent in Packages. According to package layout convention [1] it contains subfolder Runtime with related MyCompany.MyComponent.asmdef and following Foo.cs:
    Code (CSharp):
    1. namespace MyCompany.MyComponent
    2. {
    3.     using UnityEngine;
    4.  
    5.     public static class Foo
    6.     {
    7.         [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    8.         public static void Initialize()
    9.         {
    10.             Debug.Log("hello");
    11.         }
    12.     }
    13. }
    "hello" would not be printed on application launch (specifically, builds for android, managed stripping level set to "Low"), because function Foo.Initialize is not invoked, and looks like it is stripped out.

    In an attempt to fix this,
    • tried to set attribute [Preserve] (function Initialize, class Foo, both of them);
    • tried to add link.xml as a resource to .csproj (this package contains prebuilt library MyComponent.dll, and so tried to re-build MyComponent.dll with link.xml added as a resource);
    • tried to add link.xml to resources as "Embedded resource" and as "Resource";
    • tried to add link.xml to resources as a file and as a string;
    • tried to add link.xml to resources with name "link.xml" as it turned out [2], that by default resource name was "MyComponent.Resources.link.xml". Also tried with name "platform_native_link.xml";
    • tried to add link.xml with extension ".xml" and without it;
    • tried in Unity 2019.2.0f1, 2019.4.13f1, 2020.1.17f1;
    • wiped out npm cache and tried clean builds;
    but without success.

    If this package is moved from Packages to Assets before build, then obviously "hello" would be printed on application launch anyway.

    What i'm missing here?

    External links.
    1. https://docs.unity3d.com/Manual/cus-layout.html
    2. https://stackoverflow.com/questions...namespace-for-embedded-resources-with-msbuild
     
    Last edited: Dec 18, 2020
    YurySedyakin likes this.
  19. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Putting the [Preserve] attribute on the function Initialize should be enough to prevent it from being stripped. Can you check to see if it is actually being stripped when you do that? To do this, you can look in the Temp directory in the project after the build completes. You should see the assembly for your package there, and you can inspect in in a tool like ILSpy, to see if the function is actually being removed.

    It might be the case that it is not stripped, but also not called for some other reason. Or it might be stripped incorrectly.
     
  20. jilleJr

    jilleJr

    Joined:
    Jan 21, 2015
    Posts:
    63
    I got it working. It needs to have the same name as your assembly, so "MyComponent.xml" in your case.

    I really want to thank you for your efforts. I could continue on your attempts and try combinations you missed. You saved a lot of my time!

    The biggest hint I got was from the docs

    That's the only place I could find any reference of having the resource have the same name as the assembly.

    To get embedded link.xml file to work:

    1. Create a file in the .NET library project. For example under "Resources/link.xml"
    2. Add the following to your .csproj / .fsproj / .vbproj:
      Code (CSharp):
      1.   <ItemGroup>
      2.     <EmbeddedResource Include="Resources\link.xml">
      3.       <LogicalName>MyAssemblyName.xml</LogicalName>
      4.     </EmbeddedResource>
      5.   </ItemGroup>
    The fact that this works does unlock so much in the form of package user experience. No longer any need to supply a long link.xml snippet in the README.md. You can just embed it!

    Marvelous!

    @JoshPeterson Could this please be added to the official documentation? It's really helpful knowledge. It's kind of a workaround but I really do hope you never remove this feature.

    Kind regards, kalle
     
  21. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Thanks, I'll see what we can do about the documentation.
     
  22. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,109
    Is There any way to make it work for Package Assembly Definitions?
     
  23. maksimbu

    maksimbu

    Joined:
    Dec 18, 2020
    Posts:
    2
    @JoshPeterson,
    folder Temp/StagingArea/Il2Cpp/Managed contains a lot of dlls, but MyCompany.MyComponent.dll is not found there. [Preserve] attribute does not change this.

    However if following Bar.cs
    Code (CSharp):
    1. namespace MyCompany.MyComponent
    2. {
    3.     using UnityEngine;
    4.  
    5.     public static class Bar
    6.     {
    7.         public static void Initialize()
    8.         {
    9.             Debug.Log("hello from Bar");
    10.         }
    11.     }
    12. }
    added to subfolder Runtime and function Bar.Initialize() is invoked explicitly from somewhere in Assets, then MyCompany.MyComponent.dll would appear in the Temp folder, and Foo.Initialize would not be stripped and run on application launch. Even more, [Preserve] attribute would not be needed for Foo.Initialize at all.

    It looks like code stripping consists of the two separate steps:
    1. first excludes whole assemblies, if nothing is referenced explicitly from them. And it does not matter, whether [Preserve] attribute is put somewhere (or [RuntimeInitializeOnLoadMethod] attribute) or link.xml is embedded in those assemblies;
    2. second step code-strips left assemblies. At this point [Preserve] attribute and link.xml matters.
    Pure speculation, but if it is true, then arguably p. 1 is a bug?

    @jilleJr,
    part about link.xml embedded as mscorlib.xml in mscorlib.dll explains a lot. This approach works, and it can be used to a certain degree. Still i hope that someday unity will support raw link.xml in Packages.
     
    neonblitzer and JesOb like this.
  24. mike-voorhees

    mike-voorhees

    Unity Technologies

    Joined:
    Aug 9, 2016
    Posts:
    46
    You need to use
    Code (CSharp):
    1. [assembly: AlwaysLinkAssembly]
    to force code stripping to process your package when it needs to survive even when there are no code paths that use the package assembly.

    More information is available https://docs.unity3d.com/Manual/ManagedCodeStripping.html

    As for the general state of link.xml files in packages, it is not great. I elaborated on why in a post recently. https://forum.unity.com/threads/the-current-state-of-link-xml-in-packages.995848/#post-6545491

    -Mike
     
  25. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    I still don't get how this would work, would you need to provide the package code as a dll?
     
  26. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    jilleJr likes this.
  27. Revolter

    Revolter

    Joined:
    Mar 15, 2014
    Posts:
    216
    This thread doesn't explain how to embed the link.xml file into the package assembly.

    @jilleJr provided an example with .csproj -> doesn't that mean that we would have to compile the source code into the dll before creating the upm package?
    Also as far as I know, Unity creates .csproj automatically and this extension is usually added to .gitignore. This is why I'm confused
     
  28. mike-voorhees

    mike-voorhees

    Unity Technologies

    Joined:
    Aug 9, 2016
    Posts:
    46
    You can add a `csc.rsp` file in the `Runtime` folder of your package, then use the `/res` argument to embed the link.xml file.

    For example

    /res:..\CustomPackage1\Runtime\com.unity.custom.package.one.runtime.xml

    The current directory for the C# compiler will be the project directory.

    Another option that wasn't mentioned early is generating the link.xml file as part of the build. https://docs.unity3d.com/2021.1/Doc...rProcessor.GenerateAdditionalLinkXmlFile.html

    Sometimes this approach is more desirably than manually maintaining a link.xml file.
     
    jilleJr and codestage like this.
  29. SciCodeStudio

    SciCodeStudio

    Joined:
    Dec 14, 2013
    Posts:
    7
    Hi - been looking for a good answer myself, found this https://github.com/jilleJr/Newtonsoft.Json-for-Unity/wiki/Embed-link.xml-in-UPM-package which explains the process perfectly. Works for me.
     
    colorengame and jilleJr like this.
  30. jilleJr

    jilleJr

    Joined:
    Jan 21, 2015
    Posts:
    63
  31. alec100_94

    alec100_94

    Joined:
    Jan 9, 2017
    Posts:
    26
    I know this is old but a little bit of further clarification on this would be helpful. I've made a folder called Runtime in the root of my package, and put my link.xml inside along with a csc.rsp file. What I'm confused about is the path, I want the package to be directory agnostic. It looks like you're making an assumption that the package exists outside the project directory here (mines is currently in the packages folder, but could also potentially be in Library/PackageCache), the package folder name is also named after the assembly in my case (e.g. com.unity.custom.package.one), with a different Display Name.
     
    neonblitzer likes this.
  32. jilleJr

    jilleJr

    Joined:
    Jan 21, 2015
    Posts:
    63
    Yea that seems like it's the case. I would personally advice against using csc.rsp inside UPM packages for this reason then.

    Suggest you take a look at some alternative solution. If you don't want to embed it in a DLL file, then perhaps using the IUnityLinkerProcessor.GenerateAdditionalLinkXmlFile (as shown by bobbaluba) might be a good option?