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()); } } }
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)); }
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))); }
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); }
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(); }
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); }
/// <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); } } }
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() }); }
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()); } } }
/// <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(); } }
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); } } }
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("\\", "/"))); }
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(); }
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)); }
/// <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(); } }