/// <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);
        }
Esempio n. 5
0
        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.");
            }
        }
Esempio n. 6
0
        /// <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);
        }
Esempio n. 8
0
        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);
                    }
                }
            }
        }