public void GenerateDLL(string folderPath, bool generateLinkXML = true) { var generateForTypes = this.supportSerializedTypes.Where(n => n.Emit && n.Type != null).Select(n => n.Type).ToList(); FixUnityAboutWindowBeforeEmit.Fix(); AOTSupportUtilities.GenerateDLL(folderPath, FormatterEmitter.PRE_EMITTED_ASSEMBLY_NAME, generateForTypes, generateLinkXML); }
public void GenerateDLL() { FixUnityAboutWindowBeforeEmit.Fix(); const string NAME = FormatterEmitter.PRE_EMITTED_ASSEMBLY_NAME; var dirPath = this.AOTFolderPath; var newDllPath = dirPath + NAME; var fullDllPath = newDllPath + ".dll"; var fullLinkXmlPath = dirPath + "link.xml"; var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName() { Name = NAME }, AssemblyBuilderAccess.Save, dirPath); var module = assembly.DefineDynamicModule(NAME); // The following is a fix for Unity's crappy Mono runtime that doesn't know how to do this sort // of stuff properly // // We must manually remove the "Default Dynamic Assembly" module that is automatically defined, // otherwise a reference to that non-existent module will be saved into the assembly's IL, and // that will cause a multitude of issues. // // We do this by forcing there to be only one module - the one we just defined, and we set the // manifest module to be that module as well. { var modulesField = assembly.GetType().GetField("modules", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var manifestModuleField = assembly.GetType().GetField("manifest_module", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (modulesField != null) { modulesField.SetValue(assembly, new ModuleBuilder[] { module }); } if (manifestModuleField != null) { manifestModuleField.SetValue(assembly, module); } } var type = module.DefineType(NAME + ".PreventCodeStrippingViaReferences", TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.NotPublic); CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(typeof(PreserveAttribute).GetConstructor(Type.EmptyTypes), new object[0]); type.SetCustomAttribute(attributeBuilder); var staticConstructor = type.DefineTypeInitializer(); var il = staticConstructor.GetILGenerator(); HashSet <Type> seenTypes = new HashSet <Type>(); //var endPoint = il.DefineLabel(); //il.Emit(OpCodes.Br, endPoint); foreach (var typeEntry in this.supportSerializedTypes) { if (typeEntry.Type == null || !typeEntry.Emit) { continue; } if (typeEntry.Type.IsAbstract || typeEntry.Type.IsInterface) { Debug.LogError("Skipping type '" + typeEntry.Type.GetNiceFullName() + "'! Type is abstract or an interface."); continue; } if (typeEntry.Type.IsGenericType && (typeEntry.Type.IsGenericTypeDefinition || !typeEntry.Type.IsFullyConstructedGenericType())) { Debug.LogError("Skipping type '" + typeEntry.Type.GetNiceFullName() + "'! Type is a generic type definition, or its arguments contain generic parameters; type must be a fully constructed generic type."); continue; } var serializedType = typeEntry.Type; if (seenTypes.Contains(serializedType)) { continue; } seenTypes.Add(serializedType); // Reference serialized type { if (serializedType.IsValueType) { var local = il.DeclareLocal(serializedType); il.Emit(OpCodes.Ldloca, local); il.Emit(OpCodes.Initobj, serializedType); } else { var constructor = serializedType.GetConstructor(Type.EmptyTypes); if (constructor != null) { il.Emit(OpCodes.Newobj, constructor); il.Emit(OpCodes.Pop); } } } // Reference and/or create formatter type if (!FormatterUtilities.IsPrimitiveType(serializedType)) { var formatter = FormatterLocator.GetFormatter(serializedType, SerializationPolicies.Unity); if (formatter.GetType().IsDefined <EmittedFormatterAttribute>()) { //// Emit an actual AOT formatter into the generated assembly //if (this.emitAOTFormatters) //{ // var emittedFormatter = FormatterEmitter.EmitAOTFormatter(typeEntry.Type, module, SerializationPolicies.Unity); // var emittedFormatterConstructor = emittedFormatter.GetConstructor(Type.EmptyTypes); // il.Emit(OpCodes.Newobj, emittedFormatterConstructor); // il.Emit(OpCodes.Pop); //} } else { // Just reference the pre-existing formatter var formatterConstructor = formatter.GetType().GetConstructor(Type.EmptyTypes); if (formatterConstructor != null) { il.Emit(OpCodes.Newobj, formatterConstructor); il.Emit(OpCodes.Pop); } } // Make sure we have a proper reflection formatter variant if all else goes wrong il.Emit(OpCodes.Newobj, typeof(ReflectionFormatter <>).MakeGenericType(typeEntry.Type).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Pop); } ConstructorInfo serializerConstructor; // Reference serializer variant if (serializedType.IsEnum) { serializerConstructor = typeof(EnumSerializer <>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes); } else { serializerConstructor = typeof(ComplexTypeSerializer <>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes); } il.Emit(OpCodes.Newobj, serializerConstructor); il.Emit(OpCodes.Pop); } //il.MarkLabel(endPoint); il.Emit(OpCodes.Ret); type.CreateType(); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } if (File.Exists(fullDllPath)) { File.Delete(fullDllPath); } if (File.Exists(fullDllPath + ".meta")) { File.Delete(fullDllPath + ".meta"); } try { AssetDatabase.Refresh(); } catch (Exception) { // Sigh, Unity 5.3.0 } assembly.Save(NAME); File.Move(newDllPath, fullDllPath); File.WriteAllText(fullLinkXmlPath, LINK_XML_CONTENTS); try { AssetDatabase.Refresh(); } catch (Exception) { // Sigh, Unity 5.3.0 } var pluginImporter = PluginImporter.GetAtPath(fullDllPath) as PluginImporter; if (pluginImporter != null) { //pluginImporter.ClearSettings(); pluginImporter.SetCompatibleWithEditor(false); pluginImporter.SetCompatibleWithAnyPlatform(true); // Disable for all standalones pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux, false); pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false); pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinuxUniversal, false); // StandaloneOSXUniversal (<= 2017.2) / StandaloneOSX (>= 2017.3) pluginImporter.SetCompatibleWithPlatform((BuildTarget)2, false); if (!UnityVersion.IsVersionOrGreater(2017, 3)) { pluginImporter.SetCompatibleWithPlatform((BuildTarget)4, false); // StandaloneOSXIntel pluginImporter.SetCompatibleWithPlatform((BuildTarget)27, false); // StandaloneOSXIntel64 } pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false); pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false); //pluginImporter.SetCompatibleWithPlatform(BuildTarget.Android, false); pluginImporter.SaveAndReimport(); } AssetDatabase.SaveAssets(); }