public void OnPreprocessBuild(BuildReport report)
        {
            var aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated
            if (aotSettingsForTarget.DisableBurstCompilation)
            {
                return;
            }
            if (report.summary.platform == BuildTarget.Switch)
            {
                // add the static lib, and the c++ shim
                string burstCppLinkFile   = "lib_burst_generated.cpp";
                string burstStaticLibFile = "lib_burst_generated.a";
                string cppPath            = Path.Combine(TempSourceLibrary, burstCppLinkFile);
                string libPath            = Path.Combine(TempStaticLibrary, burstStaticLibFile);
                if (!Directory.Exists(TempSourceLibrary))
                {
                    Directory.CreateDirectory(TempSourceLibrary);
                    Directory.CreateDirectory(TempSourceLibrary);
                }
                File.WriteAllText(cppPath, @"
extern ""C""
{
    void Staticburst_initialize(void* );
    void* StaticBurstStaticMethodLookup(void* );

    int burst_enable_static_linkage = 1;
    void burst_initialize(void* i) { Staticburst_initialize(i); }
    void* BurstStaticMethodLookup(void* i) { return StaticBurstStaticMethodLookup(i); }
}
");
            }
        }
示例#2
0
        internal static BurstPlatformAotSettings GetOrCreateSettings(BuildTarget target)
        {
            BurstPlatformAotSettings settings = new BurstPlatformAotSettings();

            settings.DisableOptimisations    = false;
            settings.DisableSafetyChecks     = !BurstEditorOptions.EnableBurstSafetyChecks;
            settings.DisableBurstCompilation = !BurstEditorOptions.EnableBurstCompilation;

            return(settings);
        }
        internal static BurstPlatformAotSettings GetOrCreateSettings(BuildTarget target)
        {
            BurstPlatformAotSettings settings = new BurstPlatformAotSettings();

            settings.EnableOptimisations    = true;
            settings.EnableSafetyChecks     = BurstEditorOptions.EnableBurstSafetyChecks;
            settings.EnableBurstCompilation = BurstEditorOptions.EnableBurstCompilation;
            settings.UsePlatformSDKLinker   = false;
            settings.EnableDebugInAllBuilds = false;

            return(settings);
        }
示例#4
0
            public static void OnPostProcessBuild(BuildTarget target, string path)
            {
                // We only support AOT compilation for ios from a macos host (we require xcrun and the apple tool chains)
                //for other hosts, we simply act as if burst is not being used (an error will be generated by the build aot step)
                //this keeps the behaviour consistent with how it was before static linkage was introduced
                if (target == BuildTarget.iOS)
                {
                    var aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(BuildTarget.iOS);

                    // Early exit if burst is not activated
                    if (!aotSettingsForTarget.EnableBurstCompilation)
                    {
                        return;
                    }
                    PostAddStaticLibraries(path);
                }
            }
示例#5
0
        internal static BurstPlatformAotSettings GetOrCreateSettings(BuildTarget target)
        {
            BurstPlatformAotSettings settings = new BurstPlatformAotSettings(target);
            string path = GetPath(target);

            if (File.Exists(path))
            {
                var json = File.ReadAllText(path);
                EditorJsonUtility.FromJsonOverwrite(json, settings);
            }
            else
            {
                settings.Save(target);
            }

            return(settings);
        }
示例#6
0
            public override void OnActivate(string searchContext, VisualElement rootElement)
            {
                var platformFields = typeof(BurstPlatformAotSettings).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

                for (int p = 0; p < validPlatforms.Length; p++)
                {
                    m_PlatformSettings[p]   = BurstPlatformAotSettings.GetSerializedSettings(validPlatforms[p].defaultTarget);
                    m_PlatformProperties[p] = new SerializedProperty[platformFields.Length];
                    m_PlatformToolTips[p]   = new GUIContent[platformFields.Length];
                    for (int i = 0; i < platformFields.Length; i++)
                    {
                        m_PlatformProperties[p][i] = m_PlatformSettings[p].FindProperty(platformFields[i].Name);
                        m_PlatformToolTips[p][i]   = EditorGUIUtility.TrTextContent(
                            typeof(BurstPlatformAotSettings).GetField(platformFields[i].Name + "_DisplayName", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as string,
                            typeof(BurstPlatformAotSettings).GetField(platformFields[i].Name + "_ToolTip", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as string);
                    }
                }
            }
示例#7
0
        internal static BurstPlatformAotSettings GetOrCreateSettings(BuildTarget target)
        {
            BurstPlatformAotSettings settings = ScriptableObject.CreateInstance <BurstPlatformAotSettings>();

            settings.InitialiseDefaults(target);
            string path = GetPath(target);

            if (File.Exists(path))
            {
                var json = File.ReadAllText(path);
                EditorJsonUtility.FromJsonOverwrite(json, settings);
            }
            else
            {
                settings.Save(target);
            }

            return(settings);
        }
示例#8
0
        internal static BurstPlatformAotSettings GetOrCreateSettings(BuildTarget target)
        {
            target = ResolveTarget(target);
            BurstPlatformAotSettings settings = ScriptableObject.CreateInstance <BurstPlatformAotSettings>();

            settings.InitialiseDefaults(target);
            string path = GetPath(target);

            if (File.Exists(path))
            {
                var json = File.ReadAllText(path);
                settings = SerialiseIn(target, json);
            }
            else
            {
                settings.Save(target);
            }

            return(settings);
        }
示例#9
0
 private void InitialiseSettingsForPlatform(int platform, FieldInfo[] platformFields)
 {
     if (validPlatforms[platform].targetGroup == BuildTargetGroup.Standalone)
     {
         m_PlatformSettings[platform] = BurstPlatformAotSettings.GetSerializedSettings(EditorUserBuildSettings.selectedStandaloneTarget);
     }
     else
     {
         m_PlatformSettings[platform] = BurstPlatformAotSettings.GetSerializedSettings(validPlatforms[platform].defaultTarget);
     }
     m_PlatformProperties[platform] = new SerializedProperty[platformFields.Length];
     m_PlatformToolTips[platform]   = new GUIContent[platformFields.Length];
     for (int i = 0; i < platformFields.Length; i++)
     {
         m_PlatformProperties[platform][i] = m_PlatformSettings[platform].FindProperty(platformFields[i].Name);
         var displayName = typeof(BurstPlatformAotSettings).GetField(platformFields[i].Name + "_DisplayName", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as string;
         var toolTip     = typeof(BurstPlatformAotSettings).GetField(platformFields[i].Name + "_ToolTip", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as string;
         m_PlatformToolTips[platform][i] = EditorGUIUtility.TrTextContent(displayName, toolTip);
     }
 }
示例#10
0
        internal static BurstPlatformAotSettings SerialiseIn(BuildTarget target, string json)
        {
            // Deal with pre version 2 format
            BurstPlatformLegacySettings legacy = (BurstPlatformLegacySettings)ScriptableObject.CreateInstance <BurstPlatformLegacySettings>();

            EditorJsonUtility.FromJsonOverwrite(json, legacy);

            BurstPlatformAotSettings versioned = (BurstPlatformAotSettings)ScriptableObject.CreateInstance <BurstPlatformAotSettings>();

            EditorJsonUtility.FromJsonOverwrite(json, versioned);

            if (versioned.Version == 0)
            {
                // legacy file, upgrade it
                versioned.InitialiseDefaults(target);
                versioned.EnableOptimisations    = !legacy.DisableOptimisations;
                versioned.EnableBurstCompilation = !legacy.DisableBurstCompilation;
                versioned.EnableSafetyChecks     = !legacy.DisableSafetyChecks;
            }

            // Otherwise should be a modern file with a valid version (we can use that to upgrade when the time comes)
            return(versioned);
        }
        private void OnPostBuildPlayerScriptDLLsImpl(BuildReport report)
        {
            var aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated or the platform is not supported
            if (aotSettingsForTarget.DisableBurstCompilation || !IsSupportedPlatform(report.summary.platform))
            {
                return;
            }

            var commonOptions = new List <string>();
            var stagingFolder = Path.GetFullPath(TempStagingManaged);

            var playerAssemblies = GetPlayerAssemblies(report);

            // grab the location of the root of the player folder - for handling nda platforms that require keys
            var keyFolder = BuildPipeline.GetPlaybackEngineDirectory(report.summary.platform, BuildOptions.None);

            commonOptions.Add(GetOption(OptionAotKeyFolder, keyFolder));
            commonOptions.Add(GetOption(OptionAotDecodeFolder, Path.Combine(Environment.CurrentDirectory, "Library", "Burst")));

            // Extract the TargetPlatform and Cpu from the current build settings
            TargetCpu targetCpu;
            var       targetPlatform = GetTargetPlatformAndDefaultCpu(report.summary.platform, out targetCpu);

            commonOptions.Add(GetOption(OptionPlatform, targetPlatform));

            // --------------------------------------------------------------------------------------------------------
            // 1) Calculate AssemblyFolders
            // These are the folders to look for assembly resolution
            // --------------------------------------------------------------------------------------------------------
            var assemblyFolders = new List <string> {
                stagingFolder
            };

            if (report.summary.platform == BuildTarget.WSAPlayer ||
                report.summary.platform == BuildTarget.XboxOne)
            {
                // On UWP, not all assemblies are copied to StagingArea, so we want to
                // find all directories that we can reference assemblies from
                // If we don't do this, we will crash with AssemblyResolutionException
                // when following type references.
                foreach (var assembly in playerAssemblies)
                {
                    foreach (var assemblyRef in assembly.compiledAssemblyReferences)
                    {
                        // Exclude folders with assemblies already compiled in the `folder`
                        var assemblyName = Path.GetFileName(assemblyRef);
                        if (assemblyName != null && File.Exists(Path.Combine(stagingFolder, assemblyName)))
                        {
                            continue;
                        }

                        var directory = Path.GetDirectoryName(assemblyRef);
                        if (directory != null)
                        {
                            var fullPath = Path.GetFullPath(directory);
                            if (IsMonoReferenceAssemblyDirectory(fullPath) || IsDotNetStandardAssemblyDirectory(fullPath))
                            {
                                // Don't pass reference assemblies to burst because they contain methods without implementation
                                // If burst accidentally resolves them, it will emit calls to burst_abort.
                                fullPath = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/lib/mono/unityaot");
                                fullPath = Path.GetFullPath(fullPath); // GetFullPath will normalize path separators to OS native format
                                if (!assemblyFolders.Contains(fullPath))
                                {
                                    assemblyFolders.Add(fullPath);
                                }

                                fullPath = Path.Combine(fullPath, "Facades");
                                if (!assemblyFolders.Contains(fullPath))
                                {
                                    assemblyFolders.Add(fullPath);
                                }
                            }
                            else if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }
                        }
                    }
                }
            }

            // Copy assembly used during staging to have a trace
            if (BurstLoader.IsDebugging)
            {
                try
                {
                    var copyAssemblyFolder = Path.Combine(Environment.CurrentDirectory, "Logs", "StagingAssemblies");
                    try
                    {
                        if (Directory.Exists(copyAssemblyFolder))
                        {
                            Directory.Delete(copyAssemblyFolder);
                        }
                    }
                    catch
                    {
                    }

                    if (!Directory.Exists(copyAssemblyFolder))
                    {
                        Directory.CreateDirectory(copyAssemblyFolder);
                    }
                    foreach (var file in Directory.EnumerateFiles(stagingFolder))
                    {
                        File.Copy(file, Path.Combine(copyAssemblyFolder, Path.GetFileName(file)));
                    }
                }
                catch
                {
                }
            }

            // --------------------------------------------------------------------------------------------------------
            // 2) Calculate root assemblies
            // These are the assemblies that the compiler will look for methods to compile
            // This list doesn't typically include .NET runtime assemblies but only assemblies compiled as part
            // of the current Unity project
            // --------------------------------------------------------------------------------------------------------
            var rootAssemblies = new List <string>();

            foreach (var playerAssembly in playerAssemblies)
            {
                // the file at path `playerAssembly.outputPath` is actually not on the disk
                // while it is in the staging folder because OnPostBuildPlayerScriptDLLs is being called once the files are already
                // transferred to the staging folder, so we are going to work from it but we are reusing the file names that we got earlier
                var playerAssemblyPathToStaging = Path.Combine(stagingFolder, Path.GetFileName(playerAssembly.outputPath));
                if (!File.Exists(playerAssemblyPathToStaging))
                {
                    Debug.LogWarning($"Unable to find player assembly: {playerAssemblyPathToStaging}");
                }
                else
                {
                    rootAssemblies.Add(playerAssemblyPathToStaging);
                }
            }

            commonOptions.AddRange(assemblyFolders.Select(folder => GetOption(OptionAotAssemblyFolder, folder)));


            // --------------------------------------------------------------------------------------------------------
            // 3) Calculate the different target CPU combinations for the specified OS
            //
            // Typically, on some platforms like iOS we can be asked to compile a ARM32 and ARM64 CPU version
            // --------------------------------------------------------------------------------------------------------
            var combinations = CollectCombinations(targetPlatform, targetCpu, report);

            // --------------------------------------------------------------------------------------------------------
            // 4) Compile each combination
            //
            // Here bcl.exe is called for each target CPU combination
            // --------------------------------------------------------------------------------------------------------

            string debugLogFile = null;

            if (BurstLoader.IsDebugging)
            {
                // Reset log files
                try
                {
                    var logDir = Path.Combine(Environment.CurrentDirectory, "Logs");
                    debugLogFile = Path.Combine(logDir, "burst_bcl_editor.log");
                    if (!Directory.Exists(logDir))
                    {
                        Directory.CreateDirectory(logDir);
                    }
                    File.WriteAllText(debugLogFile, string.Empty);
                }
                catch
                {
                    debugLogFile = null;
                }
            }

            // Log the targets generated by BurstReflection.FindExecuteMethods
            foreach (var combination in combinations)
            {
                // Gets the output folder
                var stagingOutputFolder = Path.GetFullPath(Path.Combine(TempStaging, combination.OutputPath));
                var outputFilePrefix    = Path.Combine(stagingOutputFolder, combination.LibraryName);

                var options = new List <string>(commonOptions)
                {
                    GetOption(OptionAotOutputPath, outputFilePrefix),
                    GetOption(OptionTarget, combination.TargetCpu)
                };

                if (targetPlatform == TargetPlatform.iOS || targetPlatform == TargetPlatform.Switch)
                {
                    options.Add(GetOption(OptionStaticLinkage));
                }

                // finally add method group options
                options.AddRange(rootAssemblies.Select(path => GetOption(OptionRootAssembly, path)));

                // Log the targets generated by BurstReflection.FindExecuteMethods
                if (BurstLoader.IsDebugging && debugLogFile != null)
                {
                    try
                    {
                        var writer = new StringWriter();
                        writer.WriteLine("-----------------------------------------------------------");
                        writer.WriteLine("Combination: " + combination);
                        writer.WriteLine("-----------------------------------------------------------");

                        foreach (var option in options)
                        {
                            writer.WriteLine(option);
                        }

                        writer.WriteLine("Assemblies in AssemblyFolders:");
                        foreach (var assemblyFolder in assemblyFolders)
                        {
                            writer.WriteLine("|- Folder: " + assemblyFolder);
                            foreach (var assemblyOrDll in Directory.EnumerateFiles(assemblyFolder, "*.dll"))
                            {
                                var fileInfo = new FileInfo(assemblyOrDll);
                                writer.WriteLine("   |- " + assemblyOrDll + " Size: " + fileInfo.Length + " Date: " + fileInfo.LastWriteTime);
                            }
                        }

                        File.AppendAllText(debugLogFile, writer.ToString());
                    }
                    catch
                    {
                        // ignored
                    }
                }

                // Write current options to the response file
                var responseFile = Path.GetTempFileName();
                File.WriteAllLines(responseFile, options);

                if (BurstLoader.IsDebugging)
                {
                    Debug.Log($"bcl @{responseFile}\n\nResponse File:\n" + string.Join("\n", options));
                }

                try
                {
                    string generatedDebugInformationInOutput = "";
                    if ((report.summary.options & BuildOptions.Development) != 0)
                    {
                        generatedDebugInformationInOutput = GetOption(OptionDebug);
                    }

                    BclRunner.RunManagedProgram(Path.Combine(BurstLoader.RuntimePath, BurstAotCompilerExecutable),
                                                $"{generatedDebugInformationInOutput} \"@{responseFile}\"",
                                                new BclOutputErrorParser(),
                                                report);
                }
                catch (BuildFailedException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new BuildFailedException(e);
                }
            }
        }
示例#12
0
        private void OnPostBuildPlayerScriptDLLsImpl(BuildReport report)
        {
            BurstPlatformAotSettings aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated or the platform is not supported
            if (aotSettingsForTarget.DisableBurstCompilation || !IsSupportedPlatform(report.summary.platform))
            {
                return;
            }

            // Collect all method signatures
            var methodsToCompile = BurstReflection.FindExecuteMethods(AssembliesType.Player);

            if (methodsToCompile.Count == 0)
            {
                return; // Nothing to do
            }

            // Prepare options

            // We are grouping methods per their compiler options (float precision...etc)
            var methodGroups = new Dictionary <string, List <string> >();

            for (var i = 0; i < methodsToCompile.Count; i++)
            {
                var burstCompileTarget = methodsToCompile[i];
                if (!burstCompileTarget.IsSupported)
                {
                    continue;
                }

                var methodStr           = BurstCompilerService.GetMethodSignature(burstCompileTarget.Method);
                var methodFullSignature = methodStr + "--" + Hash128.Compute(methodStr);

                if (aotSettingsForTarget.DisableOptimisations)
                {
                    burstCompileTarget.Options.DisableOptimizations = true;
                }

                burstCompileTarget.Options.EnableBurstSafetyChecks = !aotSettingsForTarget.DisableSafetyChecks;

                string optionsAsStr;
                if (burstCompileTarget.TryGetOptionsAsString(false, out optionsAsStr))
                {
                    List <string> methodOptions;
                    if (!methodGroups.TryGetValue(optionsAsStr, out methodOptions))
                    {
                        methodOptions = new List <string>();
                        methodGroups.Add(optionsAsStr, methodOptions);
                    }
                    methodOptions.Add(GetOption(OptionAotMethod, methodFullSignature));
                }
            }

            var methodGroupOptions = new List <string>();

            // We should have something like this in the end:
            //
            // --group                1st group of method with the following shared options
            // --float-mode=xxx
            // --method=...
            // --method=...
            //
            // --group                2nd group of methods with the different shared options
            // --float-mode=yyy
            // --method=...
            // --method=...
            if (methodGroups.Count == 1)
            {
                var methodGroup = methodGroups.FirstOrDefault();
                // No need to create a group if we don't have multiple
                methodGroupOptions.Add(methodGroup.Key);
                foreach (var methodOption in methodGroup.Value)
                {
                    methodGroupOptions.Add(methodOption);
                }
            }
            else
            {
                foreach (var methodGroup in methodGroups)
                {
                    methodGroupOptions.Add(GetOption(OptionGroup));
                    methodGroupOptions.Add(methodGroup.Key);
                    foreach (var methodOption in methodGroup.Value)
                    {
                        methodGroupOptions.Add(methodOption);
                    }
                }
            }

            var commonOptions  = new List <string>();
            var targetCpu      = TargetCpu.Auto;
            var targetPlatform = GetTargetPlatformAndDefaultCpu(report.summary.platform, out targetCpu);

            commonOptions.Add(GetOption(OptionPlatform, targetPlatform));

            // TODO: Add support for configuring the optimizations/CPU
            // TODO: Add support for per method options

            var stagingFolder = Path.GetFullPath(TempStagingManaged);
            //Debug.Log($"Burst CompileAot - To Folder {stagingFolder}");

            // Prepare assembly folder list
            var assemblyFolders = new List <string>();

            assemblyFolders.Add(stagingFolder);

            var playerAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player);

            foreach (var assembly in playerAssemblies)
            {
                foreach (var assemblyRef in assembly.compiledAssemblyReferences)
                {
                    // Exclude folders with assemblies already compiled in the `folder`
                    var assemblyName = Path.GetFileName(assemblyRef);
                    if (assemblyName != null && File.Exists(Path.Combine(stagingFolder, assemblyName)))
                    {
                        continue;
                    }

                    var directory = Path.GetDirectoryName(assemblyRef);
                    if (directory != null)
                    {
                        var fullPath = Path.GetFullPath(directory);
                        if (IsMonoReferenceAssemblyDirectory(fullPath) || IsDotNetStandardAssemblyDirectory(fullPath))
                        {
                            // Don't pass reference assemblies to burst because they contain methods without implementation
                            // If burst accidentally resolves them, it will emit calls to burst_abort.
                            fullPath = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/lib/mono/unityaot");
                            fullPath = Path.GetFullPath(fullPath); // GetFullPath will normalize path separators to OS native format
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }

                            fullPath = Path.Combine(fullPath, "Facades");
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }
                        }
                        else if (!assemblyFolders.Contains(fullPath))
                        {
                            assemblyFolders.Add(fullPath);
                        }
                    }
                }
            }

            commonOptions.AddRange(assemblyFolders.Select(folder => GetOption(OptionAotAssemblyFolder, folder)));

            var combinations = new List <BurstOutputCombination>();

            if (targetPlatform == TargetPlatform.macOS)
            {
                // NOTE: OSX has a special folder for the plugin
                // Declared in GetStagingAreaPluginsFolder
                // PlatformDependent\OSXPlayer\Extensions\Managed\OSXDesktopStandalonePostProcessor.cs
                combinations.Add(new BurstOutputCombination("UnityPlayer.app/Contents/Plugins", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.iOS)
            {
                if (Application.platform != RuntimePlatform.OSXEditor)
                {
                    Debug.LogWarning("Burst Cross Compilation to iOS for standalone player, is only supported on OSX Editor at this time, burst is disabled for this build.");
                }
                else
                {
                    var targetArchitecture = (IOSArchitecture)UnityEditor.PlayerSettings.GetArchitecture(report.summary.platformGroup);
                    if (targetArchitecture == IOSArchitecture.ARMv7 || targetArchitecture == IOSArchitecture.Universal)
                    {
                        // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                        combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV7A_NEON32, DefaultLibraryName + "32"));
                    }
                    if (targetArchitecture == IOSArchitecture.ARM64 || targetArchitecture == IOSArchitecture.Universal)
                    {
                        // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                        combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV8A_AARCH64, DefaultLibraryName + "64"));
                    }
                }
            }
            else if (targetPlatform == TargetPlatform.Android)
            {
                //TODO: would be better to query AndroidNdkRoot (but thats not exposed from unity)
                string ndkRoot = null;

                // 2019.1 now has an embedded ndk
#if UNITY_2019_1_OR_NEWER
                if (EditorPrefs.HasKey("NdkUseEmbedded"))
                {
                    if (EditorPrefs.GetBool("NdkUseEmbedded"))
                    {
                        ndkRoot = Path.Combine(BuildPipeline.GetPlaybackEngineDirectory(BuildTarget.Android, BuildOptions.None), "NDK");
                    }
                    else
                    {
                        ndkRoot = EditorPrefs.GetString("AndroidNdkRootR16b");
                    }
                }
#endif

                // If we still don't have a valid root, try the old key
                if (string.IsNullOrEmpty(ndkRoot))
                {
                    ndkRoot = EditorPrefs.GetString("AndroidNdkRoot");
                }


                // Verify the directory at least exists, if not we fall back to ANDROID_NDK_ROOT current setting
                if (!string.IsNullOrEmpty(ndkRoot) && !Directory.Exists(ndkRoot))
                {
                    ndkRoot = null;
                }

                // Always set the ANDROID_NDK_ROOT (if we got a valid result from above), so BCL knows where to find the Android toolchain and its the one the user expects
                if (!string.IsNullOrEmpty(ndkRoot))
                {
                    Environment.SetEnvironmentVariable("ANDROID_NDK_ROOT", ndkRoot);
                }

                var androidTargetArch = UnityEditor.PlayerSettings.Android.targetArchitectures;
                if ((androidTargetArch & AndroidArchitecture.ARMv7) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/armeabi-v7a", TargetCpu.ARMV7A_NEON32));
                }
                if ((androidTargetArch & AndroidArchitecture.ARM64) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/arm64-v8a", TargetCpu.ARMV8A_AARCH64));
                }
                if ((androidTargetArch & AndroidArchitecture.X86) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/x86", TargetCpu.X86_SSE2));
                }
            }
            else if (targetPlatform == TargetPlatform.UWP)
            {
                // TODO: Make it configurable for x86 (sse2, sse4)
                combinations.Add(new BurstOutputCombination("Plugins/x64", TargetCpu.X64_SSE4));
                combinations.Add(new BurstOutputCombination("Plugins/x86", TargetCpu.X86_SSE2));
                combinations.Add(new BurstOutputCombination("Plugins/ARM", TargetCpu.THUMB2_NEON32));
                combinations.Add(new BurstOutputCombination("Plugins/ARM64", TargetCpu.ARMV8A_AARCH64));
            }
            else
            {
                combinations.Add(new BurstOutputCombination("Data/Plugins/", targetCpu));
            }

            foreach (var combination in combinations)
            {
                // Gets the output folder
                var stagingOutputFolder = Path.GetFullPath(Path.Combine(TempStaging, combination.OutputPath));
                var outputFilePrefix    = Path.Combine(stagingOutputFolder, combination.LibraryName);

                var options = new List <string>(commonOptions);
                options.Add(GetOption(OptionAotOutputPath, outputFilePrefix));
                options.Add(GetOption(OptionTarget, combination.TargetCpu));

                if (targetPlatform == TargetPlatform.iOS)
                {
                    options.Add(GetOption(OptionStaticLinkage));
                }

                // finally add method group options
                options.AddRange(methodGroupOptions);

                var responseFile = Path.GetTempFileName();
                File.WriteAllLines(responseFile, options);

                //Debug.Log("Burst compile with response file: " + responseFile);

                try
                {
                    string generatedDebugInformationInOutput = "";
                    if ((report.summary.options & BuildOptions.Development) != 0)
                    {
                        // Workaround for apple clang development issue (due to latest being 7.0.0) - IOS is only affected because its a source level IR compatability issue
                        if (targetPlatform != TargetPlatform.iOS)
                        {
                            generatedDebugInformationInOutput = GetOption(OptionDebug);
                        }
                    }

                    BclRunner.RunManagedProgram(Path.Combine(BurstLoader.RuntimePath, BurstAotCompilerExecutable),
                                                $"{generatedDebugInformationInOutput} @{responseFile}",
                                                new BclOutputErrorParser(),
                                                report);
                }
                catch (Exception e)
                {
                    // We don't expect any error, but in case we have one, we identify that it is burst and we print the details here
                    Debug.LogError("Unexpected error while running the burst compiler: " + e);
                }
            }
        }
示例#13
0
        public void OnPostBuildPlayerScriptDLLs(BuildReport report)
        {
            BurstPlatformAotSettings aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated or the platform is not supported
            if (aotSettingsForTarget.DisableBurstCompilation || !IsSupportedPlatform(report.summary.platform))
            {
                return;
            }

            // Collect all method signatures
            var methodsToCompile = BurstReflection.FindExecuteMethods(AssembliesType.Player);

            if (methodsToCompile.Count == 0)
            {
                return; // Nothing to do
            }

            // Prepare options
            var commonOptions = new List <string>();

            for (var i = 0; i < methodsToCompile.Count; i++)
            {
                var burstCompileTarget = methodsToCompile[i];
                if (!burstCompileTarget.SupportsBurst)
                {
                    continue;
                }

                var methodStr           = BurstCompilerService.GetMethodSignature(burstCompileTarget.Method);
                var methodFullSignature = methodStr + "--" + Hash128.Compute(methodStr);
                commonOptions.Add(GetOption(OptionAotMethod, methodFullSignature));
            }

            var targetCpu      = TargetCpu.Auto;
            var targetPlatform = GetTargetPlatformAndDefaultCpu(report.summary.platform, out targetCpu);

            commonOptions.Add(GetOption(OptionPlatform, targetPlatform));

            if (!BurstEditorOptions.EnableBurstSafetyChecks)
            {
                commonOptions.Add(GetOption(OptionDisableSafetyChecks));
            }

            // TODO: Add support for configuring the optimizations/CPU
            // TODO: Add support for per method options

            var stagingFolder = Path.GetFullPath(TempStagingManaged);
            //Debug.Log($"Burst CompileAot - To Folder {stagingFolder}");

            // Prepare assembly folder list
            var assemblyFolders = new List <string>();

            assemblyFolders.Add(stagingFolder);

            var playerAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player);

            foreach (var assembly in playerAssemblies)
            {
                foreach (var assemblyRef in assembly.compiledAssemblyReferences)
                {
                    // Exclude folders with assemblies already compiled in the `folder`
                    var assemblyName = Path.GetFileName(assemblyRef);
                    if (assemblyName != null && File.Exists(Path.Combine(stagingFolder, assemblyName)))
                    {
                        continue;
                    }

                    var directory = Path.GetDirectoryName(assemblyRef);
                    if (directory != null)
                    {
                        var fullPath = Path.GetFullPath(directory);
                        if (IsMonoReferenceAssemblyDirectory(fullPath) || IsDotNetStandardAssemblyDirectory(fullPath))
                        {
                            // Don't pass reference assemblies to burst because they contain methods without implementation
                            // If burst accidentally resolves them, it will emit calls to burst_abort.
                            fullPath = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/lib/mono/unityaot");
                            fullPath = Path.GetFullPath(fullPath); // GetFullPath will normalize path separators to OS native format
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }

                            fullPath = Path.Combine(fullPath, "Facades");
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }
                        }
                        else if (!assemblyFolders.Contains(fullPath))
                        {
                            assemblyFolders.Add(fullPath);
                        }
                    }
                }
            }

            commonOptions.AddRange(assemblyFolders.Select(folder => GetOption(OptionAotAssemblyFolder, folder)));

            // Gets platform specific IL2CPP plugin folder
            // Only the following platforms are providing a dedicated Tools directory
            switch (report.summary.platform)
            {
            case BuildTarget.XboxOne:
            case BuildTarget.PS4:
            case BuildTarget.Android:
            case BuildTarget.iOS:
                var pluginFolder = BuildPipeline.GetBuildToolsDirectory(report.summary.platform);
                commonOptions.Add(GetOption(OptionAotIL2CPPPluginFolder, pluginFolder));
                break;
            }

            var combinations = new List <BurstOutputCombination>();

            if (targetPlatform == TargetPlatform.macOS)
            {
                // NOTE: OSX has a special folder for the plugin
                // Declared in GetStagingAreaPluginsFolder
                // PlatformDependent\OSXPlayer\Extensions\Managed\OSXDesktopStandalonePostProcessor.cs
                combinations.Add(new BurstOutputCombination("UnityPlayer.app/Contents/Plugins", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.iOS)
            {
                // Check if we are under il2cpp as we may have to force a CPU backend for it
                // TODO: Should use report.summary.platformGroup instead?
                bool isUsingIL2CPP = PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) == ScriptingImplementation.IL2CPP;

                if (!isUsingIL2CPP)
                {
                    var targetArchitecture = (IOSArchitecture)UnityEditor.PlayerSettings.GetArchitecture(report.summary.platformGroup);
                    switch (targetArchitecture)
                    {
                    case IOSArchitecture.ARMv7:
                        targetCpu = TargetCpu.ARMV7A_NEON32;
                        break;

                    case IOSArchitecture.ARM64:
                        targetCpu = TargetCpu.ARMV8A_AARCH64;
                        break;

                    case IOSArchitecture.Universal:
                        // TODO: How do we proceed here?
                        targetCpu = TargetCpu.ARMV7A_NEON32;
                        break;
                    }
                }

                // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                combinations.Add(new BurstOutputCombination("Frameworks", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.Android)
            {
                // Set the ANDROID_NDK_ROOT so IL2CPP knows where to find the Android toolchain
                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT")))
                {
                    var ndkRoot = EditorPrefs.GetString("AndroidNdkRoot");
                    if (!string.IsNullOrEmpty(ndkRoot))
                    {
                        Environment.SetEnvironmentVariable("ANDROID_NDK_ROOT", ndkRoot);
                    }
                }

                var androidTargetArch = UnityEditor.PlayerSettings.Android.targetArchitectures;
                if ((androidTargetArch & AndroidArchitecture.ARMv7) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/armeabi-v7a", TargetCpu.ARMV7A_NEON32));
                }
                if ((androidTargetArch & AndroidArchitecture.ARM64) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/arm64-v8a", TargetCpu.ARMV8A_AARCH64));
                }
                if ((androidTargetArch & AndroidArchitecture.X86) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/x86", TargetCpu.X86_SSE2));
                }
            }
            else if (targetPlatform == TargetPlatform.UWP)
            {
                // TODO: Make it configurable for x86 (sse2, sse4)
                combinations.Add(new BurstOutputCombination("Plugins/x64", TargetCpu.X64_SSE4));
                combinations.Add(new BurstOutputCombination("Plugins/x86", TargetCpu.X86_SSE2));
                combinations.Add(new BurstOutputCombination("Plugins/ARM", TargetCpu.THUMB2_NEON32));
                combinations.Add(new BurstOutputCombination("Plugins/ARM64", TargetCpu.ARMV8A_AARCH64));
            }
            else
            {
                combinations.Add(new BurstOutputCombination("Data/Plugins/", targetCpu));
            }

            foreach (var combination in combinations)
            {
                // Gets the output folder
                var stagingOutputFolder = Path.GetFullPath(Path.Combine(TempStaging, combination.OutputPath));
                var outputFilePrefix    = Path.Combine(stagingOutputFolder, DefaultLibraryName);

                var options = new List <string>(commonOptions);
                options.Add(GetOption(OptionAotOutputPath, outputFilePrefix));
                options.Add(GetOption(OptionTarget, combination.TargetCpu));

                if (aotSettingsForTarget.DisableOptimisations)
                {
                    options.Add(GetOption(OptionDisableOpt));
                }
                if (aotSettingsForTarget.DisableSafetyChecks)
                {
                    options.Add(GetOption(OptionDisableSafetyChecks));
                }
                else
                {
                    options.Add(GetOption(OptionSafetyChecks));
                }

                var responseFile = Path.GetTempFileName();
                File.WriteAllLines(responseFile, options);

                //Debug.Log("Burst compile with response file: " + responseFile);

                try
                {
                    Runner.RunManagedProgram(Path.Combine(BurstLoader.RuntimePath, BurstAotCompilerExecutable), "--debug=true " + "@" + responseFile, Application.dataPath + "/..", new BclParser(), null);
                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }
        }
示例#14
0
        private static TargetPlatform?TryGetTargetPlatform(BuildTarget target, out MinMaxTargetCpu targetCpu)
        {
            var aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(target);

            // TODO: Add support for multi-CPU switch
            targetCpu.min = TargetCpu.Auto;
            targetCpu.max = TargetCpu.Auto;
            switch (target)
            {
            case BuildTarget.StandaloneWindows:
                targetCpu = aotSettingsForTarget.GetDesktopCpu32Bit();
                return(TargetPlatform.Windows);

            case BuildTarget.StandaloneWindows64:
                targetCpu = aotSettingsForTarget.GetDesktopCpu64Bit();
                return(TargetPlatform.Windows);

            case BuildTarget.StandaloneOSX:
                targetCpu = aotSettingsForTarget.GetDesktopCpu64Bit();
                return(TargetPlatform.macOS);

#if !UNITY_2019_2_OR_NEWER
            //32 bit linux support was deprecated
            case BuildTarget.StandaloneLinux:
                targetCpu = aotSettingsForTarget.GetDesktopCpu32Bit();
                return(TargetPlatform.Linux);
#endif
            case BuildTarget.StandaloneLinux64:
                targetCpu = aotSettingsForTarget.GetDesktopCpu64Bit();
                return(TargetPlatform.Linux);

            case BuildTarget.WSAPlayer:
                targetCpu = new MinMaxTargetCpu(TargetCpu.X64_SSE4);
                return(TargetPlatform.UWP);

            case BuildTarget.XboxOne:
                targetCpu = new MinMaxTargetCpu(TargetCpu.X64_SSE4);
                return(TargetPlatform.XboxOne);

            case BuildTarget.PS4:
                targetCpu = new MinMaxTargetCpu(TargetCpu.X64_SSE4);
                return(TargetPlatform.PS4);

            case BuildTarget.Android:
                targetCpu = new MinMaxTargetCpu(TargetCpu.ARMV7A_NEON32);
                return(TargetPlatform.Android);

            case BuildTarget.iOS:
                targetCpu = new MinMaxTargetCpu(TargetCpu.ARMV7A_NEON32);
                return(TargetPlatform.iOS);

            case BuildTarget.Lumin:
                targetCpu = new MinMaxTargetCpu(TargetCpu.ARMV8A_AARCH64);
                return(TargetPlatform.Lumin);

            case BuildTarget.Switch:
                targetCpu = new MinMaxTargetCpu(TargetCpu.ARMV8A_AARCH64);
                return(TargetPlatform.Switch);

#if UNITY_2019_3_OR_NEWER
            case BuildTarget.Stadia:
                targetCpu = new MinMaxTargetCpu(TargetCpu.AVX2);
                return(TargetPlatform.Stadia);
#endif
            }
            return(null);
        }
        public void OnPostBuildPlayerScriptDLLs(BuildReport report)
        {
            BurstPlatformAotSettings aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated or the platform is not supported
            if (aotSettingsForTarget.DisableBurstCompilation || !IsSupportedPlatform(report.summary.platform))
            {
                return;
            }

            // Collect all method signatures
            var methodsToCompile = BurstReflection.FindExecuteMethods(AssembliesType.Player);

            if (methodsToCompile.Count == 0)
            {
                return; // Nothing to do
            }

            // Prepare options

            // We are grouping methods per their compiler options (float precision...etc)
            var methodGroups = new Dictionary <string, List <string> >();

            for (var i = 0; i < methodsToCompile.Count; i++)
            {
                var burstCompileTarget = methodsToCompile[i];
                if (!burstCompileTarget.IsSupported)
                {
                    continue;
                }

                var methodStr           = BurstCompilerService.GetMethodSignature(burstCompileTarget.Method);
                var methodFullSignature = methodStr + "--" + Hash128.Compute(methodStr);

                if (aotSettingsForTarget.DisableOptimisations)
                {
                    burstCompileTarget.Options.DisableOptimizations = true;
                }

                burstCompileTarget.Options.EnableBurstSafetyChecks = !aotSettingsForTarget.DisableSafetyChecks;

                string optionsAsStr;
                if (burstCompileTarget.TryGetOptionsAsString(false, out optionsAsStr))
                {
                    List <string> methodOptions;
                    if (!methodGroups.TryGetValue(optionsAsStr, out methodOptions))
                    {
                        methodOptions = new List <string>();
                        methodGroups.Add(optionsAsStr, methodOptions);
                    }
                    methodOptions.Add(GetOption(OptionAotMethod, methodFullSignature));
                }
            }

            var methodGroupOptions = new List <string>();

            // We should have something like this in the end:
            //
            // --group                1st group of method with the following shared options
            // --float-mode=xxx
            // --method=...
            // --method=...
            //
            // --group                2nd group of methods with the different shared options
            // --float-mode=yyy
            // --method=...
            // --method=...
            if (methodGroups.Count == 1)
            {
                var methodGroup = methodGroups.FirstOrDefault();
                // No need to create a group if we don't have multiple
                methodGroupOptions.Add(methodGroup.Key);
                foreach (var methodOption in methodGroup.Value)
                {
                    methodGroupOptions.Add(methodOption);
                }
            }
            else
            {
                foreach (var methodGroup in methodGroups)
                {
                    methodGroupOptions.Add(GetOption(OptionGroup));
                    methodGroupOptions.Add(methodGroup.Key);
                    foreach (var methodOption in methodGroup.Value)
                    {
                        methodGroupOptions.Add(methodOption);
                    }
                }
            }

            var commonOptions  = new List <string>();
            var targetCpu      = TargetCpu.Auto;
            var targetPlatform = GetTargetPlatformAndDefaultCpu(report.summary.platform, out targetCpu);

            commonOptions.Add(GetOption(OptionPlatform, targetPlatform));

            // TODO: Add support for configuring the optimizations/CPU
            // TODO: Add support for per method options

            var stagingFolder = Path.GetFullPath(TempStagingManaged);
            //Debug.Log($"Burst CompileAot - To Folder {stagingFolder}");

            // Prepare assembly folder list
            var assemblyFolders = new List <string>();

            assemblyFolders.Add(stagingFolder);

            var playerAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player);

            foreach (var assembly in playerAssemblies)
            {
                foreach (var assemblyRef in assembly.compiledAssemblyReferences)
                {
                    // Exclude folders with assemblies already compiled in the `folder`
                    var assemblyName = Path.GetFileName(assemblyRef);
                    if (assemblyName != null && File.Exists(Path.Combine(stagingFolder, assemblyName)))
                    {
                        continue;
                    }

                    var directory = Path.GetDirectoryName(assemblyRef);
                    if (directory != null)
                    {
                        var fullPath = Path.GetFullPath(directory);
                        if (IsMonoReferenceAssemblyDirectory(fullPath) || IsDotNetStandardAssemblyDirectory(fullPath))
                        {
                            // Don't pass reference assemblies to burst because they contain methods without implementation
                            // If burst accidentally resolves them, it will emit calls to burst_abort.
                            fullPath = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/lib/mono/unityaot");
                            fullPath = Path.GetFullPath(fullPath); // GetFullPath will normalize path separators to OS native format
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }

                            fullPath = Path.Combine(fullPath, "Facades");
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }
                        }
                        else if (!assemblyFolders.Contains(fullPath))
                        {
                            assemblyFolders.Add(fullPath);
                        }
                    }
                }
            }

            commonOptions.AddRange(assemblyFolders.Select(folder => GetOption(OptionAotAssemblyFolder, folder)));

            var combinations = new List <BurstOutputCombination>();

            if (targetPlatform == TargetPlatform.macOS)
            {
                // NOTE: OSX has a special folder for the plugin
                // Declared in GetStagingAreaPluginsFolder
                // PlatformDependent\OSXPlayer\Extensions\Managed\OSXDesktopStandalonePostProcessor.cs
                combinations.Add(new BurstOutputCombination("UnityPlayer.app/Contents/Plugins", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.iOS)
            {
                var targetArchitecture = (IOSArchitecture)UnityEditor.PlayerSettings.GetArchitecture(report.summary.platformGroup);
                if (targetArchitecture == IOSArchitecture.ARMv7 || targetArchitecture == IOSArchitecture.Universal)
                {
                    // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                    combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV7A_NEON32, DefaultLibraryName + "32"));
                }
                if (targetArchitecture == IOSArchitecture.ARM64 || targetArchitecture == IOSArchitecture.Universal)
                {
                    // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                    combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV8A_AARCH64, DefaultLibraryName + "64"));
                }
            }
            else if (targetPlatform == TargetPlatform.Android)
            {
                // Set the ANDROID_NDK_ROOT so BCL knows where to find the Android toolchain
                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT")))
                {
                    var ndkRoot = EditorPrefs.GetString("AndroidNdkRoot");
                    if (!string.IsNullOrEmpty(ndkRoot))
                    {
                        Environment.SetEnvironmentVariable("ANDROID_NDK_ROOT", ndkRoot);
                    }
                }

                var androidTargetArch = UnityEditor.PlayerSettings.Android.targetArchitectures;
                if ((androidTargetArch & AndroidArchitecture.ARMv7) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/armeabi-v7a", TargetCpu.ARMV7A_NEON32));
                }
                if ((androidTargetArch & AndroidArchitecture.ARM64) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/arm64-v8a", TargetCpu.ARMV8A_AARCH64));
                }
                if ((androidTargetArch & AndroidArchitecture.X86) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/x86", TargetCpu.X86_SSE2));
                }
            }
            else if (targetPlatform == TargetPlatform.UWP)
            {
                // TODO: Make it configurable for x86 (sse2, sse4)
                combinations.Add(new BurstOutputCombination("Plugins/x64", TargetCpu.X64_SSE4));
                combinations.Add(new BurstOutputCombination("Plugins/x86", TargetCpu.X86_SSE2));
                combinations.Add(new BurstOutputCombination("Plugins/ARM", TargetCpu.THUMB2_NEON32));
                combinations.Add(new BurstOutputCombination("Plugins/ARM64", TargetCpu.ARMV8A_AARCH64));
            }
            else
            {
                combinations.Add(new BurstOutputCombination("Data/Plugins/", targetCpu));
            }

            foreach (var combination in combinations)
            {
                // Gets the output folder
                var stagingOutputFolder = Path.GetFullPath(Path.Combine(TempStaging, combination.OutputPath));
                var outputFilePrefix    = Path.Combine(stagingOutputFolder, combination.LibraryName);

                var options = new List <string>(commonOptions);
                options.Add(GetOption(OptionAotOutputPath, outputFilePrefix));
                options.Add(GetOption(OptionTarget, combination.TargetCpu));

                if (targetPlatform == TargetPlatform.iOS)
                {
                    options.Add(GetOption(OptionStaticLinkage));
                }

                // finally add method group options
                options.AddRange(methodGroupOptions);

                var responseFile = Path.GetTempFileName();
                File.WriteAllLines(responseFile, options);

                //Debug.Log("Burst compile with response file: " + responseFile);

                try
                {
                    Runner.RunManagedProgram(Path.Combine(BurstLoader.RuntimePath, BurstAotCompilerExecutable), "--debug=true " + "@" + responseFile, Application.dataPath + "/..", new BclParser(), null);
                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }
        }