/// <summary> /// Parses an asmdef file creating a new instance of <see cref="AssemblyDefinitionInfo"/>. /// </summary> /// <param name="file">The file representing asmdef.</param> /// <param name="unityProjectInfo">Instance of <see cref="UnityProjectInfo"/>,</param> /// <param name="assembly">The Unity assembly reference.</param> /// <param name="isBuiltInPackage">True whether this asmdef lives in the editor installation folder.</param> /// <returns></returns> public static AssemblyDefinitionInfo Parse(FileInfo file, UnityProjectInfo unityProjectInfo, Assembly assembly, bool isBuiltInPackage = false) { if (file.Extension != ".asmdef") { throw new ArgumentException($"Given file '{file.FullName}' is not an assembly definition file."); } else if (!file.Exists) { throw new ArgumentException($"Given file '{file.FullName}' does not exist."); } AssemblyDefinitionInfo toReturn = JsonUtility.FromJson <AssemblyDefinitionInfo>(File.ReadAllText(file.FullName)); if (!Utilities.TryGetGuidForAsset(file, out Guid guid)) { Debug.LogError($"Failed to parse AsmDef meta for asm def: '{file.FullName}', didn't find guid."); } toReturn.assembly = assembly; toReturn.Directory = file.Directory; toReturn.file = file; toReturn.Guid = guid; toReturn.BuiltInPackage = isBuiltInPackage; toReturn.Validate(unityProjectInfo.AvailablePlatforms); toReturn.PrecompiledAssemblyReferences = new HashSet <string>(toReturn.precompiledReferences?.Select(t => t.Replace(".dll", string.Empty)) ?? Array.Empty <string>()); return(toReturn); }
/// <summary> /// Exports the project given a template. /// </summary> /// <param name="projectFileTemplateText">The template of the csproj file.</param> /// <param name="projectFilesPath">The output folder where all the props were added.</param> internal void ExportProject(string projectFileTemplateText, string projectFilesPath) { if (File.Exists(ReferencePath.AbsolutePath)) { File.Delete(ReferencePath.AbsolutePath); } if (Utilities.TryGetXMLTemplate(projectFileTemplateText, "PROJECT_REFERENCE_SET", out string projectReferenceSetTemplate) && Utilities.TryGetXMLTemplate(projectFileTemplateText, "SOURCE_INCLUDE", out string sourceIncludeTemplate) && Utilities.TryGetXMLTemplate(projectFileTemplateText, "SUPPORTED_PLATFORM_BUILD_CONDITION", out string suportedPlatformBuildConditionTemplate)) { List <string> sourceIncludes = new List <string>(); Dictionary <Guid, string> sourceGuidToClassName = new Dictionary <Guid, string>(); foreach (SourceFileInfo source in AssemblyDefinitionInfo.GetSources()) { ProcessSourceFile(source, sourceIncludeTemplate, sourceIncludes, sourceGuidToClassName); } File.WriteAllLines(Path.Combine(projectFilesPath, $"{Guid.ToString()}.csmap"), sourceGuidToClassName.Select(t => $"{t.Key.ToString("N")}:{t.Value}")); List <string> supportedPlatformBuildConditions = new List <string>(); PopulateSupportedPlatformBuildConditions(supportedPlatformBuildConditions, suportedPlatformBuildConditionTemplate, "InEditor", InEditorPlatforms); PopulateSupportedPlatformBuildConditions(supportedPlatformBuildConditions, suportedPlatformBuildConditionTemplate, "Player", PlayerPlatforms); HashSet <string> inEditorSearchPaths = new HashSet <string>(), playerSearchPaths = new HashSet <string>(); string projectReferences = string.Join("\r\n", CreateProjectReferencesSet(projectReferenceSetTemplate, inEditorSearchPaths, true), CreateProjectReferencesSet(projectReferenceSetTemplate, playerSearchPaths, false)); Dictionary <string, string> tokens = new Dictionary <string, string>() { { "<!--PROJECT_GUID_TOKEN-->", Guid.ToString() }, { "<!--ALLOW_UNSAFE_TOKEN-->", AssemblyDefinitionInfo.allowUnsafeCode.ToString() }, { "<!--LANGUAGE_VERSION_TOKEN-->", MSBuildTools.CSharpVersion }, { "<!--DEVELOPMENT_BUILD_TOKEN-->", "false" }, // Default to false { "<!--IS_EDITOR_ONLY_TARGET_TOKEN-->", (ProjectType == ProjectType.EditorAsmDef || ProjectType == ProjectType.PredefinedEditorAssembly).ToString() }, { "<!--UNITY_EDITOR_INSTALL_FOLDER-->", Path.GetDirectoryName(EditorApplication.applicationPath) + "\\" }, { "<!--DEFAULT_PLATFORM_TOKEN-->", UnityProjectInfo.AvailablePlatforms.First(t => t.BuildTarget == BuildTarget.StandaloneWindows).Name }, { "<!--SUPPORTED_PLATFORMS_TOKEN-->", string.Join(";", UnityProjectInfo.AvailablePlatforms.Select(t => t.Name)) }, { "<!--INEDITOR_ASSEMBLY_SEARCH_PATHS_TOKEN-->", string.Join(";", inEditorSearchPaths) }, { "<!--PLAYER_ASSEMBLY_SEARCH_PATHS_TOKEN-->", string.Join(";", playerSearchPaths) }, { "##PLATFORM_PROPS_FOLDER_PATH_TOKEN##", projectFilesPath }, { projectReferenceSetTemplate, projectReferences }, { sourceIncludeTemplate, string.Join("\r\n", sourceIncludes) }, { suportedPlatformBuildConditionTemplate, string.Join("\r\n", supportedPlatformBuildConditions) } }; projectFileTemplateText = Utilities.ReplaceTokens(projectFileTemplateText, tokens, true); } else { Debug.LogError("Failed to find ProjectReferenceSet and/or Source_Include templates in the project template file."); } File.WriteAllText(ReferencePath.AbsolutePath, projectFileTemplateText); }
/// <summary> /// Creates an instance of <see cref="AssemblyDefinitionInfo"/> for the default projects (such as Assembly-CSharp) /// </summary> /// <param name="assembly">The Unity assembly reference.</param> /// <returns>A new instance.</returns> public static AssemblyDefinitionInfo GetDefaultAssemblyCSharpInfo(Assembly assembly) { AssemblyDefinitionInfo toReturn = new AssemblyDefinitionInfo() { IsDefaultAssembly = true, Guid = Guid.NewGuid(), Directory = new DirectoryInfo(Utilities.AssetPath) }; toReturn.assembly = assembly; toReturn.name = assembly.name; toReturn.references = assembly.assemblyReferences.Select(t => t.name).ToArray(); toReturn.PrecompiledAssemblyReferences = new HashSet <string>(); return(toReturn); }
/// <summary> /// Creates a new instance of the CSProject info. /// </summary> /// <param name="unityProjectInfo">Instance of parsed unity project info.</param> /// <param name="guid">The unique Guid of this reference item.</param> /// <param name="assemblyDefinitionInfo">The associated Assembly-Definition info.</param> /// <param name="assembly">The Unity assembly object associated with this csproj.</param> /// <param name="baseOutputPath">The output path where everything will be outputted.</param> internal CSProjectInfo(UnityProjectInfo unityProjectInfo, AssemblyDefinitionInfo assemblyDefinitionInfo, string baseOutputPath) : base(unityProjectInfo, assemblyDefinitionInfo.Guid, new Uri(Path.Combine(baseOutputPath, $"{assemblyDefinitionInfo.Name}.csproj")), assemblyDefinitionInfo.Name) { AssemblyDefinitionInfo = assemblyDefinitionInfo; ProjectType = GetProjectType(assemblyDefinitionInfo); InEditorPlatforms = GetCompilationPlatforms(true); PlayerPlatforms = GetCompilationPlatforms(false); if (InEditorPlatforms.Count == 0 && PlayerPlatforms.Count == 0) { Debug.LogError($"The assembly project '{Name}' doesn't contain any supported in-editor or player platform targets."); } ProjectDependencies = new ReadOnlyCollection <CSProjectDependency <CSProjectInfo> >(csProjectDependencies); }
private ProjectType GetProjectType(AssemblyDefinitionInfo assemblyDefinitionInfo, Assembly assembly) { if (assemblyDefinitionInfo != null) { return(assemblyDefinitionInfo.EditorPlatformSupported && !assemblyDefinitionInfo.NonEditorPlatformSupported ? ProjectType.EditorAsmDef : ProjectType.AsmDef); } switch (assembly.name) { case "Assembly-CSharp": case "Assembly-CSharp-firstpass": return(ProjectType.PredefinedAssembly); case "Assembly-CSharp-editor": case "Assembly-CSharp-firstpass-editor": return(ProjectType.PredefinedEditorAssembly); default: throw new InvalidOperationException($"Predefined assembly '{assembly.name}' was not recognized, this generally means it should be added to the switch statement in CSProjectInfo:GetProjectType. Treating is as a PredefinedAssembly instead of PredefinedEditorAssembly."); } }
/// <summary> /// Creates a new instance of the CSProject info. /// </summary> /// <param name="availablePlatforms">A list of platforms available to MSBuild.</param> /// <param name="guid">The unique Guid of this reference item.</param> /// <param name="assemblyDefinitionInfo">The associated Assembly-Definition info.</param> /// <param name="assembly">The Unity assembly object associated with this csproj.</param> /// <param name="baseOutputPath">The output path where everything will be outputted.</param> internal CSProjectInfo(IEnumerable <CompilationPlatformInfo> availablePlatforms, Guid guid, AssemblyDefinitionInfo assemblyDefinitionInfo, Assembly assembly, string baseOutputPath) : base(availablePlatforms, guid, new Uri(Path.Combine(baseOutputPath, $"{assembly.name}.csproj")), assembly.name) { if (Name.Contains("Timeline")) { Debug.Log("Here"); } AssemblyDefinitionInfo = assemblyDefinitionInfo; Assembly = assembly; ProjectType = GetProjectType(assemblyDefinitionInfo, assembly); InEditorPlatforms = GetCompilationPlatforms(true); PlayerPlatforms = GetCompilationPlatforms(false); if (InEditorPlatforms.Count == 0 && PlayerPlatforms.Count == 0) { Debug.LogError($"The assembly project '{Name}' doesn't contain any supported in-editor or player platform targets."); } ProjectDependencies = new ReadOnlyCollection <CSProjectDependency <CSProjectInfo> >(csProjectDependencies); }
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 UnityProjectInfo(IEnumerable <CompilationPlatformInfo> availablePlatforms, string projectOutputPath) { this.availablePlatforms = availablePlatforms; Dictionary <string, Assembly> unityAssemblies = CompilationPipeline.GetAssemblies().ToDictionary(t => t.name); Dictionary <string, CSProjectInfo> csProjects = new Dictionary <string, CSProjectInfo>(); CSProjects = new ReadOnlyDictionary <string, CSProjectInfo>(csProjects); foreach (KeyValuePair <string, Assembly> pair in unityAssemblies) { CSProjectInfo toAdd; string asmDefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(pair.Key); if (string.IsNullOrEmpty(asmDefPath)) { if (!pair.Key.StartsWith("Assembly-CSharp")) { Debug.LogError($"Failed to retrieve AsmDef for script assembly: {pair.Key}"); } toAdd = new CSProjectInfo(availablePlatforms, Guid.NewGuid(), null, pair.Value, projectOutputPath); } else { string guid = AssetDatabase.AssetPathToGUID(asmDefPath); if (!Guid.TryParse(guid, out Guid guidResult)) { Debug.LogError($"Failed to get GUID of the AsmDef at '{asmDefPath}' for assembly: {pair.Key}"); } else { guidResult = Guid.NewGuid(); } AssemblyDefinitionAsset assemblyDefinitionAsset = AssetDatabase.LoadAssetAtPath <AssemblyDefinitionAsset>(asmDefPath); AssemblyDefinitionInfo assemblyDefinitionInfo = assemblyDefinitionAsset == null ? null : JsonUtility.FromJson <AssemblyDefinitionInfo>(assemblyDefinitionAsset.text); assemblyDefinitionInfo?.Validate(availablePlatforms); toAdd = new CSProjectInfo(availablePlatforms, guidResult, assemblyDefinitionInfo, pair.Value, projectOutputPath); } csProjects.Add(pair.Key, toAdd); } Plugins = new ReadOnlyCollection <PluginAssemblyInfo>(ScanForPluginDLLs()); foreach (PluginAssemblyInfo plugin in Plugins) { if (plugin.Type == PluginType.Native) { Debug.LogWarning($"Native plugin {plugin.ReferencePath.AbsolutePath} not yet supported for MSBuild project."); } } foreach (CSProjectInfo project in CSProjects.Values) { // Get the assembly references first from AssemblyDefinitionInfo if available (it's actually more correct), otherwise fallback to Assemby IEnumerable <string> references = project.AssemblyDefinitionInfo == null ? project.Assembly.assemblyReferences.Select(t => t.name) : (project.AssemblyDefinitionInfo.references ?? Array.Empty <string>()); foreach (string reference in references) { if (CSProjects.TryGetValue(reference, out CSProjectInfo dependency)) { project.AddDependency(dependency); } else { Debug.LogError($"Failed to get dependency '{reference}' for project '{project.Name}'."); } } foreach (PluginAssemblyInfo plugin in Plugins) { if (plugin.AutoReferenced && plugin.Type != PluginType.Native) { project.AddDependency(plugin); } } } }