Example #1
0
        /// <summary>
        /// Attempts to read project information for the given file.
        /// </summary>
        /// <param name="File">The project file to read</param>
        /// <param name="Properties">Initial set of property values</param>
        /// <param name="OutProjectInfo">If successful, the parsed project info</param>
        /// <returns>True if the project was read successfully, false otherwise</returns>
        public static bool TryRead(FileReference File, Dictionary <string, string> Properties, out CsProjectInfo OutProjectInfo)
        {
            // Read the project file
            XmlDocument Document = new XmlDocument();

            Document.Load(File.FullName);

            // Check the root element is the right type
//			HashSet<FileReference> ProjectBuildProducts = new HashSet<FileReference>();
            if (Document.DocumentElement.Name != "Project")
            {
                OutProjectInfo = null;
                return(false);
            }

            // Parse the basic structure of the document, updating properties and recursing into other referenced projects as we go
            CsProjectInfo ProjectInfo = new CsProjectInfo(Properties);

            foreach (XmlElement Element in Document.DocumentElement.ChildNodes.OfType <XmlElement>())
            {
                switch (Element.Name)
                {
                case "PropertyGroup":
                    if (EvaluateCondition(Element, ProjectInfo.Properties))
                    {
                        ParsePropertyGroup(Element, ProjectInfo.Properties);
                    }
                    break;

                case "ItemGroup":
                    if (EvaluateCondition(Element, ProjectInfo.Properties))
                    {
                        ParseItemGroup(File.Directory, Element, ProjectInfo);
                    }
                    break;
                }
            }

            // Return the complete project
            OutProjectInfo = ProjectInfo;
            return(true);
        }
Example #2
0
        /// <summary>
        /// Read a project file, plus all the project files it references.
        /// </summary>
        /// <param name="File">Project file to read</param>
        /// <param name="InitialProperties">Mapping of property name to value for the initial project</param>
        /// <param name="FileToProjectInfo"></param>
        /// <returns>True if the projects were read correctly, false (and prints an error to the log) if not</returns>
        static void ReadProjectsRecursively(FileReference File, Dictionary <string, string> InitialProperties, Dictionary <FileReference, CsProjectInfo> FileToProjectInfo)
        {
            // Early out if we've already read this project
            if (!FileToProjectInfo.ContainsKey(File))
            {
                // Try to read this project
                CsProjectInfo ProjectInfo;
                if (!CsProjectInfo.TryRead(File, InitialProperties, out ProjectInfo))
                {
                    throw new AutomationException("Couldn't read project '{0}'", File.FullName);
                }

                // Add it to the project lookup, and try to read all the projects it references
                FileToProjectInfo.Add(File, ProjectInfo);
                foreach (FileReference ProjectReference in ProjectInfo.ProjectReferences.Keys)
                {
                    ReadProjectsRecursively(ProjectReference, InitialProperties, FileToProjectInfo);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Read a project file, plus all the project files it references.
        /// </summary>
        /// <param name="File">Project file to read</param>
        /// <param name="InitialProperties">Mapping of property name to value for the initial project</param>
        /// <param name="FileToProjectInfo"></param>
        /// <returns>True if the projects were read correctly, false (and prints an error to the log) if not</returns>
        static bool ReadProjectsRecursively(FileReference File, Dictionary <string, string> InitialProperties, Dictionary <FileReference, CsProjectInfo> FileToProjectInfo)
        {
            // Early out if we've already read this project, return success
            if (FileToProjectInfo.ContainsKey(File))
            {
                return(true);
            }

            // Try to read this project
            CsProjectInfo ProjectInfo;

            if (!CsProjectInfo.TryRead(File, InitialProperties, out ProjectInfo))
            {
                CommandUtils.LogError("Couldn't read project '{0}'", File.FullName);
                return(false);
            }

            // Add it to the project lookup, and try to read all the projects it references
            FileToProjectInfo.Add(File, ProjectInfo);
            return(ProjectInfo.ProjectReferences.Keys.All(x => ReadProjectsRecursively(x, InitialProperties, FileToProjectInfo)));
        }
Example #4
0
        /// <summary>
        /// Find all the build products created by compiling the given project file
        /// </summary>
        /// <param name="ProjectFiles">Initial project file to read. All referenced projects will also be read.</param>
        /// <param name="InitialProperties">Mapping of property name to value</param>
        /// <param name="OutBuildProducts">Receives a set of build products on success</param>
        /// <param name="OutReferences">Receives a set of non-private references on success</param>
        static void FindBuildProductsAndReferences(HashSet <FileReference> ProjectFiles, Dictionary <string, string> InitialProperties, out HashSet <FileReference> OutBuildProducts, out HashSet <FileReference> OutReferences)
        {
            // Find all the build products and references
            OutBuildProducts = new HashSet <FileReference>();
            OutReferences    = new HashSet <FileReference>();

            // Read all the project information into a dictionary
            Dictionary <FileReference, CsProjectInfo> FileToProjectInfo = new Dictionary <FileReference, CsProjectInfo>();

            foreach (FileReference ProjectFile in ProjectFiles)
            {
                // Read all the projects
                ReadProjectsRecursively(ProjectFile, InitialProperties, FileToProjectInfo);

                // Find all the outputs for each project
                foreach (KeyValuePair <FileReference, CsProjectInfo> Pair in FileToProjectInfo)
                {
                    CsProjectInfo ProjectInfo = Pair.Value;

                    // Add all the build projects from this project
                    DirectoryReference OutputDir = ProjectInfo.GetOutputDir(Pair.Key.Directory);
                    ProjectInfo.FindBuildProducts(OutputDir, OutBuildProducts, FileToProjectInfo);

                    // Add any files which are only referenced
                    foreach (KeyValuePair <FileReference, bool> Reference in ProjectInfo.References)
                    {
                        if (!Reference.Value)
                        {
                            CsProjectInfo.AddReferencedAssemblyAndSupportFiles(Reference.Key, OutReferences);
                        }
                    }
                }
            }

            OutBuildProducts.RemoveWhere(x => !FileReference.Exists(x));
            OutReferences.RemoveWhere(x => !FileReference.Exists(x));
        }
Example #5
0
        /// <summary>
        /// Parses an 'ItemGroup' element.
        /// </summary>
        /// <param name="BaseDirectory">Base directory to resolve relative paths against</param>
        /// <param name="ParentElement">The parent 'ItemGroup' element</param>
        /// <param name="ProjectInfo">Project info object to be updated</param>
        static void ParseItemGroup(DirectoryReference BaseDirectory, XmlElement ParentElement, CsProjectInfo ProjectInfo)
        {
            // Parse any external assembly references
            foreach (XmlElement ItemElement in ParentElement.ChildNodes.OfType <XmlElement>())
            {
                switch (ItemElement.Name)
                {
                case "Reference":
                    // Reference to an external assembly
                    if (EvaluateCondition(ItemElement, ProjectInfo.Properties))
                    {
                        ParseReference(BaseDirectory, ItemElement, ProjectInfo.References);
                    }
                    break;

                case "ProjectReference":
                    // Reference to another project
                    if (EvaluateCondition(ItemElement, ProjectInfo.Properties))
                    {
                        ParseProjectReference(BaseDirectory, ItemElement, ProjectInfo.ProjectReferences);
                    }
                    break;
                }
            }
        }
Example #6
0
        /// <summary>
        /// Find all the build products created by compiling the given project file
        /// </summary>
        /// <param name="ProjectFiles">Initial project file to read. All referenced projects will also be read.</param>
        /// <param name="InitialProperties">Mapping of property name to value</param>
        /// <param name="OutBuildProducts">Receives a set of build products on success</param>
        /// <param name="OutReferences">Receives a set of non-private references on success</param>
        /// <returns>True if the build products were found, false otherwise.</returns>
        static bool FindBuildProducts(HashSet <FileReference> ProjectFiles, Dictionary <string, string> InitialProperties, out HashSet <FileReference> OutBuildProducts, out HashSet <FileReference> OutReferences)
        {
            // Read all the project information into a dictionary
            Dictionary <FileReference, CsProjectInfo> FileToProjectInfo = new Dictionary <FileReference, CsProjectInfo>();

            foreach (FileReference ProjectFile in ProjectFiles)
            {
                if (!ReadProjectsRecursively(ProjectFile, InitialProperties, FileToProjectInfo))
                {
                    OutBuildProducts = null;
                    OutReferences    = null;
                    return(false);
                }
            }

            // Find all the build products and references
            HashSet <FileReference> BuildProducts = new HashSet <FileReference>();
            HashSet <FileReference> References    = new HashSet <FileReference>();

            foreach (KeyValuePair <FileReference, CsProjectInfo> Pair in FileToProjectInfo)
            {
                CsProjectInfo ProjectInfo = Pair.Value;

                // Add the standard build products
                DirectoryReference OutputDir = ProjectInfo.GetOutputDir(Pair.Key.Directory);
                ProjectInfo.AddBuildProducts(OutputDir, BuildProducts);

                // Add the referenced assemblies
                foreach (KeyValuePair <FileReference, bool> Reference in ProjectInfo.References)
                {
                    FileReference OtherAssembly = Reference.Key;
                    if (Reference.Value)
                    {
                        // Add reference from the output dir
                        FileReference OutputFile = FileReference.Combine(OutputDir, OtherAssembly.GetFileName());
                        BuildProducts.Add(OutputFile);

                        FileReference OutputSymbolFile = OutputFile.ChangeExtension(".pdb");
                        if (FileReference.Exists(OutputSymbolFile))
                        {
                            BuildProducts.Add(OutputSymbolFile);
                        }
                    }
                    else
                    {
                        // Add reference directly
                        References.Add(OtherAssembly);
                        FileReference SymbolFile = OtherAssembly.ChangeExtension(".pdb");
                        if (FileReference.Exists(SymbolFile))
                        {
                            References.Add(SymbolFile);
                        }
                    }
                }

                // Add build products from all the referenced projects. MSBuild only copy the directly referenced build products, not recursive references or other assemblies.
                foreach (CsProjectInfo OtherProjectInfo in ProjectInfo.ProjectReferences.Where(x => x.Value).Select(x => FileToProjectInfo[x.Key]))
                {
                    OtherProjectInfo.AddBuildProducts(OutputDir, BuildProducts);
                }
            }

            // Update the output set
            OutBuildProducts = BuildProducts;
            OutReferences    = References;
            return(true);
        }
		/// <summary>
		/// Parses an 'ItemGroup' element.
		/// </summary>
		/// <param name="BaseDirectory">Base directory to resolve relative paths against</param>
		/// <param name="ParentElement">The parent 'ItemGroup' element</param>
		/// <param name="ProjectInfo">Project info object to be updated</param>
		static void ParseItemGroup(DirectoryReference BaseDirectory, XmlElement ParentElement, CsProjectInfo ProjectInfo)
		{
			// Parse any external assembly references
			foreach(XmlElement ItemElement in ParentElement.ChildNodes.OfType<XmlElement>())
			{
				switch(ItemElement.Name)
				{
					case "Reference":
						// Reference to an external assembly
						if(EvaluateCondition(ItemElement, ProjectInfo.Properties))
						{
							ParseReference(BaseDirectory, ItemElement, ProjectInfo.References);
						}
						break;
					case "ProjectReference":
						// Reference to another project
						if(EvaluateCondition(ItemElement, ProjectInfo.Properties))
						{
							ParseProjectReference(BaseDirectory, ItemElement, ProjectInfo.ProjectReferences);
						}
						break;
				}
			}
		}
		/// <summary>
		/// Attempts to read project information for the given file.
		/// </summary>
		/// <param name="File">The project file to read</param>
		/// <param name="Properties">Initial set of property values</param>
		/// <param name="OutProjectInfo">If successful, the parsed project info</param>
		/// <returns>True if the project was read successfully, false otherwise</returns>
		public static bool TryRead(FileReference File, Dictionary<string, string> Properties, out CsProjectInfo OutProjectInfo)
		{
			// Read the project file
			XmlDocument Document = new XmlDocument();
			Document.Load(File.FullName);

			// Check the root element is the right type
//			HashSet<FileReference> ProjectBuildProducts = new HashSet<FileReference>();
			if(Document.DocumentElement.Name != "Project")
			{
				OutProjectInfo = null;
				return false;
			}

			// Parse the basic structure of the document, updating properties and recursing into other referenced projects as we go
			CsProjectInfo ProjectInfo = new CsProjectInfo(Properties);
			foreach(XmlElement Element in Document.DocumentElement.ChildNodes.OfType<XmlElement>())
			{
				switch(Element.Name)
				{
					case "PropertyGroup":
						if(EvaluateCondition(Element, ProjectInfo.Properties))
						{
							ParsePropertyGroup(Element, ProjectInfo.Properties);
						}
						break;
					case "ItemGroup":
						if(EvaluateCondition(Element, ProjectInfo.Properties))
						{
							ParseItemGroup(File.Directory, Element, ProjectInfo);
						}
						break;
				}
			}

			// Return the complete project
			OutProjectInfo = ProjectInfo;
			return true;
		}