/// <summary> /// Creates a hash collection that represents the state of all modules in this list. If /// a module has no current output or is missing files then a null collection will be returned /// </summary> /// <param name="Modules"></param> /// <returns></returns> private static HashCollection HashModules(IEnumerable <string> Modules, bool WarnOnFailure = true) { HashCollection Hashes = new HashCollection(); foreach (string Module in Modules) { // this project is built by the AutomationTool project that the RunUAT script builds so // it will always be newer than was last built if (Module.Contains("AutomationUtils.Automation")) { continue; } CsProjectInfo Proj; Dictionary <string, string> Properties = new Dictionary <string, string>(); Properties.Add("Platform", "AnyCPU"); Properties.Add("Configuration", "Development"); FileReference ModuleFile = new FileReference(Module); if (!CsProjectInfo.TryRead(ModuleFile, Properties, out Proj)) { if (WarnOnFailure) { Log.TraceWarning("Failed to read file {0}", ModuleFile); } return(null); } if (!Hashes.AddCsProjectInfo(Proj, HashCollection.HashType.MetaData)) { if (WarnOnFailure) { Log.TraceWarning("Failed to hash file {0}", ModuleFile); } return(null); } } return(Hashes); }
/// <summary> /// Finds and/or compiles all script files and assemblies. /// </summary> /// <param name="ScriptsForProjectFileName">Path to the current project. May be null, in which case we compile scripts for all projects.</param> /// <param name="AdditionalScriptsFolders">Additional script fodlers to look for source files in.</param> public static void FindAndCompileAllScripts(string ScriptsForProjectFileName, List <string> AdditionalScriptsFolders) { // Find all the project files Stopwatch SearchTimer = Stopwatch.StartNew(); List <FileReference> ProjectFiles = FindAutomationProjects(ScriptsForProjectFileName, AdditionalScriptsFolders); Log.TraceLog("Found {0} project files in {1:0.000}s", ProjectFiles.Count, SearchTimer.Elapsed.TotalSeconds); // Get the default properties for compiling the projects Dictionary <string, string> MsBuildProperties = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); MsBuildProperties.Add("Platform", "AnyCPU"); MsBuildProperties.Add("Configuration", BuildConfig); MsBuildProperties.Add("EngineDir", CommandUtils.EngineDirectory.FullName); // Read all the projects Stopwatch ParsingTimer = Stopwatch.StartNew(); CsProjectInfo[] Projects = new CsProjectInfo[ProjectFiles.Count]; Parallel.For(0, ProjectFiles.Count, Idx => Projects[Idx] = CsProjectInfo.Read(ProjectFiles[Idx], MsBuildProperties)); Log.TraceLog("Parsed project files in {0:0.000}s", ParsingTimer.Elapsed.TotalSeconds); // Compile only if not disallowed. if (GlobalCommandLine.Compile && !String.IsNullOrEmpty(CommandUtils.CmdEnv.MsBuildExe)) { List <CsProjectInfo> CompileProjects = new List <CsProjectInfo>(Projects); if (CommandUtils.IsEngineInstalled()) { CompileProjects.RemoveAll(x => x.ProjectPath.IsUnderDirectory(CommandUtils.EngineDirectory)); } CompileAutomationProjects(CompileProjects, MsBuildProperties); } // Get all the build artifacts BuildProducts = new HashSet <FileReference>(); HashSet <DirectoryReference> OutputDirs = new HashSet <DirectoryReference>(); OutputDirs.Add(DirectoryReference.Combine(CommandUtils.EngineDirectory, "Binaries", "DotNET")); // Don't want any artifacts from this directory (just AutomationTool.exe and AutomationScripts.dll) foreach (CsProjectInfo Project in Projects) { DirectoryReference OutputDir; if (!Project.TryGetOutputDir(out OutputDir)) { throw new AutomationException("Unable to get output directory for {0}", Project.ProjectPath); } if (OutputDirs.Add(OutputDir)) { BuildProducts.UnionWith(DirectoryReference.EnumerateFiles(OutputDir)); } } // Load everything Stopwatch LoadTimer = Stopwatch.StartNew(); List <Assembly> Assemblies = LoadAutomationAssemblies(Projects); Log.TraceLog("Loaded assemblies in {0:0.000}s", LoadTimer.Elapsed.TotalSeconds); // Setup platforms Platform.InitializePlatforms(Assemblies.ToArray()); // Instantiate all the automation classes for interrogation Log.TraceVerbose("Creating commands."); ScriptCommands = new Dictionary <string, Type>(StringComparer.InvariantCultureIgnoreCase); foreach (Assembly CompiledScripts in Assemblies) { try { foreach (Type ClassType in CompiledScripts.GetTypes()) { if (ClassType.IsSubclassOf(typeof(BuildCommand)) && ClassType.IsAbstract == false) { if (ScriptCommands.ContainsKey(ClassType.Name) == false) { ScriptCommands.Add(ClassType.Name, ClassType); } else { bool IsSame = string.Equals(ClassType.AssemblyQualifiedName, ScriptCommands[ClassType.Name].AssemblyQualifiedName); if (IsSame == false) { Log.TraceWarning("Unable to add command {0} twice. Previous: {1}, Current: {2}", ClassType.Name, ClassType.AssemblyQualifiedName, ScriptCommands[ClassType.Name].AssemblyQualifiedName); } } } } } catch (ReflectionTypeLoadException LoadEx) { foreach (Exception SubEx in LoadEx.LoaderExceptions) { Log.TraceWarning("Got type loader exception: {0}", SubEx.ToString()); } throw new AutomationException("Failed to add commands from {0}. {1}", CompiledScripts, LoadEx); } catch (Exception Ex) { throw new AutomationException("Failed to add commands from {0}. {1}", CompiledScripts, Ex); } } }