Add NullableAttribute to package link.xml
applejag opened this issue · 3 comments
Description
Based on the issue found by @SwingWren in #52
For some reason IL2CPP strips the NullableAttribute:.ctor(byte)
constructor when using High Stripping Level, which it shouldn't as the attribute is clearly used in the referenced invokation.
Motivation
Even high managed stripping level should work.
Suggested solution
-
Add the following to the
link.xml
inside the package:<assembly fullname="Newtonsoft.Json"> <type fullname="System.Runtime.CompilerServices.NullableAttribute"/> <type fullname="System.Runtime.CompilerServices.NullableContextAttribute"/> </assembly>
-
Add a forum post on https://forum.unity.com asking if this is intended or buggy behaviour
Inspiration sources
- NullableAttribute: https://github.com/dotnet/roslyn/blob/master/docs/features/nullable-metadata.md
- IL syntax: https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf
- II.15.4.1.4 The .param directive
- II.23.3 Custom attributes
- Managed Stripping Levels: https://docs.unity3d.com/Manual/ManagedCodeStripping.html#ManagedStrippingLevels
Media
Signature from metadata inside Visual Studio:
[NullableAttribute(2)]
public JToken? this[string propertyName] { get; set; }
IL:
.method public hidebysig newslot specialname virtual final
instance void set_Item(string propertyName,
class Newtonsoft.Json.Linq.JToken 'value') cil managed
{
.param [2]
.custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 )
// Code size 43 (0x2b)
.maxstack 3
.locals init (class Newtonsoft.Json.Linq.JProperty V_0)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldc.i4.4
IL_0003: call instance class Newtonsoft.Json.Linq.JProperty Newtonsoft.Json.Linq.JObject::Property(string,
valuetype [netstandard]System.StringComparison)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: brfalse.s IL_0014
IL_000c: ldloc.0
IL_000d: ldarg.2
IL_000e: callvirt instance void Newtonsoft.Json.Linq.JProperty::set_Value(class Newtonsoft.Json.Linq.JToken)
IL_0013: ret
IL_0014: ldarg.0
IL_0015: ldarg.1
IL_0016: callvirt instance void Newtonsoft.Json.Linq.JObject::OnPropertyChanging(string)
IL_001b: ldarg.0
IL_001c: ldarg.1
IL_001d: ldarg.2
IL_001e: call instance void Newtonsoft.Json.Linq.JObject::Add(string,
class Newtonsoft.Json.Linq.JToken)
IL_0023: ldarg.0
IL_0024: ldarg.1
IL_0025: callvirt instance void Newtonsoft.Json.Linq.JObject::OnPropertyChanged(string)
IL_002a: ret
} // end of method JObject::set_Item
JObject.get_Item source code:
Error message on build:
Failed running C:\Program Files\Unity\Hub\Editor\2019.3.3f1\Editor\Data\il2cpp\build/deploy/net471/UnityLinker.exe -out="C:/dev/JsonNet-for-Unity #52/Temp/StagingArea/Data/Managed/tempStrip" -x="C:/dev/JsonNet-for-Unity #52/Temp/StagingArea/Data/Managed/TypesInScenes.xml" -x="C:/dev/JsonNet-for-Unity #52/Assets/link.xml" -d="C:/dev/JsonNet-for-Unity #52/Temp/StagingArea/Data/Managed" --include-unity-root-assembly="C:/dev/JsonNet-for-Unity #52/Temp/StagingArea/Data/Managed/Assembly-CSharp.dll" --dotnetruntime=il2cpp --dotnetprofile=unityaot --use-editor-options --include-directory="C:/dev/JsonNet-for-Unity #52/Temp/StagingArea/Data/Managed" --editor-settings-flag=Development --rule-set=Experimental --editor-data-file="C:/dev/JsonNet-for-Unity #52/Temp/StagingArea/Data/Managed/EditorToUnityLinkerData.json" --platform=WindowsDesktop --engine-modules-asset-file="C:/Program Files/Unity/Hub/Editor/2019.3.3f1/Editor/Data/PlaybackEngines/WindowsStandaloneSupport/Whitelists/../modules.asset"
stdout:
Fatal error in Unity CIL Linker
System.ArgumentException: Member 'System.Void System.Runtime.CompilerServices.NullableAttribute::.ctor(System.Byte)' is declared in another module and needs to be imported
at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
at Mono.Cecil.MetadataBuilder.AddCustomAttributes(ICustomAttributeProvider owner)
at Mono.Cecil.MetadataBuilder.AddConstraints(GenericParameter generic_parameter, GenericParamConstraintTable table)
at Mono.Cecil.MetadataBuilder.AddGenericParameters()
at Mono.Cecil.MetadataBuilder.BuildModule()
at Mono.Cecil.MetadataBuilder.BuildMetadata()
at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__2_0(MetadataBuilder builder, MetadataReader _)
at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
at Mono.Linker.Steps.OutputStep.WriteAssembly(AssemblyDefinition assembly, String directory, WriterParameters writerParameters)
at Unity.Linker.Steps.UnityOutputStep.WriteAssembly(AssemblyDefinition assembly, String directory, WriterParameters writerParameters)
at Mono.Linker.Steps.OutputStep.OutputAssembly(AssemblyDefinition assembly)
at Mono.Linker.Steps.BaseStep.Process(LinkContext context)
at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
at Unity.Linker.UnityPipeline.ProcessStep(LinkContext context, IStep step)
at Mono.Linker.Pipeline.Process(LinkContext context)
at Unity.Linker.UnityDriver.Run()
at Unity.Linker.UnityDriver.RunDriverWithoutErrorHandling()
at Unity.Linker.UnityDriver.RunDriver()
stderr:
UnityEngine.Debug:LogError(Object)
UnityEditorInternal.Runner:RunProgram(Program, String, String, String, CompilerOutputParserBase)
UnityEditorInternal.Runner:RunManagedProgram(String, String, String, CompilerOutputParserBase, Action`1)
UnityEditorInternal.AssemblyStripper:RunAssemblyLinker(IEnumerable`1, String&, String&, String, String)
UnityEditorInternal.AssemblyStripper:StripAssembliesTo(String, String&, String&, IEnumerable`1, UnityLinkerRunInformation)
UnityEditorInternal.AssemblyStripper:RunAssemblyStripper(UnityLinkerRunInformation)
UnityEditorInternal.AssemblyStripper:StripAssemblies(String, BaseUnityLinkerPlatformProvider, IIl2CppPlatformProvider, RuntimeClassRegistry, ManagedStrippingLevel)
UnityEditorInternal.IL2CPPBuilder:Run()
UnityEditorInternal.IL2CPPUtils:RunIl2Cpp(String, IIl2CppPlatformProvider, Action`1, RuntimeClassRegistry)
DesktopStandalonePostProcessor:SetupStagingArea(BuildPostProcessArgs, HashSet`1)
DesktopStandalonePostProcessor:PostProcess(BuildPostProcessArgs)
UnityEditor.EditorApplication:Internal_CallGlobalEventHandler()
I also ran into this and your workaround works for me too! Looking around for the error initially, I also found a post on the unity forum of the "same" issue:
Unfortunately it looks like the guy didn't follow-up after Unity asked for bug report.
@timheijden Hey good find! I can try do a repro and post it in the same thread as the one you linked. Nice
@timheijden I was not able to correlate this issue with the ones mentioned in the forum thread you linked. I was however able to find a different workaround to get these link.xml changes embedded into the package and I've written about it here: https://forum.unity.com/threads/while-custom-package-need-a-link-xml.727460/#post-6708610