Exemple #1
0
        public override void Execute(Pipeline pipeline)
        {
            var mani = pipeline.Manifest;
            var allThunderstoreManifests = pipeline.Datums.OfType <ThunderstoreManifest>();
            var thunderstoreManifest     = mani.Data.OfType <ThunderstoreManifest>().First();
            var dependencies             = thunderstoreManifest.dependencies;

            bool IsDependency(string dependency, ThunderstoreManifest man) => $"{man.author}-{man.name}-{man.versionNumber}".Equals(dependency);

            var dependantManifests = pipeline.manifests
                                     .Where(man => man.Data.OfType <ThunderstoreManifest>().Any())
                                     .Select(man => (manifest: man, tsManifest: man.Data.OfType <ThunderstoreManifest>().First()))
                                     .Where(projection => dependencies.Any(dep => IsDependency(dep, projection.tsManifest)))
                                     .Select(projection => projection.manifest);

            var explicitDownstreamAssets = dependantManifests
                                           .SelectMany(man => man.Data.OfType <AssetBundleDefs>())
                                           .SelectMany(mabd => mabd.assetBundles)
                                           .SelectMany(ab => ab.assets)
                                           .Select(asset => AssetDatabase.GetAssetPath(asset))
                                           .ToArray();

            AssetDatabase.SaveAssets();
            foreach (var assetBundleDef in mani.Data.OfType <AssetBundleDefs>())
            {
                var playerAssemblies   = CompilationPipeline.GetAssemblies();
                var assemblyFiles      = playerAssemblies.Select(pa => pa.outputPath).ToArray();
                var sourceFiles        = playerAssemblies.SelectMany(pa => pa.sourceFiles).ToArray();
                var excludedExtensions = new[] { ".dll" };

                var builds    = new AssetBundleBuild[assetBundleDef.assetBundles.Length];
                var fileCount = 0;

                var logBuilder = new StringBuilder();
                logBuilder.AppendLine("Constructing AssetBundles");

                for (int i = 0; i < assetBundleDef.assetBundles.Length; i++)
                {
                    var def            = assetBundleDef.assetBundles[i];
                    var explicitAssets = assetBundleDef.assetBundles.Where((ab, abi) => abi != i).SelectMany(ab => ab.assets).Select(asset => AssetDatabase.GetAssetPath(asset)).ToArray();
                    var build          = builds[i];
                    var assets         = new List <string>();
                    logBuilder.AppendLine($"Building bundle: {def.assetBundleName}");
                    if (def.assets.OfType <SceneAsset>().Any())
                    {
                        assets.Add(AssetDatabase.GetAssetPath(def.assets.OfType <SceneAsset>().First()));
                    }
                    else
                    {
                        foreach (var asset in def.assets)
                        {
                            var  assetPath = AssetDatabase.GetAssetPath(asset);
                            bool isFolder  = AssetDatabase.IsValidFolder(assetPath);

                            logBuilder.AppendLine($"Asset: {asset.name} is a {(isFolder ? "Folder" : "File")}");
                            if (isFolder)
                            {
                                var bundleAssets = AssetDatabase.GetAllAssetPaths()
                                                   .Where(ap => !AssetDatabase.IsValidFolder(ap))
                                                   .Where(ap => ap.StartsWith(assetPath))
                                                   .Where(ap => !assets.Contains(ap))
                                                   .Where(ap => !sourceFiles.Contains(ap))
                                                   .Where(ap => !assemblyFiles.Contains(ap))
                                                   .Where(ap => recurseDirectories || Path.GetDirectoryName(ap).Replace('\\', '/').Equals(assetPath))
                                                   .SelectMany(ap => AssetDatabase.GetDependencies(ap)
                                                               .Where(dap => !explicitAssets.Contains(dap))
                                                               .Where(dap => !explicitDownstreamAssets.Contains(dap))
                                                               )
                                                   .Where(ap =>
                                {
                                    var extension = Path.GetExtension(ap);
                                    return(!excludedExtensions.Contains(extension));
                                })

                                                   .Where(ap => !assets.Contains(ap))
                                ;
                                assets.AddRange(bundleAssets);
                            }
                            else
                            {
                                var validAssets = AssetDatabase.GetDependencies(assetPath)
                                                  .Where(dap => !explicitDownstreamAssets.Contains(dap))
                                                  .Where(dap => !explicitAssets.Contains(dap))
                                                  .Where(ap => !assets.Contains(ap))
                                                  .Where(ap =>
                                {
                                    var extension = Path.GetExtension(ap);
                                    return(!excludedExtensions.Contains(extension));
                                })
                                                  .Where(ap => !sourceFiles.Contains(ap))
                                                  .Where(ap => !assemblyFiles.Contains(ap))
                                                  .Where(ap => AssetDatabase.GetMainAssetTypeAtPath(ap) != typeof(UnityPackage))
                                ;
                                assets.AddRange(validAssets);
                            }
                        }
                    }
                    build.assetNames      = assets.ToArray();
                    build.assetBundleName = def.assetBundleName;
                    builds[i]             = build;
                    fileCount            += build.assetNames.Length;
                    foreach (var asset in build.assetNames)
                    {
                        logBuilder.AppendLine(asset);
                    }
                }

                logBuilder.AppendLine($"Constructed {builds.Length} AssetBundleBuilds with {fileCount} files.");

                if (!simulate)
                {
                    var stablePath = BundleArtifactPath.Resolve(pipeline, this);
                    Directory.CreateDirectory(stablePath);
                    BuildPipeline.BuildAssetBundles(stablePath, builds, AssetBundleBuildOptions, buildTarget);

                    foreach (var outputPath in assetBundleDef.StagingPaths.Select(path => path.Resolve(pipeline, this)))
                    {
                        CopyFilesRecursively(stablePath, outputPath);
                    }
                }

                Debug.Log(logBuilder.ToString());
            }
        }
        private Dictionary <string, CSProjectInfo> CreateUnityProjects(string projectOutputPath)
        {
            // Not all of these will be converted to C# objects, only the ones found to be referenced
            Dictionary <string, AssemblyDefinitionInfo> asmDefInfoMap = new Dictionary <string, AssemblyDefinitionInfo>();
            HashSet <string> builtInPackagesWithoutSource             = new HashSet <string>();

            // Parse the builtInPackagesFirst
            DirectoryInfo builtInPackagesDirectory = new DirectoryInfo(Utilities.BuiltInPackagesPath);

            foreach (DirectoryInfo packageDirectory in builtInPackagesDirectory.GetDirectories())
            {
                FileInfo[] asmDefFiles = packageDirectory.GetFiles("*.asmdef", SearchOption.AllDirectories);

                if (asmDefFiles.Length == 0)
                {
                    builtInPackagesWithoutSource.Add(packageDirectory.Name.ToLower());
                    continue;
                }

                foreach (FileInfo fileInfo in asmDefFiles)
                {
                    AssemblyDefinitionInfo assemblyDefinitionInfo = AssemblyDefinitionInfo.Parse(fileInfo, this, null, true);
                    asmDefInfoMap.Add(Path.GetFileNameWithoutExtension(fileInfo.Name), assemblyDefinitionInfo);
                }
            }

            Dictionary <string, Assembly>      unityAssemblies = CompilationPipeline.GetAssemblies().ToDictionary(t => t.name);
            Dictionary <string, CSProjectInfo> projectsMap     = new Dictionary <string, CSProjectInfo>();
            Queue <string> projectsToProcess = new Queue <string>();

            // Parse the unity assemblies
            foreach (KeyValuePair <string, Assembly> pair in unityAssemblies)
            {
                if (!asmDefInfoMap.TryGetValue(pair.Key, out AssemblyDefinitionInfo assemblyDefinitionInfo))
                {
                    string asmDefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(pair.Key);
                    if (string.IsNullOrEmpty(asmDefPath))
                    {
                        if (!pair.Key.StartsWith("Assembly-CSharp"))
                        {
                            throw new InvalidOperationException($"Failed to retrieve AsmDef for script assembly: {pair.Key}");
                        }

                        assemblyDefinitionInfo = AssemblyDefinitionInfo.GetDefaultAssemblyCSharpInfo(pair.Value);
                        projectsToProcess.Enqueue(pair.Key);
                    }
                    else
                    {
                        assemblyDefinitionInfo = AssemblyDefinitionInfo.Parse(new FileInfo(Utilities.GetFullPathFromKnownRelative(asmDefPath)), this, pair.Value);

                        if (asmDefPath.StartsWith("Assets/"))
                        {
                            // Add as mandatory
                            projectsToProcess.Enqueue(pair.Key);
                        }
                    }

                    asmDefInfoMap.Add(pair.Key, assemblyDefinitionInfo);
                }
            }

            while (projectsToProcess.Count > 0)
            {
                string projectKey = projectsToProcess.Dequeue();

                if (!projectsMap.ContainsKey(projectKey))
                {
                    GetProjectInfo(projectsMap, asmDefInfoMap, builtInPackagesWithoutSource, projectKey, projectOutputPath);
                }
            }

            // Ignore test projects when generating docs with Unity 2019
#if UNITY_2019_3_OR_NEWER
            projectsMap.Remove("Microsoft.MixedReality.Toolkit.Tests.EditModeTests");
            projectsMap.Remove("Microsoft.MixedReality.Toolkit.Tests.PlayModeTests");
#endif
            return(projectsMap);
        }
        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());
                }
            }
        }
Exemple #4
0
        IEnumerable <ResponseFileData> ParseResponseFileData(Assembly assembly)
        {
            var systemReferenceDirectories = CompilationPipeline.GetSystemAssemblyDirectories(assembly.compilerOptions.ApiCompatibilityLevel);

            Dictionary <string, ResponseFileData> responseFilesData = assembly.compilerOptions.ResponseFiles.ToDictionary(x => x, x => CompilationPipeline.ParseResponseFile(
                                                                                                                              Path.Combine(ProjectDirectory, x),
                                                                                                                              ProjectDirectory,
                                                                                                                              systemReferenceDirectories
                                                                                                                              ));

            Dictionary <string, ResponseFileData> responseFilesWithErrors = responseFilesData.Where(x => x.Value.Errors.Any())
                                                                            .ToDictionary(x => x.Key, x => x.Value);

            if (responseFilesWithErrors.Any())
            {
                foreach (var error in responseFilesWithErrors)
                {
                    foreach (var valueError in error.Value.Errors)
                    {
                        Debug.LogError($"{error.Key} Parse Error : {valueError}");
                    }
                }
            }

            return(responseFilesData.Select(x => x.Value));
        }
Exemple #5
0
 public IEnumerable <Assembly> GetAssemblies(Func <string, bool> shouldFileBePartOfSolution)
 {
     // CompilationPipeline.GetAssemblies(AssembliesType.Player).Where(i => 0 < i.sourceFiles.Length && i.sourceFiles.Any(shouldFileBePartOfSolution));
     return(CompilationPipeline.GetAssemblies().Where(i => 0 < i.sourceFiles.Length && i.sourceFiles.Any(shouldFileBePartOfSolution)));
 }
Exemple #6
0
 static Assembly FindCompilationPipelineAssembly(string assemblyName) =>
 CompilationPipeline.GetAssemblies().First(assembly => assembly.name == assemblyName);
        public IEnumerable <AssemblyInfo> Compile(IProgressBar progressBar = null)
        {
#if UNITY_2018_1_OR_NEWER
            var assemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player);
#else
            var assemblies = CompilationPipeline.GetAssemblies();
#endif

#if UNITY_2018_2_OR_NEWER
            if (progressBar != null)
            {
                var numAssemblies = assemblies.Length;
                progressBar.Initialize("Assembly Compilation", "Compiling project scripts",
                                       numAssemblies);
                m_OnAssemblyCompilationStarted = (s) =>
                {
                    progressBar.AdvanceProgressBar(Path.GetFileName(s));
                };
                CompilationPipeline.assemblyCompilationStarted += m_OnAssemblyCompilationStarted;
            }
            CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished;

            m_OutputFolder = FileUtil.GetUniqueTempPathInProject();

            var input = new ScriptCompilationSettings
            {
                target = EditorUserBuildSettings.activeBuildTarget,
                group  = EditorUserBuildSettings.selectedBuildTargetGroup
            };

            var compilationResult = PlayerBuildInterface.CompilePlayerScripts(input, m_OutputFolder);

            if (progressBar != null)
            {
                progressBar.ClearProgressBar();
            }

            if (!m_Success)
            {
                Dispose();
                throw new AssemblyCompilationException();
            }

            var compiledAssemblyPaths = compilationResult.assemblies.Select(assembly => Path.Combine(m_OutputFolder, assembly));
#else
            // fallback to CompilationPipeline assemblies
            var compiledAssemblyPaths = CompilationPipeline.GetAssemblies()
                                        .Where(a => a.flags != AssemblyFlags.EditorAssembly).Select(assembly => assembly.outputPath);
#endif

            var assemblyInfos = new List <AssemblyInfo>();
            foreach (var compiledAssemblyPath in compiledAssemblyPaths)
            {
                var assemblyInfo = AssemblyHelper.GetAssemblyInfoFromAssemblyPath(compiledAssemblyPath);
                var assembly     = assemblies.First(a => a.name.Equals(assemblyInfo.name));
                var sourcePaths  = assembly.sourceFiles.Select(file => file.Remove(0, assemblyInfo.relativePath.Length + 1));

                assemblyInfo.sourcePaths = sourcePaths.ToArray();
                assemblyInfos.Add(assemblyInfo);
            }

            return(assemblyInfos);
        }
        private static HashSet <string> GetReferencedAssemblyNameSet()
        {
            if (s_referencedAssemblyNameSet != null)
            {
                return(s_referencedAssemblyNameSet);
            }

            s_referencedAssemblyNameSet = new HashSet <string>();
            Assembly playerAssembly = typeof(VRModule).Assembly;
            Assembly editorAssembly = typeof(VRModuleManagerEditor).Assembly;

            // C# player referenced assemblies
            foreach (AssemblyName asmName in playerAssembly.GetReferencedAssemblies())
            {
                s_referencedAssemblyNameSet.Add(asmName.Name);
            }

            // C# editor referenced assemblies
            foreach (AssemblyName asmName in editorAssembly.GetReferencedAssemblies())
            {
                s_referencedAssemblyNameSet.Add(asmName.Name);
            }

#if UNITY_2018_1_OR_NEWER
            // Unity player referenced assemblies
            UnityEditor.Compilation.Assembly playerUnityAsm = FindUnityAssembly(playerAssembly.GetName().Name, AssembliesType.Player);
            if (playerUnityAsm != null)
            {
                foreach (UnityEditor.Compilation.Assembly asm in playerUnityAsm.assemblyReferences)
                {
                    s_referencedAssemblyNameSet.Add(asm.name);
                }
            }
            else
            {
                Debug.LogWarning("Player assembly not found.");
            }

            // Unity editor referenced assemblies
            UnityEditor.Compilation.Assembly editorUnityAsm = FindUnityAssembly(editorAssembly.GetName().Name, AssembliesType.Editor);
            if (editorUnityAsm != null)
            {
                foreach (UnityEditor.Compilation.Assembly asm in editorUnityAsm.assemblyReferences)
                {
                    s_referencedAssemblyNameSet.Add(asm.name);
                }
            }
            else
            {
                Debug.LogWarning("Editor assembly not found.");
            }
#elif UNITY_2017_3_OR_NEWER
            UnityEditor.Compilation.Assembly[] assemblies = CompilationPipeline.GetAssemblies();
            foreach (UnityEditor.Compilation.Assembly asm in assemblies)
            {
                s_referencedAssemblyNameSet.Add(asm.name);
            }
#endif

            return(s_referencedAssemblyNameSet);
        }
        static AssemblyDefintionState LoadAssemblyDefintionState(string path)
        {
            var asset = AssetDatabase.LoadAssetAtPath <AssemblyDefinitionAsset>(path);

            if (asset == null)
            {
                return(null);
            }

            var data = CustomScriptAssemblyData.FromJson(asset.text);

            if (data == null)
            {
                return(null);
            }

            var state = new AssemblyDefintionState();

            state.asset           = asset;
            state.name            = data.name;
            state.references      = new List <AssemblyDefinitionReference>();
            state.allowUnsafeCode = ToMixedBool(data.allowUnsafeCode);

            if (data.references != null)
            {
                foreach (var reference in data.references)
                {
                    try
                    {
                        var assemblyDefinitionFile = new AssemblyDefinitionReference();
                        var referencePath          = Compilation.CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(reference);

                        if (string.IsNullOrEmpty(referencePath))
                        {
                            throw new AssemblyDefinitionException(string.Format("Could not find assembly reference '{0}'", reference), path);
                        }

                        assemblyDefinitionFile.asset = AssetDatabase.LoadAssetAtPath <AssemblyDefinitionAsset>(referencePath);

                        if (assemblyDefinitionFile.asset == null)
                        {
                            throw new AssemblyDefinitionException(string.Format("Reference assembly definition file '{0}' not found", referencePath), path);
                        }

                        assemblyDefinitionFile.data         = CustomScriptAssemblyData.FromJson(assemblyDefinitionFile.asset.text);
                        assemblyDefinitionFile.displayValue = MixedBool.False;
                        state.references.Add(assemblyDefinitionFile);
                    }
                    catch (AssemblyDefinitionException e)
                    {
                        UnityEngine.Debug.LogException(e, asset);
                        state.references.Add(new AssemblyDefinitionReference());
                        state.modified = true;
                    }
                }
            }

            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();

            state.platformCompatibility = new MixedBool[platforms.Length];

            var OptinalUnityAssemblies = CustomScriptAssembly.OptinalUnityAssemblies;

            state.optionalUnityReferences = new MixedBool[OptinalUnityAssemblies.Length];

            if (data.optionalUnityReferences != null)
            {
                for (int i = 0; i < OptinalUnityAssemblies.Length; i++)
                {
                    var optionalUnityReferences = OptinalUnityAssemblies[i].OptionalUnityReferences.ToString();
                    var any = data.optionalUnityReferences.Any(x => x == optionalUnityReferences);
                    if (any)
                    {
                        state.optionalUnityReferences[i] = MixedBool.True;
                    }
                }
            }

            state.compatibleWithAnyPlatform = MixedBool.True;
            string[] dataPlatforms = null;

            if (data.includePlatforms != null && data.includePlatforms.Length > 0)
            {
                state.compatibleWithAnyPlatform = MixedBool.False;
                dataPlatforms = data.includePlatforms;
            }
            else if (data.excludePlatforms != null && data.excludePlatforms.Length > 0)
            {
                state.compatibleWithAnyPlatform = MixedBool.True;
                dataPlatforms = data.excludePlatforms;
            }

            if (dataPlatforms != null)
            {
                foreach (var platform in dataPlatforms)
                {
                    var platformIndex = GetPlatformIndex(platforms, platform);
                    state.platformCompatibility[platformIndex] = MixedBool.True;
                }
            }

            return(state);
        }
Exemple #10
0
        public override void Execute(Pipeline pipeline)
        {
            var excludedExtensions = new[] { ".dll", ".cs", ".meta" };

            AssetDatabase.SaveAssets();

            var assetBundleDefs    = pipeline.Datums.OfType <AssetBundleDefinitions>().ToArray();
            var bundleArtifactPath = BundleArtifactPath.Resolve(pipeline, this);

            Directory.CreateDirectory(bundleArtifactPath);

            var builds      = new AssetBundleBuild[assetBundleDefs.Sum(abd => abd.assetBundles.Length)];
            var buildsIndex = 0;

            for (int defIndex = 0; defIndex < assetBundleDefs.Length; defIndex++)
            {
                var assetBundleDef   = assetBundleDefs[defIndex];
                var playerAssemblies = CompilationPipeline.GetAssemblies();
                var assemblyFiles    = playerAssemblies.Select(pa => pa.outputPath).ToArray();
                var sourceFiles      = playerAssemblies.SelectMany(pa => pa.sourceFiles).ToArray();

                var fileCount = 0;

                var logBuilder = new StringBuilder();
                logBuilder.AppendLine("Constructing AssetBundles");
                for (int i = 0; i < assetBundleDef.assetBundles.Length; i++)
                {
                    var def = assetBundleDef.assetBundles[i];

                    var explicitAssets = assetBundleDef.assetBundles.Where((ab, abi) => abi != i).SelectMany(ab => ab.assets).Select(asset => AssetDatabase.GetAssetPath(asset)).ToArray();
                    var build          = builds[buildsIndex];

                    var assets = new List <string>();

                    logBuilder.AppendLine($"Building bundle: {def.assetBundleName}");

                    var firstAsset = def.assets.FirstOrDefault(x => x is SceneAsset);

                    if (firstAsset != null)
                    {
                        assets.Add(AssetDatabase.GetAssetPath(firstAsset));
                    }
                    else
                    {
                        foreach (var asset in def.assets)
                        {
                            var assetPath = AssetDatabase.GetAssetPath(asset);

                            if (AssetDatabase.IsValidFolder(assetPath))
                            {
                                assets.AddRange(Directory.GetFiles(assetPath, "*", SearchOption.AllDirectories)
                                                .SelectMany(ap => AssetDatabase.GetDependencies(ap).Union(new[] { ap })));
                            }

                            else if (asset is UnityPackage up)
                            {
                                if (up.exportPackageOptions.HasFlag(ExportPackageOptions.Recurse))
                                {
                                    foreach (var upAsset in up.AssetFiles)
                                    {
                                        var path = AssetDatabase.GetAssetPath(upAsset);
                                        if (AssetDatabase.IsValidFolder(path))
                                        {
                                            assets.AddRange(Directory.GetFiles(path, "*", SearchOption.AllDirectories)
                                                            .SelectMany(ap => AssetDatabase.GetDependencies(ap).Union(new[] { ap })));
                                        }
                                        else
                                        {
                                            assets.Add(path);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                assets.AddRange(AssetDatabase.GetDependencies(assetPath)
                                                .Where(ap => AssetDatabase.GetMainAssetTypeAtPath(ap) != typeof(UnityPackage))
                                                .Union(new[] { assetPath }));
                            }
                        }
                    }

                    build.assetNames = assets
                                       .Select(ap => ap.Replace("\\", "/"))
                                       //.Where(dap => !explicitDownstreamAssets.Contains(dap))
                                       .Where(dap => !ArrayUtility.Contains(explicitAssets, dap) &&
                                              !ArrayUtility.Contains(excludedExtensions, Path.GetExtension(dap)) &&
                                              !ArrayUtility.Contains(sourceFiles, dap) &&
                                              !ArrayUtility.Contains(assemblyFiles, dap) &&
                                              !AssetDatabase.IsValidFolder(dap))
                                       .Distinct()
                                       .ToArray();
                    build.assetBundleName = def.assetBundleName;
                    builds[buildsIndex]   = build;
                    buildsIndex++;

                    fileCount += build.assetNames.Length;
                    foreach (var asset in build.assetNames)
                    {
                        logBuilder.AppendLine(asset);
                    }
                }
                logBuilder.AppendLine($"Constructed {builds.Length} AssetBundleBuilds with {fileCount} files.");

                Debug.Log(logBuilder.ToString());
            }

            if (!simulate)
            {
                var allBuilds = builds.ToArray();
                BuildPipeline.BuildAssetBundles(bundleArtifactPath, allBuilds, AssetBundleBuildOptions, buildTarget);
                for (pipeline.ManifestIndex = 0; pipeline.ManifestIndex < pipeline.Manifests.Length; pipeline.ManifestIndex++)
                {
                    var manifest = pipeline.Manifest;
                    foreach (var assetBundleDef in manifest.Data.OfType <AssetBundleDefinitions>())
                    {
                        var bundleNames = assetBundleDef.assetBundles.Select(ab => ab.assetBundleName).ToArray();
                        foreach (var outputPath in assetBundleDef.StagingPaths.Select(path => path.Resolve(pipeline, this)))
                        {
                            foreach (string dirPath in Directory.GetDirectories(bundleArtifactPath, "*", SearchOption.AllDirectories))
                            {
                                Directory.CreateDirectory(dirPath.Replace(bundleArtifactPath, outputPath));
                            }

                            foreach (string filePath in Directory.GetFiles(bundleArtifactPath, "*", SearchOption.AllDirectories))
                            {
                                bool found = false;
                                foreach (var bundleName in bundleNames)
                                {
                                    if (filePath.IndexOf(bundleName, System.StringComparison.OrdinalIgnoreCase) >= 0)
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found)
                                {
                                    continue;
                                }
                                string destFileName = filePath.Replace(bundleArtifactPath, outputPath);
                                Directory.CreateDirectory(Path.GetDirectoryName(destFileName));
                                FileUtil.ReplaceFile(filePath, destFileName);
                            }

                            var manifestSource      = Path.Combine(bundleArtifactPath, $"{Path.GetFileName(bundleArtifactPath)}.manifest");
                            var manifestDestination = Path.Combine(outputPath, $"{manifest.Identity.Name}.manifest");
                            FileUtil.ReplaceFile(manifestSource, manifestDestination);
                        }
                    }
                }
                pipeline.ManifestIndex = -1;
            }
        }
 public static void Do()
 {
     CompilationPipeline.RequestScriptCompilation();
 }
 public static void RecompileScripts()
 {
     CompilationPipeline.RequestScriptCompilation();
 }
Exemple #13
0
        private Dictionary <string, CSProjectInfo> CreateUnityProjects()
        {
            // Not all of these will be converted to C# objects, only the ones found to be referenced
            Dictionary <string, AssemblyDefinitionInfo> asmDefInfoMap           = new Dictionary <string, AssemblyDefinitionInfo>();
            SortedSet <AssemblyDefinitionInfo>          asmDefDirectoriesSorted = new SortedSet <AssemblyDefinitionInfo>(Comparer <AssemblyDefinitionInfo> .Create((a, b) => a.Directory.FullName.CompareTo(b.Directory.FullName)));

            HashSet <string> builtInPackagesWithoutSource = new HashSet <string>();

            // Parse the builtInPackagesFirst
            DirectoryInfo builtInPackagesDirectory = new DirectoryInfo(Utilities.BuiltInPackagesPath);

            foreach (DirectoryInfo packageDirectory in builtInPackagesDirectory.GetDirectories())
            {
                FileInfo[] asmDefFiles = packageDirectory.GetFiles("*.asmdef", SearchOption.AllDirectories);

                if (asmDefFiles.Length == 0)
                {
                    builtInPackagesWithoutSource.Add(packageDirectory.Name.ToLower());
                    continue;
                }

                foreach (FileInfo fileInfo in asmDefFiles)
                {
                    AssemblyDefinitionInfo assemblyDefinitionInfo = AssemblyDefinitionInfo.Parse(fileInfo, this, null, true);
                    asmDefDirectoriesSorted.Add(assemblyDefinitionInfo);
                    asmDefInfoMap.Add(Path.GetFileNameWithoutExtension(fileInfo.Name), assemblyDefinitionInfo);
                }
            }

            Dictionary <string, string> packageCacheVersionedMap = new Dictionary <string, string>();

            foreach (string directory in Directory.GetDirectories(Utilities.PackageLibraryCachePath))
            {
                string directoryName = Path.GetFileName(directory);
                packageCacheVersionedMap.Add(directoryName.Split('@')[0], directoryName);
            }

            Dictionary <string, Assembly>      unityAssemblies = CompilationPipeline.GetAssemblies().ToDictionary(t => t.name);
            Dictionary <string, CSProjectInfo> projectsMap     = new Dictionary <string, CSProjectInfo>();
            Queue <string> projectsToProcess = new Queue <string>();

            // Parse the unity assemblies
            foreach (KeyValuePair <string, Assembly> pair in unityAssemblies)
            {
                if (!asmDefInfoMap.TryGetValue(pair.Key, out AssemblyDefinitionInfo assemblyDefinitionInfo))
                {
                    string asmDefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(pair.Key);
                    if (string.IsNullOrEmpty(asmDefPath))
                    {
                        if (!pair.Key.StartsWith("Assembly-CSharp"))
                        {
                            throw new InvalidOperationException($"Failed to retrieve AsmDef for script assembly: {pair.Key}");
                        }

                        Guid guid;
                        switch (pair.Key)
                        {
                        case "Assembly-CSharp":
                            guid = config.AssemblyCSharpGuid;
                            break;

                        case "Assembly-CSharp-firstpass":
                            guid = config.AssemblyCSharpFirstPassGuid;
                            break;

                        case "Assembly-CSharp-Editor":
                            guid = config.AssemblyCSharpEditorGuid;
                            break;

                        case "Assembly-CSharp-Editor-firstpass":
                            guid = config.AssemblyCSharpFirstPassEditorGuid;
                            break;

                        default:
                            throw new InvalidOperationException($"Predefined assembly '{assemblyDefinitionInfo.Name}' was not recognized, this generally means it should be added to the switch statement in CSProjectInfo:GetProjectType.");
                        }

                        assemblyDefinitionInfo = AssemblyDefinitionInfo.GetDefaultAssemblyCSharpInfo(pair.Value, guid);
                        projectsToProcess.Enqueue(pair.Key);
                    }
                    else
                    {
                        assemblyDefinitionInfo = AssemblyDefinitionInfo.Parse(new FileInfo(Utilities.GetFullPathFromKnownRelative(asmDefPath)), this, pair.Value);

                        if (asmDefPath.StartsWith("Assets/"))
                        {
                            // Add as mandatory
                            projectsToProcess.Enqueue(pair.Key);
                        }
                    }

                    asmDefDirectoriesSorted.Add(assemblyDefinitionInfo);
                    asmDefInfoMap.Add(pair.Key, assemblyDefinitionInfo);
                }
            }

            // This will parse additional asmdefs that are not part of current compilation set, but we still need
            foreach (string asmdefGuid in AssetDatabase.FindAssets("t:asmdef"))
            {
                string asmDefPath = AssetDatabase.GUIDToAssetPath(asmdefGuid);
                string asmDefKey  = Path.GetFileNameWithoutExtension(asmDefPath);
                if (!asmDefInfoMap.ContainsKey(asmDefKey))
                {
                    AssemblyDefinitionInfo assemblyDefinitionInfo = AssemblyDefinitionInfo.Parse(new FileInfo(Utilities.GetFullPathFromKnownRelative(asmDefPath)), this, null);
                    asmDefDirectoriesSorted.Add(assemblyDefinitionInfo);
                    asmDefInfoMap.Add(asmDefKey, assemblyDefinitionInfo);
                }
            }

            // Now we have all of the assembly definiton files, let's run a quick validation.
            ValidateAndPatchAssemblyDefinitions(asmDefInfoMap);

            int index = 0;

            ProcessSortedAsmDef(asmDefDirectoriesSorted.ToArray(), ref index, (uri) => true, (a) => { });

            while (projectsToProcess.Count > 0)
            {
                string projectKey = projectsToProcess.Dequeue();

                if (!projectsMap.ContainsKey(projectKey))
                {
                    GetProjectInfo(projectsMap, asmDefInfoMap, builtInPackagesWithoutSource, projectKey);
                }
            }

            return(projectsMap);
        }
Exemple #14
0
        /// <summary>
        /// Parses the current state of the Unity project.
        /// </summary>
        /// <param name="supportedBuildTargets">BuildTargets that are considered supported.</param>
        /// <param name="config">Config for MSBuildTools.</param>
        /// <param name="performCompleteParse">If this is false, UnityProjectInfo will parse only the minimum required information about current project. Includes: <see cref="ExistingCSProjects"/> <see cref="CurrentPlayerPlatform"/>.</param>
        public UnityProjectInfo(ILogger logger, Dictionary <BuildTarget, string> supportedBuildTargets, MSBuildToolsConfig config, bool performCompleteParse = true)
        {
            this.logger = logger;
            this.config = config;

            if (performCompleteParse)
            {
                AvailablePlatforms = new ReadOnlyCollection <CompilationPlatformInfo>(CompilationPipeline.GetAssemblyDefinitionPlatforms()
                                                                                      .Where(t => Utilities.IsPlatformInstalled(t.BuildTarget))
                                                                                      .Where(t => supportedBuildTargets.ContainsKey(t.BuildTarget))
                                                                                      .Select(CompilationPlatformInfo.GetCompilationPlatform)
                                                                                      .OrderBy(t => t.Name).ToList());

                EditorPlatform = CompilationPlatformInfo.GetEditorPlatform();

                CurrentPlayerPlatform = AvailablePlatforms.First(t => t.BuildTarget == EditorUserBuildSettings.activeBuildTarget);
            }
            else
            {
                CurrentPlayerPlatform = CompilationPlatformInfo.GetCompilationPlatform(
                    CompilationPipeline.GetAssemblyDefinitionPlatforms()
                    .First(t => t.BuildTarget == EditorUserBuildSettings.activeBuildTarget));
            }

            UnityProjectName = Application.productName;

            if (string.IsNullOrWhiteSpace(UnityProjectName))
            {
                UnityProjectName = "UnityProject";
            }

            RefreshPlugins(performCompleteParse);

            if (performCompleteParse)
            {
                RefreshProjects();
            }
        }
        static void SaveAssemblyDefinitionState(AssemblyDefinitionState state)
        {
            var references = state.references;
            var platforms  = CompilationPipeline.GetAssemblyDefinitionPlatforms();

            CustomScriptAssemblyData data = new CustomScriptAssemblyData();

            data.name          = state.assemblyName;
            data.rootNamespace = state.rootNamespace;

            if (state.useGUIDs)
            {
                data.references = references.Select(r =>
                {
                    var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(r.asset));

                    if (string.IsNullOrEmpty(guid))
                    {
                        return(r.serializedReference);
                    }

                    return(CompilationPipeline.GUIDToAssemblyDefinitionReferenceGUID(guid));
                }).ToArray();
            }
            else
            {
                data.references = references.Select(r => r.name).ToArray();
            }

            data.defineConstraints = state.defineConstraints
                                     .Where(x => !string.IsNullOrEmpty(x.name))
                                     .Select(r => r.name)
                                     .ToArray();

            data.versionDefines     = state.versionDefines.ToArray();
            data.autoReferenced     = state.autoReferenced;
            data.overrideReferences = state.overrideReferences;

            data.precompiledReferences = state.precompiledReferences
                                         .Select(r => r.name).ToArray();

            data.allowUnsafeCode    = state.allowUnsafeCode;
            data.noEngineReferences = state.noEngineReferences;

            List <string> dataPlatforms = new List <string>();

            for (int i = 0; i < platforms.Length; ++i)
            {
                if (state.platformCompatibility[i])
                {
                    dataPlatforms.Add(platforms[i].Name);
                }
            }

            if (dataPlatforms.Any())
            {
                if (state.compatibleWithAnyPlatform)
                {
                    data.excludePlatforms = dataPlatforms.ToArray();
                }
                else
                {
                    data.includePlatforms = dataPlatforms.ToArray();
                }
            }

            var json = CustomScriptAssemblyData.ToJson(data);

            File.WriteAllText(state.path, json);

            AssetDatabase.ImportAsset(state.path);
        }
        private static bool IsReferenced(Assembly assembly)
        {
            // C# player referenced assemblies
            foreach (AssemblyName asmName in typeof(VRModule).Assembly.GetReferencedAssemblies())
            {
                if (assembly.GetName().Name == asmName.Name)
                {
                    return(true);
                }
            }

            // C# editor referenced assemblies
            foreach (AssemblyName asmName in typeof(VRModuleManagerEditor).Assembly.GetReferencedAssemblies())
            {
                if (assembly.GetName().Name == asmName.Name)
                {
                    return(true);
                }
            }

#if UNITY_2018_1_OR_NEWER
            // Unity player referenced assemblies
            UnityEditor.Compilation.Assembly playerUnityAsm = FindUnityAssembly(typeof(VRModule).Assembly.GetName().Name, AssembliesType.Player);
            if (playerUnityAsm != null)
            {
                foreach (UnityEditor.Compilation.Assembly asm in playerUnityAsm.assemblyReferences)
                {
                    if (assembly.GetName().Name == asm.name)
                    {
                        return(true);
                    }
                }
            }
            else
            {
                Debug.LogWarning("Player assembly not found.");
            }

            // Unity editor referenced assemblies
            UnityEditor.Compilation.Assembly editorUnityAsm = FindUnityAssembly(typeof(VRModuleManagerEditor).Assembly.GetName().Name, AssembliesType.Editor);
            if (editorUnityAsm != null)
            {
                foreach (UnityEditor.Compilation.Assembly asm in editorUnityAsm.assemblyReferences)
                {
                    if (assembly.GetName().Name == asm.name)
                    {
                        return(true);
                    }
                }
            }
            else
            {
                Debug.LogWarning("Editor assembly not found.");
            }
#elif UNITY_2017_3_OR_NEWER
            UnityEditor.Compilation.Assembly[] assemblies = CompilationPipeline.GetAssemblies();
            foreach (UnityEditor.Compilation.Assembly asm in assemblies)
            {
                if (assembly.GetName().Name == asm.name)
                {
                    return(true);
                }
            }
#endif

            return(false);
        }
        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 !UNITY_2019_2_OR_NEWER
                if ((androidTargetArch & AndroidArchitecture.X86) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/x86", TargetCpu.X86_SSE2));
                }
#endif
            }
            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 clang >6 development issue (due to latest being 7.0.0) - IOS & newer PS4 SDKS are affected because its a source level IR compatability issue
                        if ((targetPlatform != TargetPlatform.iOS) && (targetPlatform != TargetPlatform.PS4))
                        {
                            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);
                }
            }
        }
Exemple #18
0
        public static void AddScriptCompilationData(BeeDriver beeDriver,
                                                    EditorCompilation editorCompilation,
                                                    ScriptAssembly[] assemblies,
                                                    bool debug,
                                                    string outputDirectory,
                                                    BuildTarget buildTarget,
                                                    bool buildingForEditor,
                                                    string[] extraScriptingDefines = null)
        {
            // Need to call AssemblyDataFrom before calling CompilationPipeline.GetScriptAssemblies,
            // as that acts on the same ScriptAssemblies, and modifies them with different build settings.
            var cachedAssemblies = AssemblyDataFrom(assemblies);

            AssemblyData[] codeGenAssemblies;
            using (new ProfilerMarker("GetScriptAssembliesForCodeGen").Auto())
            {
                codeGenAssemblies = buildingForEditor
                    ? null
                    : AssemblyDataFrom(CodeGenAssemblies(CompilationPipeline.GetScriptAssemblies(editorCompilation, AssembliesType.Editor, extraScriptingDefines)));
            }

            var movedFromExtractorPath = EditorApplication.applicationContentsPath + $"/Tools/ScriptUpdater/ApiUpdater.MovedFromExtractor.exe";
            var dotNetSdkRoslynPath    = EditorApplication.applicationContentsPath + $"/DotNetSdkRoslyn";

            var localization = "en-US";

            if (LocalizationDatabase.currentEditorLanguage != SystemLanguage.English && EditorPrefs.GetBool("Editor.kEnableCompilerMessagesLocalization", false))
            {
                localization = LocalizationDatabase.GetCulture(LocalizationDatabase.currentEditorLanguage);
            }


            var assembliesToScanForTypeDB = new HashSet <string>();
            var searchPaths = new HashSet <string>(BuildPlayerDataGenerator.GetStaticSearchPaths(buildTarget));
            var options     = EditorScriptCompilationOptions.BuildingIncludingTestAssemblies;

            if (buildingForEditor)
            {
                options |= EditorScriptCompilationOptions.BuildingForEditor;
            }
            foreach (var a in editorCompilation.GetAllScriptAssemblies(options, extraScriptingDefines))
            {
                if (!a.Flags.HasFlag(AssemblyFlags.EditorOnly))
                {
                    var path = a.FullPath.ToNPath();
                    assembliesToScanForTypeDB.Add(path.ToString());
                    searchPaths.Add(path.Parent.ToString());
                }
            }

            var precompileAssemblies = editorCompilation.PrecompiledAssemblyProvider.GetPrecompiledAssembliesDictionary(
                buildingForEditor,
                BuildPipeline.GetBuildTargetGroup(buildTarget),
                buildTarget,
                extraScriptingDefines);

            if (precompileAssemblies != null)
            {
                foreach (var a in precompileAssemblies)
                {
                    if (!a.Value.Flags.HasFlag(AssemblyFlags.EditorOnly))
                    {
                        var path = a.Value.Path.ToNPath();
                        assembliesToScanForTypeDB.Add(path.ToString());
                        searchPaths.Add(path.Parent.ToString());
                    }
                }
            }

            beeDriver.DataForBuildProgram.Add(new ScriptCompilationData
            {
                OutputDirectory        = outputDirectory,
                DotnetRuntimePath      = NetCoreProgram.DotNetRuntimePath.ToString(),
                DotnetRoslynPath       = dotNetSdkRoslynPath,
                MovedFromExtractorPath = movedFromExtractorPath,
                Assemblies             = cachedAssemblies,
                CodegenAssemblies      = codeGenAssemblies,
                Debug                           = debug,
                BuildTarget                     = buildTarget.ToString(),
                Localization                    = localization,
                EnableDiagnostics               = editorCompilation.EnableDiagnostics,
                BuildPlayerDataOutput           = $"Library/BuildPlayerData/{(buildingForEditor ? "Editor" : "Player")}",
                ExtractRuntimeInitializeOnLoads = !buildingForEditor,
                AssembliesToScanForTypeDB       = assembliesToScanForTypeDB.OrderBy(p => p).ToArray(),
                SearchPaths                     = searchPaths.OrderBy(p => p).ToArray()
            });
        }
Exemple #19
0
        static AssemblyDefintionState LoadAssemblyDefintionState(string path)
        {
            var asset = AssetDatabase.LoadAssetAtPath <AssemblyDefinitionAsset>(path);

            if (asset == null)
            {
                return(null);
            }

            var data = CustomScriptAssemblyData.FromJson(asset.text);

            if (data == null)
            {
                return(null);
            }

            var state = new AssemblyDefintionState();

            state.asset                 = asset;
            state.name                  = data.name;
            state.references            = new List <AssemblyDefinitionReference>();
            state.precompiledReferences = new List <PrecompiledReference>();
            state.defineConstraints     = new List <DefineConstraint>();
            state.autoReferenced        = ToMixedBool(data.autoReferenced);
            state.allowUnsafeCode       = ToMixedBool(data.allowUnsafeCode);
            state.overrideReferences    = ToMixedBool(data.overrideReferences);

            if (data.defineConstraints != null)
            {
                foreach (var defineConstaint in data.defineConstraints)
                {
                    try
                    {
                        var symbolName = defineConstaint.StartsWith(DefineConstraintsHelper.Not) ? defineConstaint.Substring(1) : defineConstaint;
                        if (!SymbolNameRestrictions.IsValid(symbolName))
                        {
                            throw new AssemblyDefinitionException($"Invalid define constraint {symbolName}", path);
                        }

                        state.defineConstraints.Add(new DefineConstraint
                        {
                            name         = defineConstaint,
                            displayValue = MixedBool.False,
                        });
                    }
                    catch (AssemblyDefinitionException e)
                    {
                        Debug.LogException(e, asset);
                        state.modified = true;
                    }
                }
            }

            if (data.references != null)
            {
                foreach (var reference in data.references)
                {
                    try
                    {
                        var assemblyDefinitionFile = new AssemblyDefinitionReference();
                        var referencePath          = Compilation.CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(reference);

                        if (string.IsNullOrEmpty(referencePath))
                        {
                            throw new AssemblyDefinitionException(string.Format("Could not find assembly reference '{0}'", reference), path);
                        }

                        assemblyDefinitionFile.asset = AssetDatabase.LoadAssetAtPath <AssemblyDefinitionAsset>(referencePath);

                        if (assemblyDefinitionFile.asset == null)
                        {
                            throw new AssemblyDefinitionException(string.Format("Reference assembly definition file '{0}' not found", referencePath), path);
                        }

                        assemblyDefinitionFile.data         = CustomScriptAssemblyData.FromJson(assemblyDefinitionFile.asset.text);
                        assemblyDefinitionFile.displayValue = MixedBool.False;
                        state.references.Add(assemblyDefinitionFile);
                    }
                    catch (AssemblyDefinitionException e)
                    {
                        UnityEngine.Debug.LogException(e, asset);
                        state.references.Add(new AssemblyDefinitionReference());
                        state.modified = true;
                    }
                }
            }

            var nameToPrecompiledReference = EditorCompilationInterface.Instance.GetAllPrecompiledAssemblies()
                                             .Where(x => (x.Flags & AssemblyFlags.UserAssembly) == AssemblyFlags.UserAssembly)
                                             .ToDictionary(x => AssetPath.GetFileName(x.Path), x => x);

            foreach (var precompiledReferenceName in data.precompiledReferences ?? Enumerable.Empty <String>())
            {
                try
                {
                    var precompiledReference = new PrecompiledReference();

                    var precompiledAssemblyPossibleReference = nameToPrecompiledReference.ContainsKey(precompiledReferenceName);
                    if (!precompiledAssemblyPossibleReference && !data.overrideReferences)
                    {
                        throw new AssemblyDefinitionException(string.Format("Referenced precompiled assembly '{0}' not found", precompiledReferenceName), path);
                    }

                    precompiledReference.precompiled  = nameToPrecompiledReference[precompiledReferenceName];
                    precompiledReference.displayValue = MixedBool.True;
                    state.precompiledReferences.Add(precompiledReference);
                }
                catch (AssemblyDefinitionException e)
                {
                    Debug.LogException(e, asset);
                    state.precompiledReferences.Add(new PrecompiledReference());
                    state.modified = true;
                }
            }

            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();

            state.platformCompatibility = new MixedBool[platforms.Length];

            var OptinalUnityAssemblies = CustomScriptAssembly.OptinalUnityAssemblies;

            state.optionalUnityReferences = new MixedBool[OptinalUnityAssemblies.Length];

            if (data.optionalUnityReferences != null)
            {
                for (int i = 0; i < OptinalUnityAssemblies.Length; i++)
                {
                    var optionalUnityReferences = OptinalUnityAssemblies[i].OptionalUnityReferences.ToString();
                    var any = data.optionalUnityReferences.Any(x => x == optionalUnityReferences);
                    if (any)
                    {
                        state.optionalUnityReferences[i] = MixedBool.True;
                    }
                }
            }

            state.compatibleWithAnyPlatform = MixedBool.True;
            string[] dataPlatforms = null;

            if (data.includePlatforms != null && data.includePlatforms.Length > 0)
            {
                state.compatibleWithAnyPlatform = MixedBool.False;
                dataPlatforms = data.includePlatforms;
            }
            else if (data.excludePlatforms != null && data.excludePlatforms.Length > 0)
            {
                state.compatibleWithAnyPlatform = MixedBool.True;
                dataPlatforms = data.excludePlatforms;
            }

            if (dataPlatforms != null)
            {
                foreach (var platform in dataPlatforms)
                {
                    var platformIndex = GetPlatformIndex(platforms, platform);
                    state.platformCompatibility[platformIndex] = MixedBool.True;
                }
            }

            return(state);
        }
        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());
                }
            }
        }
Exemple #21
0
        /// <returns>Returns a dictionary of type name inside MRTK DLLs mapped to additional data.</returns>
        private static Dictionary <string, AssemblyInformation> ProcessCompiledDLLs(string temporaryDirectoryName, string outputDirectory, Dictionary <string, string> asmDefMappings)
        {
            Assembly[] dlls = CompilationPipeline.GetAssemblies();

            string tmpDirPath = Path.Combine(Application.dataPath, temporaryDirectoryName);

            if (Directory.Exists(tmpDirPath))
            {
                Directory.Delete(tmpDirPath);
            }

            Directory.CreateDirectory(tmpDirPath);

            try
            {
                Utilities.EnsureCleanDirectory(outputDirectory);

                foreach (Assembly dll in dlls)
                {
                    if (dll.name.Contains("MixedReality"))
                    {
                        string dllPath = Utilities.GetFullPathFromAssetsRelative($"Assets/../MSBuild/Publish/InEditor/WindowsStandalone32/{dll.name}.dll");
                        File.Copy(dllPath, Path.Combine(tmpDirPath, $"{dll.name}.dll"), true);
                        File.Copy(dllPath, Path.Combine(outputDirectory, $"{dll.name}.dll"));
                        File.Copy(Path.ChangeExtension(dllPath, ".pdb"), Path.Combine(outputDirectory, $"{dll.name}.pdb"));
                    }
                }

                // Load these directories
                AssetDatabase.Refresh();

                Dictionary <string, AssemblyInformation> toReturn = new Dictionary <string, AssemblyInformation>();

                foreach (Assembly dll in dlls)
                {
                    if (dll.name.Contains("MixedReality"))
                    {
                        if (!asmDefMappings.TryGetValue($"{dll.name}.dll", out string newDllGuid))
                        {
                            throw new InvalidOperationException($"No guid based on .asmdef was generated for DLL '{dll.name}'.");
                        }

                        AssemblyInformation assemblyInformation = new AssemblyInformation(dll.name, newDllGuid);

                        Object[] assets = AssetDatabase.LoadAllAssetsAtPath(Path.Combine("Assets", temporaryDirectoryName, $"{dll.name}.dll"));

                        foreach (Object asset in assets)
                        {
                            MonoScript monoScript = asset as MonoScript;
                            if (!(monoScript is null) && AssetDatabase.TryGetGUIDAndLocalFileIdentifier(monoScript, out string guid, out long fileId))
                            {
                                Type type = monoScript.GetClass();

                                if (type == null)
                                {
                                    Debug.LogError($"Encountered a MonoScript we get a null Type from: '{monoScript.name}'");
                                }
                                // check for a namespace, MRTK or the DotNetAdapter namespace
                                else if ((type.Namespace == null) || (!type.Namespace.Contains("Microsoft.MixedReality.Toolkit") && !type.Namespace.Contains("Microsoft.Windows.MixedReality")))
                                {
                                    throw new InvalidDataException($"Type {type.Name} is not a member of an approved (typically, 'Microsoft.MixedReality.Toolkit') namespace");
                                }
                                else
                                {
                                    assemblyInformation.CompiledClasses.Add(type.FullName, new ClassInformation()
                                    {
                                        Name = type.Name, Namespace = type.Namespace, FileId = fileId, Guid = newDllGuid
                                    });
                                }
                            }
                        }

                        toReturn.Add(dll.name, assemblyInformation);
                    }
                }

                return(toReturn);
            }
            finally
            {
                Directory.Delete(tmpDirPath, true);
                AssetDatabase.Refresh();
            }
        }
Exemple #22
0
        static void OnCompilationFinished(string assemblyPath, CompilerMessage[] messages)
        {
            // Do nothing if there were compile errors on the target
            if (CompilerMessagesContainError(messages))
            {
                Debug.Log("Weaver: stop because compile errors on target");
                return;
            }

            // Should not run on the editor only assemblies
            if (assemblyPath.Contains("-Editor") || assemblyPath.Contains(".Editor"))
            {
                return;
            }

            // don't weave mirror files
            string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);

            if (assemblyName == MirrorRuntimeAssemblyName || assemblyName == MirrorWeaverAssemblyName)
            {
                return;
            }

            // find Mirror.dll
            string mirrorRuntimeDll = FindMirrorRuntime();

            if (string.IsNullOrEmpty(mirrorRuntimeDll))
            {
                Debug.LogError("Failed to find Mirror runtime assembly");
                return;
            }
            if (!File.Exists(mirrorRuntimeDll))
            {
                // this is normal, it happens with any assembly that is built before mirror
                // such as unity packages or your own assemblies
                // those don't need to be weaved
                // if any assembly depends on mirror, then it will be built after
                return;
            }

            // find UnityEngine.CoreModule.dll
            string unityEngineCoreModuleDLL = UnityEditorInternal.InternalEditorUtility.GetEngineCoreModuleAssemblyPath();

            if (string.IsNullOrEmpty(unityEngineCoreModuleDLL))
            {
                Debug.LogError("Failed to find UnityEngine assembly");
                return;
            }

            // build directory list for later asm/symbol resolving using CompilationPipeline refs
            HashSet <string> dependencyPaths = new HashSet <string>();

            dependencyPaths.Add(Path.GetDirectoryName(assemblyPath));
            foreach (UnityAssembly unityAsm in CompilationPipeline.GetAssemblies())
            {
                if (unityAsm.outputPath != assemblyPath)
                {
                    continue;
                }

                foreach (string unityAsmRef in unityAsm.compiledAssemblyReferences)
                {
                    dependencyPaths.Add(Path.GetDirectoryName(unityAsmRef));
                }
            }

            // passing null in the outputDirectory param will do an in-place update of the assembly
            if (Program.Process(unityEngineCoreModuleDLL, mirrorRuntimeDll, null, new[] { assemblyPath }, dependencyPaths.ToArray(), HandleWarning, HandleError))
            {
                WeaveFailed = false;
                //Debug.Log("Weaving succeeded for: " + assemblyPath);
            }
            else
            {
                WeaveFailed = true;
                if (UnityLogEnabled)
                {
                    Debug.LogError("Weaving failed for: " + assemblyPath);
                }
            }
        }
Exemple #23
0
 public string GetAssemblyNameFromScriptPath(string path)
 {
     return(CompilationPipeline.GetAssemblyNameFromScriptPath(path));
 }
        internal static IEnumerable <string> GetPrecompiledAssemblyPaths(PrecompiledAssemblyTypes flags)
        {
            var assemblyPaths = new List <string>();

#if UNITY_2019_1_OR_NEWER
            var precompiledAssemblySources = (CompilationPipeline.PrecompiledAssemblySources)flags;
            assemblyPaths.AddRange(CompilationPipeline.GetPrecompiledAssemblyPaths(precompiledAssemblySources));
#else
            if ((flags & PrecompiledAssemblyTypes.UnityEngine) != 0)
            {
                assemblyPaths.AddRange(Directory.GetFiles(Path.Combine(EditorApplication.applicationContentsPath,
                                                                       Path.Combine("Managed", "UnityEngine"))).Where(path => Path.GetExtension(path).Equals(".dll")));
            }
            if ((flags & PrecompiledAssemblyTypes.UnityEditor) != 0)
            {
                assemblyPaths.AddRange(Directory.GetFiles(Path.Combine(EditorApplication.applicationContentsPath,
                                                                       "Managed")).Where(path => Path.GetExtension(path).Equals(".dll")));
            }
            if ((flags & PrecompiledAssemblyTypes.UserAssembly) != 0)
            {
                assemblyPaths.AddRange(CompilationPipeline.GetPrecompiledAssemblyNames().Select(name => CompilationPipeline.GetPrecompiledAssemblyPathFromAssemblyName(name)));
            }
#endif

#if !UNITY_2019_2_OR_NEWER
            var extensions = new List <string>();
            if ((flags & PrecompiledAssemblyTypes.UnityEngine) != 0)
            {
                extensions.AddRange(new[]
                {
                    "UnityExtensions/Unity/Networking/UnityEngine.Networking.dll",
                    "UnityExtensions/Unity/Timeline/Runtime/UnityEngine.Timeline.dll",
                    "UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll",
                });
            }
            if ((flags & PrecompiledAssemblyTypes.UnityEditor) != 0)
            {
                extensions.AddRange(new[]
                {
                    "UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll",
                    "UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll",
                    "UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll",
                });
            }
            assemblyPaths.AddRange(extensions.Select(ext => Path.Combine(EditorApplication.applicationContentsPath, ext)));
#endif
            return(assemblyPaths.Select(path => path.Replace("\\", "/")));
        }
Exemple #25
0
        private void DrawOptions(DllManipulatorOptions options)
        {
            var guiEnabledStack = new Stack <bool>();

            guiEnabledStack.Push(GUI.enabled);
            if (EditorApplication.isPlaying)
            {
                GUI.enabled = false;
            }
            options.mockAllNativeFunctions = EditorGUILayout.Toggle(TARGET_ALL_NATIVE_FUNCTIONS_GUI_CONTENT, options.mockAllNativeFunctions);

            if (EditorGUILayout.Toggle(TARGET_ONLY_EXECUTING_ASSEMBLY_GUI_CONTENT, options.assemblyPaths.Length == 0))
            {
                options.assemblyPaths = new string[0];
            }
            else
            {
                var prevIndent1 = EditorGUI.indentLevel;
                EditorGUI.indentLevel++;

                if (_allKnownAssemblies == null || _lastKnownAssembliesRefreshTime + ASSEMBLIES_REFRESH_INTERVAL < DateTime.Now)
                {
                    var playerCompiledAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player)
                                                   .Select(a => PathUtils.NormallizeUnityAssemblyPath(a.outputPath));

                    var editorCompiledAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Editor)
                                                   .Select(a => PathUtils.NormallizeUnityAssemblyPath(a.outputPath));

                    var assemblyAssets = Resources.FindObjectsOfTypeAll <PluginImporter>()
                                         .Where(p => !p.isNativePlugin)
                                         .Select(p => PathUtils.NormallizeUnityAssemblyPath(p.assetPath));

                    string[] defaultAssemblyPrefixes = { "UnityEngine.", "UnityEditor.", "Unity.", "com.unity.", "Mono.", "nunit." };

                    _allKnownAssemblies = playerCompiledAssemblies
                                          .Concat(assemblyAssets)
                                          .Concat(editorCompiledAssemblies)
                                          .OrderBy(path => Array.FindIndex(defaultAssemblyPrefixes, p => path.Substring(path.LastIndexOf('/') + 1).StartsWith(p)))
                                          .ToArray();
                    _lastKnownAssembliesRefreshTime = DateTime.Now;
                }

                if (options.assemblyPaths.Length == 0)
                {
                    var first = GetFirstAssemblyToList(_allKnownAssemblies);
                    if (first != null)
                    {
                        options.assemblyPaths = new[] { first }
                    }
                    ;
                }

                _showTargetAssemblies = EditorGUILayout.Foldout(_showTargetAssemblies, TARGET_ASSEMBLIES_GUI_CONTENT);
                if (_showTargetAssemblies)
                {
                    var prevIndent2 = EditorGUI.indentLevel;
                    EditorGUI.indentLevel++;

                    var selectedAssemblies    = options.assemblyPaths.Where(p => _allKnownAssemblies.Any(a => PathUtils.DllPathsEqual(a, p))).ToList();
                    var notSelectedAssemblies = _allKnownAssemblies.Except(selectedAssemblies).ToArray();
                    DrawList(selectedAssemblies, i =>
                    {
                        var values = new[] { selectedAssemblies[i] }
                        .Concat(notSelectedAssemblies)
                        .Select(a => a.Substring(a.LastIndexOf('/') + 1))
                        .ToArray();

                        var selectedIndex = EditorGUILayout.Popup(0, values);
                        return(selectedIndex == 0 ? selectedAssemblies[i] : notSelectedAssemblies[selectedIndex - 1]);
                    }, notSelectedAssemblies.Length > 0, () => notSelectedAssemblies[0]);
                    options.assemblyPaths = selectedAssemblies.ToArray();

                    EditorGUI.indentLevel = prevIndent2;
                }

                EditorGUI.indentLevel = prevIndent1;
            }

            options.onlyInEditor = EditorGUILayout.Toggle(ONLY_IN_EDITOR, options.onlyInEditor);

            options.dllPathPattern = EditorGUILayout.TextField(DLL_PATH_PATTERN_GUI_CONTENT, options.dllPathPattern);

            options.loadingMode = (DllLoadingMode)EditorGUILayout.EnumPopup(DLL_LOADING_MODE_GUI_CONTENT, options.loadingMode);

#if UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX
            options.posixDlopenFlags = (PosixDlopenFlags)EditorGUILayout.EnumPopup(POSIX_DLOPEN_FLAGS_GUI_CONTENT, options.posixDlopenFlags);
#endif

            guiEnabledStack.Push(GUI.enabled);
            if (options.loadingMode != DllLoadingMode.Preload)
            {
                options.threadSafe = false;
                GUI.enabled        = false;
            }
            options.threadSafe = EditorGUILayout.Toggle(THREAD_SAFE_GUI_CONTENT, options.threadSafe);
            GUI.enabled        = guiEnabledStack.Pop();

            options.enableCrashLogs = EditorGUILayout.Toggle(CRASH_LOGS_GUI_CONTENT, options.enableCrashLogs);

            if (options.enableCrashLogs)
            {
                var prevIndent = EditorGUI.indentLevel;
                EditorGUI.indentLevel += 1;

                options.crashLogsDir = EditorGUILayout.TextField(CRASH_LOGS_DIR_GUI_CONTENT, options.crashLogsDir);

                options.crashLogsStackTrace = EditorGUILayout.Toggle(CRASH_LOGS_STACK_TRACE_GUI_CONTENT, options.crashLogsStackTrace);

                EditorGUI.indentLevel = prevIndent;
            }

            GUI.enabled = guiEnabledStack.Pop();
        }
        public override void OnInspectorGUI()
        {
            if (initializeException != null)
            {
                ShowLoadErrorExceptionGUI(initializeException);
                ApplyRevertGUI();
                return;
            }

            extraDataSerializedObject.Update();

            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();

            using (new EditorGUI.DisabledScope(false))
            {
                if (targets.Length > 1)
                {
                    using (new EditorGUI.DisabledScope(true))
                    {
                        var value = string.Join(", ", extraDataTargets.Select(t => t.name).ToArray());
                        EditorGUILayout.TextField(Styles.name, value, EditorStyles.textField);
                    }
                }
                else
                {
                    EditorGUILayout.PropertyField(m_AssemblyName, Styles.name);
                }

                GUILayout.Label(Styles.generalOptions, EditorStyles.boldLabel);
                EditorGUILayout.BeginVertical(GUI.skin.box);
                EditorGUILayout.PropertyField(m_AllowUnsafeCode, Styles.allowUnsafeCode);
                EditorGUILayout.PropertyField(m_AutoReferenced, Styles.autoReferenced);
                EditorGUILayout.PropertyField(m_NoEngineReferences, Styles.noEngineReferences);
                EditorGUILayout.PropertyField(m_OverrideReferences, Styles.overrideReferences);
                EditorGUILayout.PropertyField(m_RootNamespace, Styles.rootNamespace);

                EditorGUILayout.EndVertical();
                GUILayout.Space(10f);

                EditorGUILayout.BeginHorizontal();
                GUILayout.Label(Styles.defineConstraints, EditorStyles.boldLabel);
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();

                if (m_DefineConstraints.serializedProperty.arraySize > 0)
                {
                    var defineConstraintsCompatible = true;

                    var defines = CompilationPipeline.GetDefinesFromAssemblyName(m_AssemblyName.stringValue);

                    if (defines != null)
                    {
                        for (var i = 0; i < m_DefineConstraints.serializedProperty.arraySize && defineConstraintsCompatible; ++i)
                        {
                            var defineConstraint = m_DefineConstraints.serializedProperty.GetArrayElementAtIndex(i).FindPropertyRelative("name").stringValue;

                            if (DefineConstraintsHelper.GetDefineConstraintCompatibility(defines, defineConstraint) != DefineConstraintsHelper.DefineConstraintStatus.Compatible)
                            {
                                defineConstraintsCompatible = false;
                            }
                        }

                        var constraintValidityRect = new Rect(GUILayoutUtility.GetLastRect());
                        constraintValidityRect.x += constraintValidityRect.width - 23;
                        var image   = defineConstraintsCompatible ? Styles.validDefineConstraint : Styles.invalidDefineConstraint;
                        var tooltip = Styles.GetTitleTooltipFromDefineConstraintCompatibility(defineConstraintsCompatible);
                        var content = new GUIContent(image, tooltip);

                        constraintValidityRect.width  = Styles.kValidityIconWidth;
                        constraintValidityRect.height = Styles.kValidityIconHeight;
                        EditorGUI.LabelField(constraintValidityRect, content);
                    }
                }

                m_DefineConstraints.DoLayoutList();

                GUILayout.Label(Styles.references, EditorStyles.boldLabel);

                EditorGUILayout.BeginVertical(GUI.skin.box);
                EditorGUILayout.PropertyField(m_UseGUIDs, Styles.useGUIDs);
                EditorGUILayout.EndVertical();

                m_ReferencesList.DoLayoutList();

                if (extraDataTargets.Any(data => ((AssemblyDefinitionState)data).references != null && ((AssemblyDefinitionState)data).references.Any(x => x.asset == null)))
                {
                    EditorGUILayout.HelpBox("The grayed out assembly references are missing and will not be referenced during compilation.", MessageType.Info);
                }

                if (m_OverrideReferences.boolValue && !m_OverrideReferences.hasMultipleDifferentValues)
                {
                    GUILayout.Label(Styles.precompiledReferences, EditorStyles.boldLabel);

                    UpdatePrecompiledReferenceListEntry();
                    m_PrecompiledReferencesList.DoLayoutList();

                    if (extraDataTargets.Any(data => ((AssemblyDefinitionState)data).precompiledReferences.Any(x => string.IsNullOrEmpty(x.path) && !string.IsNullOrEmpty(x.name))))
                    {
                        EditorGUILayout.HelpBox("The grayed out assembly references are missing and will not be referenced during compilation.", MessageType.Info);
                    }
                }

                GUILayout.Label(Styles.platforms, EditorStyles.boldLabel);
                EditorGUILayout.BeginVertical(GUI.skin.box);

                using (var change = new EditorGUI.ChangeCheckScope())
                {
                    EditorGUILayout.PropertyField(m_CompatibleWithAnyPlatform, Styles.anyPlatform);
                    if (change.changed)
                    {
                        // Invert state include/exclude compatibility of states that have the opposite compatibility,
                        // so all states are either include or exclude.
                        var compatibleWithAny = m_CompatibleWithAnyPlatform.boolValue;
                        var needToSwap        = extraDataTargets.Cast <AssemblyDefinitionState>().Where(p => p.compatibleWithAnyPlatform != compatibleWithAny).ToList();
                        extraDataSerializedObject.ApplyModifiedProperties();
                        foreach (var state in needToSwap)
                        {
                            InversePlatformCompatibility(state);
                        }

                        extraDataSerializedObject.Update();
                    }
                }

                if (!m_CompatibleWithAnyPlatform.hasMultipleDifferentValues)
                {
                    GUILayout.Label(m_CompatibleWithAnyPlatform.boolValue ? Styles.excludePlatforms : Styles.includePlatforms, EditorStyles.boldLabel);

                    for (int i = 0; i < platforms.Length; ++i)
                    {
                        SerializedProperty property;
                        if (i >= m_PlatformCompatibility.arraySize)
                        {
                            m_PlatformCompatibility.arraySize++;
                            property           = m_PlatformCompatibility.GetArrayElementAtIndex(i);
                            property.boolValue = false;
                        }
                        else
                        {
                            property = m_PlatformCompatibility.GetArrayElementAtIndex(i);
                        }

                        EditorGUILayout.PropertyField(property, new GUIContent(platforms[i].DisplayName));
                    }

                    EditorGUILayout.Space();

                    GUILayout.BeginHorizontal();

                    if (GUILayout.Button(Styles.selectAll))
                    {
                        var prop = m_PlatformCompatibility.GetArrayElementAtIndex(0);
                        var end  = m_PlatformCompatibility.GetEndProperty();
                        do
                        {
                            prop.boolValue = true;
                        }while (prop.Next(false) && !SerializedProperty.EqualContents(prop, end));
                    }

                    if (GUILayout.Button(Styles.deselectAll))
                    {
                        var prop = m_PlatformCompatibility.GetArrayElementAtIndex(0);
                        var end  = m_PlatformCompatibility.GetEndProperty();
                        do
                        {
                            prop.boolValue = false;
                        }while (prop.Next(false) && !SerializedProperty.EqualContents(prop, end));
                    }

                    GUILayout.FlexibleSpace();
                    GUILayout.EndHorizontal();
                }

                EditorGUILayout.EndVertical();
                GUILayout.Space(10f);

                EditorGUILayout.BeginVertical(GUI.skin.box);
                GUILayout.Label(Styles.versionDefines, EditorStyles.boldLabel);
                m_VersionDefineList.DoLayoutList();
                EditorGUILayout.EndVertical();
            }

            extraDataSerializedObject.ApplyModifiedProperties();

            ApplyRevertGUI();
        }
Exemple #27
0
        private static void OnCompilationFinished(string assemblyPath, CompilerMessage[] messages)
        {
            var sw = Stopwatch.StartNew();

            if (Array.FindIndex(messages, IsErrorMessage) != -1)
            {
                return;
            }

            var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);

            if (assemblyName == null || assemblyName == UniMobRuntimeAssemblyName)
            {
                return;
            }

            //if (assemblyName == UniMobEditorAssemblyName)
            //{
            //    // should we reload scripts when Weaver changed?
            //    // it allow package update but assemblies will reload twice
            //    // on project startup
            //    SessionState.SetBool(UniMobWeavedFlagName, false);
            //    return;
            //}

            if (assemblyPath.Contains("-Editor") || assemblyPath.Contains(".Editor"))
            {
                return;
            }

            var assemblies = CompilationPipeline.GetAssemblies();

            var uniMobRuntime = FindUniMobRuntime(assemblies);

            if (uniMobRuntime == null)
            {
                Debug.LogError("Failed to find UniMob runtime assembly");
                return;
            }

            if (!File.Exists(uniMobRuntime.outputPath))
            {
                return;
            }

            var dependencyPaths = new HashSet <string>
            {
                Path.GetDirectoryName(assemblyPath)
            };

            var shouldWeave = false;

            for (var asmIndex = 0; asmIndex < assemblies.Length; asmIndex++)
            {
                var assembly = assemblies[asmIndex];
                if (assembly.outputPath != assemblyPath)
                {
                    continue;
                }

                for (var i = 0; i < assembly.compiledAssemblyReferences.Length; i++)
                {
                    var referencePath = assembly.compiledAssemblyReferences[i];
                    dependencyPaths.Add(Path.GetDirectoryName(referencePath));
                }

                for (var i = 0; i < assembly.assemblyReferences.Length; i++)
                {
                    var reference = assembly.assemblyReferences[i];
                    if (reference.outputPath == uniMobRuntime.outputPath)
                    {
                        shouldWeave = true;
                    }
                }

                break;
            }

            if (!shouldWeave)
            {
                return;
            }

            Weave(assemblyPath, dependencyPaths);

#if UNIMOB_WEAVER_LOGGING_ENABLED
            Debug.Log($"Weaved {assemblyPath} in {sw.ElapsedMilliseconds}ms");
#endif
        }
        static void LoadAssemblyDefinitionState(AssemblyDefinitionState state, string path)
        {
            var asset = AssetDatabase.LoadAssetAtPath <AssemblyDefinitionAsset>(path);

            if (asset == null)
            {
                return;
            }

            var data = CustomScriptAssemblyData.FromJsonNoFieldValidation(asset.text);

            if (data == null)
            {
                return;
            }

            try
            {
                data.ValidateFields();
            }
            catch (Exception e)
            {
                Debug.LogException(e, asset);
            }

            state.asset                 = asset;
            state.assemblyName          = data.name;
            state.rootNamespace         = data.rootNamespace;
            state.references            = new List <AssemblyDefinitionReference>();
            state.precompiledReferences = new List <PrecompiledReference>();
            state.defineConstraints     = new List <DefineConstraint>();
            state.versionDefines        = new List <VersionDefine>();
            state.autoReferenced        = data.autoReferenced;
            state.allowUnsafeCode       = data.allowUnsafeCode;
            state.overrideReferences    = data.overrideReferences;
            state.noEngineReferences    = data.noEngineReferences;

            // If the .asmdef has no references (true for newly created .asmdef), then use GUIDs.
            // Otherwise do not use GUIDs. This value might be changed below if any reference is a GUID.
            state.useGUIDs = (data.references == null || data.references.Length == 0);

            if (data.versionDefines != null)
            {
                foreach (var versionDefine in data.versionDefines)
                {
                    state.versionDefines.Add(versionDefine);
                }
            }

            if (data.defineConstraints != null)
            {
                foreach (var defineConstraint in data.defineConstraints)
                {
                    state.defineConstraints.Add(new DefineConstraint
                    {
                        name = defineConstraint,
                    });
                }
            }

            if (data.references != null)
            {
                foreach (var reference in data.references)
                {
                    try
                    {
                        var assemblyDefinitionFile = new AssemblyDefinitionReference
                        {
                            name = reference,
                            serializedReference = reference
                        };

                        // If any references is a GUID, use GUIDs.
                        var isGuid = CompilationPipeline.GetAssemblyDefinitionReferenceType(reference) == AssemblyDefinitionReferenceType.Guid;
                        if (isGuid)
                        {
                            state.useGUIDs = true;
                        }

                        assemblyDefinitionFile.Load(reference, isGuid);
                        state.references.Add(assemblyDefinitionFile);
                    }
                    catch (AssemblyDefinitionException e)
                    {
                        Debug.LogException(e, asset);
                        state.references.Add(new AssemblyDefinitionReference());
                    }
                }
            }

            var nameToPrecompiledReference = EditorCompilationInterface.Instance.PrecompiledAssemblyProvider
                                             .GetPrecompiledAssemblies(true, EditorUserBuildSettings.activeBuildTargetGroup, EditorUserBuildSettings.activeBuildTarget)
                                             .Where(x => (x.Flags & AssemblyFlags.UserAssembly) == AssemblyFlags.UserAssembly)
                                             .Distinct()
                                             .ToDictionary(x => AssetPath.GetFileName(x.Path), x => x);

            foreach (var precompiledReferenceName in data.precompiledReferences ?? Enumerable.Empty <String>())
            {
                try
                {
                    var precompiledReference = new PrecompiledReference
                    {
                        name = precompiledReferenceName,
                    };

                    PrecompiledAssembly assembly;
                    if (nameToPrecompiledReference.TryGetValue(precompiledReferenceName, out assembly))
                    {
                        precompiledReference.path     = assembly.Path;
                        precompiledReference.fileName = AssetPath.GetFileName(assembly.Path);
                    }

                    state.precompiledReferences.Add(precompiledReference);
                }
                catch (AssemblyDefinitionException e)
                {
                    Debug.LogException(e, asset);
                    state.precompiledReferences.Add(new PrecompiledReference());
                }
            }

            var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms();

            state.platformCompatibility = new bool[platforms.Length];

            state.compatibleWithAnyPlatform = true;
            string[] dataPlatforms = null;

            if (data.includePlatforms != null && data.includePlatforms.Length > 0)
            {
                state.compatibleWithAnyPlatform = false;
                dataPlatforms = data.includePlatforms;
            }
            else if (data.excludePlatforms != null && data.excludePlatforms.Length > 0)
            {
                state.compatibleWithAnyPlatform = true;
                dataPlatforms = data.excludePlatforms;
            }

            if (dataPlatforms != null)
            {
                foreach (var platform in dataPlatforms)
                {
                    var platformIndex = GetPlatformIndex(platforms, platform);
                    state.platformCompatibility[platformIndex] = true;
                }
            }
        }
 public IEnumerable <UnityEditor.Compilation.Assembly> GetAssemblies()
 {
     return(CompilationPipeline.
            GetAssemblies(AssembliesType.Editor).Where(WillProcess));
 }
Exemple #30
0
        /// <returns>Returns a dictionary of type name inside MRTK DLLs mapped to additional data.</returns>
        private static Dictionary <string, ClassInformation> ProcessCompiledDLLs(string temporaryDirectoryName, string outputDirectory, Dictionary <string, string> asmDefMappings)
        {
            Assembly[] dlls = CompilationPipeline.GetAssemblies();

            string tmpDirPath = Path.Combine(Application.dataPath, temporaryDirectoryName);

            if (Directory.Exists(tmpDirPath))
            {
                Directory.Delete(tmpDirPath);
            }

            Directory.CreateDirectory(tmpDirPath);

            try
            {
                foreach (Assembly dll in dlls)
                {
                    if (dll.name.Contains("MixedReality"))
                    {
                        File.Copy(dll.outputPath, Path.Combine(tmpDirPath, $"{dll.name}.dll"), true);
                    }
                }

                // Load these directories
                AssetDatabase.Refresh();

                Dictionary <string, ClassInformation> toReturn = new Dictionary <string, ClassInformation>();

                if (Directory.Exists(outputDirectory))
                {
                    Directory.Delete(outputDirectory, true);
                }

                Directory.CreateDirectory(outputDirectory);
                foreach (Assembly dll in dlls)
                {
                    if (dll.name.Contains("MixedReality"))
                    {
                        if (!asmDefMappings.TryGetValue($"{dll.name}.dll", out string newDllGuid))
                        {
                            throw new InvalidOperationException($"No guid based on .asmdef was generated for DLL '{dll.name}'.");
                        }

                        File.Copy(Path.Combine(tmpDirPath, $"{dll.name}.dll"), Path.Combine(outputDirectory, $"{dll.name}.dll"));
                        File.Copy(Path.Combine(tmpDirPath, $"{dll.name}.dll.meta"), Path.Combine(outputDirectory, $"{dll.name}.dll.meta"));

                        Object[] assets = AssetDatabase.LoadAllAssetsAtPath(Path.Combine("Assets", temporaryDirectoryName, $"{dll.name}.dll"));

                        foreach (Object asset in assets)
                        {
                            MonoScript monoScript = asset as MonoScript;
                            if (!(monoScript is null) && AssetDatabase.TryGetGUIDAndLocalFileIdentifier(monoScript, out string guid, out long fileId))
                            {
                                Type type = monoScript.GetClass();

                                if (type.Namespace == null || !type.Namespace.Contains("Microsoft.MixedReality.Toolkit"))
                                {
                                    throw new InvalidDataException($"Type {type.Name} is not a member of the Microsoft.MixedReality.Toolkit namespace");
                                }
                                toReturn.Add(type.FullName, new ClassInformation()
                                {
                                    Name = type.Name, Namespace = type.Namespace, FileId = fileId, Guid = newDllGuid
                                });
                            }
                        }
                    }
                }

                return(toReturn);
            }
            finally
            {
                Directory.Delete(tmpDirPath, true);
                AssetDatabase.Refresh();
            }
        }