/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="InAdd"></param>
		/// <param name="InFilter"></param>
		/// <param name="InBaseDirectory"></param>
		public OutputTask(FileFilter InAddFiles, FileFilter InFilterFiles, string InBaseDirectory)
		{
			AddFiles = InAddFiles;
			FilterFiles = InFilterFiles;
			BaseDirectory = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, InBaseDirectory);
		}
예제 #2
0
파일: UBTUtils.cs 프로젝트: LLChennn/UE4.21
        /// <summary>
        /// Runs UBT with the specified commandline. Automatically creates a logfile. When
        /// no LogName is specified, the executable name is used as logfile base name.
        /// </summary>
        /// <param name="Env">Environment to use.</param>
        /// <param name="CommandLine">Commandline to pass on to UBT.</param>
        /// <param name="LogName">Optional logfile name.</param>
        public static void RunUBT(CommandEnvironment Env, string UBTExecutable, string CommandLine)
        {
            if (!FileExists(UBTExecutable))
            {
                throw new AutomationException("Unable to find UBT executable: " + UBTExecutable);
            }

            if (GlobalCommandLine.VS2015)
            {
                CommandLine += " -2015";
            }
            if (!IsBuildMachine && UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealBuildTool.UnrealTargetPlatform.Mac)
            {
                CommandLine += " -nocreatestub";
            }
            CommandLine += " -NoHotReload";
            if (bJunkDeleted || GlobalCommandLine.IgnoreJunk)
            {
                // UBT has already deleted junk files, make sure it doesn't do it again
                CommandLine += " -ignorejunk";
            }
            else
            {
                // UBT will delete junk on first run
                bJunkDeleted = true;
            }

            string BaseLogName = String.Format("UBT-{0}", String.Join("-", SharedUtils.ParseCommandLine(CommandLine).Where(x => !x.Contains('/') && !x.Contains('\\') && !x.StartsWith("-"))));
            string LogName;

            for (int Attempt = 1;; Attempt++)
            {
                LogName = String.Format("{0}.txt", (Attempt == 1)? BaseLogName : String.Format("{0}_{1}", BaseLogName, Attempt));

                FileReference LogLocation = FileReference.Combine(new DirectoryReference(Env.LogFolder), LogName);
                if (!FileReference.Exists(LogLocation))
                {
                    CommandLine += String.Format(" -log=\"{0}\"", LogLocation);
                    break;
                }

                if (Attempt >= 50)
                {
                    throw new AutomationException("Unable to find name for UBT log file after {0} attempts", Attempt);
                }
            }

            IProcessResult Result = Run(UBTExecutable, CommandLine, Options: ERunOptions.AllowSpew | ERunOptions.NoStdOutCapture);

            if (Result.ExitCode != 0)
            {
                throw new AutomationException((ExitCode)Result.ExitCode, "UnrealBuildTool failed. See log for more details. ({0})", CommandUtils.CombinePaths(Env.FinalLogFolder, LogName));
            }
        }
예제 #3
0
        public static int Main()
        {
            var CommandLine = SharedUtils.ParseCommandLine();

            LogUtils.InitLogging(CommandLine);

            ErrorCodes ReturnCode = ErrorCodes.Error_Success;

            try
            {
                HostPlatform.Initialize();

                Log.TraceVerbose("Running on {0} as a {1}-bit process.", HostPlatform.Current.GetType().Name, Environment.Is64BitProcess ? 64 : 32);

                XmlConfigLoader.Init();

                // Log if we're running from the launcher
                var ExecutingAssemblyLocation = CommandUtils.CombinePaths(Assembly.GetExecutingAssembly().Location);
                if (String.Compare(ExecutingAssemblyLocation, CommandUtils.CombinePaths(InternalUtils.ExecutingAssemblyLocation), true) != 0)
                {
                    Log.WriteLine(TraceEventType.Information, "Executed from AutomationToolLauncher ({0})", ExecutingAssemblyLocation);
                }
                Log.WriteLine(TraceEventType.Information, "CWD={0}", Environment.CurrentDirectory);

                // Hook up exit callbacks
                var Domain = AppDomain.CurrentDomain;
                Domain.ProcessExit  += Domain_ProcessExit;
                Domain.DomainUnload += Domain_ProcessExit;
                HostPlatform.Current.SetConsoleCtrlHandler(ProgramCtrlHandler);

                var Version = InternalUtils.ExecutableVersion;
                Log.WriteLine(TraceEventType.Verbose, "{0} ver. {1}", Version.ProductName, Version.ProductVersion);

                // Don't allow simultaneous execution of AT (in the same branch)
                InternalUtils.RunSingleInstance(MainProc, CommandLine);
            }
            catch (Exception Ex)
            {
                // Catch all exceptions and propagate the ErrorCode if we are given one.
                Log.WriteLine(TraceEventType.Error, "AutomationTool terminated with exception:");
                Log.WriteLine(TraceEventType.Error, LogUtils.FormatException(Ex));
                // set the exit code of the process
                if (Ex is AutomationException)
                {
                    ReturnCode = (Ex as AutomationException).ErrorCode;
                }
                else
                {
                    ReturnCode = ErrorCodes.Error_Unknown;
                }
            }
            finally
            {
                // In all cases, do necessary shut down stuff, but don't let any additional exceptions leak out while trying to shut down.

                // Make sure there's no directories on the stack.
                NoThrow(() => CommandUtils.ClearDirStack(), "Clear Dir Stack");

                // Try to kill process before app domain exits to leave the other KillAll call to extreme edge cases
                NoThrow(() => { if (ShouldKillProcesses && !Utils.IsRunningOnMono)
                                {
                                    ProcessManager.KillAll();
                                }
                        }, "Kill All Processes");

                Log.WriteLine(TraceEventType.Information, "AutomationTool exiting with ExitCode={0}", ReturnCode);

                // Can't use NoThrow here because the code logs exceptions. We're shutting down logging!
                LogUtils.ShutdownLogging();
            }

            // STOP: No code beyond the return statement should go beyond this point!
            // Nothing should happen after the finally block above is finished.
            return((int)ReturnCode);
        }
예제 #4
0
        private static void FindAndCompileScriptModules(string ScriptsForProjectFileName, List <string> AdditionalScriptsFolders)
        {
            Log.TraceInformation("Compiling scripts.");

            var OldCWD             = Environment.CurrentDirectory;
            var UnrealBuildToolCWD = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Source");

            Environment.CurrentDirectory = UnrealBuildToolCWD;

            // Configure the rules compiler
            // Get all game folders and convert them to build subfolders.
            List <DirectoryReference> AllGameFolders;

            if (ScriptsForProjectFileName == null)
            {
                AllGameFolders = UProjectInfo.FilterGameProjects(true, null).Select(x => x.Folder).ToList();
            }
            else
            {
                AllGameFolders = new List <DirectoryReference> {
                    new DirectoryReference(Path.GetDirectoryName(ScriptsForProjectFileName))
                };
            }

            var AllAdditionalScriptFolders = new List <DirectoryReference>(AdditionalScriptsFolders.Select(x => new DirectoryReference(x)));

            foreach (var Folder in AllGameFolders)
            {
                var GameBuildFolder = DirectoryReference.Combine(Folder, "Build");
                if (DirectoryReference.Exists(GameBuildFolder))
                {
                    AllAdditionalScriptFolders.Add(GameBuildFolder);
                }
            }

            Log.TraceVerbose("Discovering game folders.");

            var DiscoveredModules = UnrealBuildTool.RulesCompiler.FindAllRulesSourceFiles(UnrealBuildTool.RulesCompiler.RulesFileType.AutomationModule, GameFolders: AllGameFolders, ForeignPlugins: null, AdditionalSearchPaths: AllAdditionalScriptFolders);
            var ModulesToCompile  = new List <string>(DiscoveredModules.Count);

            foreach (var ModuleFilename in DiscoveredModules)
            {
                if (HostPlatform.Current.IsScriptModuleSupported(ModuleFilename.GetFileNameWithoutAnyExtensions()))
                {
                    ModulesToCompile.Add(ModuleFilename.FullName);
                }
                else
                {
                    CommandUtils.LogVerbose("Script module {0} filtered by the Host Platform and will not be compiled.", ModuleFilename);
                }
            }

            if ((UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealBuildTool.UnrealTargetPlatform.Win64) ||
                (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealBuildTool.UnrealTargetPlatform.Win32))
            {
                string Modules = string.Join(";", ModulesToCompile.ToArray());
                var    UATProj = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, @"Engine\Source\Programs\AutomationTool\Scripts\UAT.proj");
                var    CmdLine = String.Format("\"{0}\" /p:Modules=\"{1}\" /p:Configuration={2} /verbosity:minimal /nologo", UATProj, Modules, BuildConfig);
                // suppress the run command because it can be long and intimidating, making the logs around this code harder to read.
                var Result = CommandUtils.Run(CommandUtils.CmdEnv.MsBuildExe, CmdLine, Options: CommandUtils.ERunOptions.Default | CommandUtils.ERunOptions.NoLoggingOfRunCommand | CommandUtils.ERunOptions.LoggingOfRunDuration);
                if (Result.ExitCode != 0)
                {
                    throw new AutomationException(String.Format("Failed to build \"{0}\":{1}{2}", UATProj, Environment.NewLine, Result.Output));
                }
            }
            else
            {
                CompileModules(ModulesToCompile);
            }


            Environment.CurrentDirectory = OldCWD;
        }
예제 #5
0
        /// <summary>
        /// Detects root paths for the specified client.
        /// </summary>
        /// <param name="UATLocation">AutomationTool.exe location</param>
        /// <param name="ThisClient">Client to detect the root paths for</param>
        /// <param name="BuildRootPath">Build root</param>
        /// <param name="LocalRootPath">Local root</param>
        /// <param name="ClientRootPath">Client root</param>
        private static void DetectRootPaths(P4Connection Connection, string LocalRootPath, P4ClientInfo ThisClient, out string BuildRootPath, out string ClientRootPath)
        {
            if (!String.IsNullOrEmpty(ThisClient.Stream))
            {
                BuildRootPath  = ThisClient.Stream;
                ClientRootPath = String.Format("//{0}", ThisClient.Name);
            }
            else
            {
                // Figure out the build root
                string         KnownFilePathFromRoot = CommandEnvironment.KnownFileRelativeToRoot;
                string         KnownLocalPath        = CommandUtils.MakePathSafeToUseWithCommandLine(CommandUtils.CombinePaths(PathSeparator.Slash, LocalRootPath, KnownFilePathFromRoot));
                IProcessResult P4Result = Connection.P4(String.Format("files -m 1 {0}", KnownLocalPath), AllowSpew: false);

                string KnownFileDepotMapping = P4Result.Output;

                // Get the build root
                Log.TraceVerbose("Looking for {0} in {1}", KnownFilePathFromRoot, KnownFileDepotMapping);
                int EndIdx = KnownFileDepotMapping.IndexOf(KnownFilePathFromRoot, StringComparison.CurrentCultureIgnoreCase);
                if (EndIdx < 0)
                {
                    EndIdx = KnownFileDepotMapping.IndexOf(CommandUtils.ConvertSeparators(PathSeparator.Slash, KnownFilePathFromRoot), StringComparison.CurrentCultureIgnoreCase);
                }
                // Get the root path without the trailing path separator
                BuildRootPath = KnownFileDepotMapping.Substring(0, EndIdx - 1);

                // Get the client root
                if (LocalRootPath.StartsWith(CommandUtils.CombinePaths(PathSeparator.Slash, ThisClient.RootPath, "/"), StringComparison.InvariantCultureIgnoreCase) || LocalRootPath == CommandUtils.CombinePaths(PathSeparator.Slash, ThisClient.RootPath))
                {
                    ClientRootPath = CommandUtils.CombinePaths(PathSeparator.Depot, String.Format("//{0}", ThisClient.Name), LocalRootPath.Substring(ThisClient.RootPath.Length));
                }
                else
                {
                    throw new AutomationException("LocalRootPath ({0}) does not start with the client root path ({1})", LocalRootPath, ThisClient.RootPath);
                }
            }
        }
        /// <summary>
        /// Attempts to autodetect project properties.
        /// </summary>
        /// <param name="RawProjectPath">Full project path.</param>
        /// <returns>Project properties.</returns>
        private static ProjectProperties DetectProjectProperties(FileReference RawProjectPath, List <UnrealTargetPlatform> ClientTargetPlatforms, bool AssetNativizationRequested)
        {
            var Properties = new ProjectProperties();

            Properties.RawProjectPath = RawProjectPath;

            // detect if the project is content only, but has non-default build settings
            List <string> ExtraSearchPaths = null;

            if (RawProjectPath != null)
            {
                string TempTargetDir = CommandUtils.CombinePaths(Path.GetDirectoryName(RawProjectPath.FullName), "Intermediate", "Source");
                if (RequiresTempTarget(RawProjectPath, ClientTargetPlatforms, AssetNativizationRequested))
                {
                    GenerateTempTarget(RawProjectPath);
                    Properties.bWasGenerated = true;
                    ExtraSearchPaths         = new List <string>();
                    ExtraSearchPaths.Add(TempTargetDir);
                }
                else if (File.Exists(Path.Combine(Path.GetDirectoryName(RawProjectPath.FullName), "Intermediate", "Source", Path.GetFileNameWithoutExtension(RawProjectPath.FullName) + ".Target.cs")))
                {
                    File.Delete(Path.Combine(Path.GetDirectoryName(RawProjectPath.FullName), "Intermediate", "Source", Path.GetFileNameWithoutExtension(RawProjectPath.FullName) + ".Target.cs"));
                }

                // in case the RulesCompiler (what we use to find all the
                // Target.cs files) has already cached the contents of this
                // directory, then we need to invalidate that cache (so
                // it'll find/use the new Target.cs file)
                RulesCompiler.InvalidateRulesFileCache(TempTargetDir);
            }

            if (CommandUtils.CmdEnv.HasCapabilityToCompile)
            {
                DetectTargetsForProject(Properties, ExtraSearchPaths);
                Properties.bIsCodeBasedProject = !CommandUtils.IsNullOrEmpty(Properties.Targets) || !CommandUtils.IsNullOrEmpty(Properties.Programs);
            }
            else
            {
                // should never ask for engine targets if we can't compile
                if (RawProjectPath == null)
                {
                    throw new AutomationException("Cannot determine engine targets if we can't compile.");
                }

                Properties.bIsCodeBasedProject = Properties.bWasGenerated;
                // if there's a Source directory with source code in it, then mark us as having source code
                string SourceDir = CommandUtils.CombinePaths(Path.GetDirectoryName(RawProjectPath.FullName), "Source");
                if (Directory.Exists(SourceDir))
                {
                    string[] CppFiles = Directory.GetFiles(SourceDir, "*.cpp", SearchOption.AllDirectories);
                    string[] HFiles   = Directory.GetFiles(SourceDir, "*.h", SearchOption.AllDirectories);
                    Properties.bIsCodeBasedProject |= (CppFiles.Length > 0 || HFiles.Length > 0);
                }
            }

            // check to see if the uproject loads modules, only if we haven't already determined it is a code based project
            if (!Properties.bIsCodeBasedProject && RawProjectPath != null)
            {
                string uprojectStr = File.ReadAllText(RawProjectPath.FullName);
                Properties.bIsCodeBasedProject = uprojectStr.Contains("\"Modules\"");
            }

            // Get all ini files
            if (RawProjectPath != null)
            {
                CommandUtils.LogVerbose("Loading ini files for {0}", RawProjectPath);

                foreach (UnrealTargetPlatform TargetPlatformType in Enum.GetValues(typeof(UnrealTargetPlatform)))
                {
                    if (TargetPlatformType != UnrealTargetPlatform.Unknown)
                    {
                        var Config = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, RawProjectPath.Directory, TargetPlatformType);
                        Properties.EngineConfigs.Add(TargetPlatformType, Config);
                    }
                }

                foreach (UnrealTargetPlatform TargetPlatformType in Enum.GetValues(typeof(UnrealTargetPlatform)))
                {
                    if (TargetPlatformType != UnrealTargetPlatform.Unknown)
                    {
                        var Config = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, RawProjectPath.Directory, TargetPlatformType);
                        Properties.GameConfigs.Add(TargetPlatformType, Config);
                    }
                }
            }

            return(Properties);
        }
예제 #7
0
        /// <summary>
        /// Entry point for the commandlet
        /// </summary>
        public override void ExecuteBuild()
        {
            string OutputDir = ParseParamValue("OutputDir");
            string ContentOnlyPlatformsString = ParseParamValue("ContentOnlyPlatforms");
            IEnumerable <UnrealTargetPlatform> ContentOnlyPlatforms = Enumerable.Empty <UnrealTargetPlatform>();

            if (!String.IsNullOrWhiteSpace(ContentOnlyPlatformsString))
            {
                ContentOnlyPlatforms = ContentOnlyPlatformsString.Split(';').Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => UnrealTargetPlatform.Parse(x));
            }
            string AnalyticsTypeOverride = ParseParamValue("AnalyticsTypeOverride");

            // Write InstalledBuild.txt to indicate Engine is installed
            string InstalledBuildFile = CommandUtils.CombinePaths(OutputDir, "Engine/Build/InstalledBuild.txt");

            CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(InstalledBuildFile));
            CommandUtils.WriteAllText(InstalledBuildFile, "");

            // Write InstalledBuild.txt to indicate Engine is installed
            string Project = ParseParamValue("Project");

            if (Project != null)
            {
                string InstalledProjectBuildFile = CommandUtils.CombinePaths(OutputDir, "Engine/Build/InstalledProjectBuild.txt");
                CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(InstalledProjectBuildFile));
                CommandUtils.WriteAllText(InstalledProjectBuildFile, new FileReference(Project).MakeRelativeTo(new DirectoryReference(OutputDir)));
            }

            string         OutputEnginePath     = Path.Combine(OutputDir, "Engine");
            string         OutputBaseEnginePath = Path.Combine(OutputEnginePath, "Config", "BaseEngine.ini");
            FileAttributes OutputAttributes     = FileAttributes.ReadOnly;
            List <String>  IniLines             = new List <String>();

            // Should always exist but if not, we don't need extra line
            if (File.Exists(OutputBaseEnginePath))
            {
                OutputAttributes = File.GetAttributes(OutputBaseEnginePath);
                IniLines.Add("");
            }
            else
            {
                CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(OutputBaseEnginePath));
                CommandUtils.WriteAllText(OutputBaseEnginePath, "");
                OutputAttributes = File.GetAttributes(OutputBaseEnginePath) | OutputAttributes;
            }

            // Create list of platform configurations installed in a Rocket build
            List <InstalledPlatformInfo.InstalledPlatformConfiguration> InstalledConfigs = new List <InstalledPlatformInfo.InstalledPlatformConfiguration>();

            // Add the editor platform, otherwise we'll never be able to run UAT
            string EditorArchitecture = PlatformExports.GetDefaultArchitecture(HostPlatform.Current.HostEditorPlatform, null);

            InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(UnrealTargetConfiguration.Development, HostPlatform.Current.HostEditorPlatform, TargetRules.TargetType.Editor, EditorArchitecture, "", EProjectType.Unknown, false));
            InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(UnrealTargetConfiguration.DebugGame, HostPlatform.Current.HostEditorPlatform, TargetRules.TargetType.Editor, EditorArchitecture, "", EProjectType.Unknown, false));

            foreach (UnrealTargetPlatform CodeTargetPlatform in UnrealTargetPlatform.GetValidPlatforms())
            {
                if (PlatformExports.IsPlatformAvailable(CodeTargetPlatform))
                {
                    string Architecture = PlatformExports.GetDefaultArchitecture(CodeTargetPlatform, null);

                    // Try to parse additional Architectures from the command line
                    string Architectures    = ParseParamValue(CodeTargetPlatform.ToString() + "Architectures");
                    string GPUArchitectures = ParseParamValue(CodeTargetPlatform.ToString() + "GPUArchitectures");

                    // Build a list of pre-compiled architecture combinations for this platform if any
                    List <string> AllArchNames;

                    if (!String.IsNullOrWhiteSpace(Architectures) && !String.IsNullOrWhiteSpace(GPUArchitectures))
                    {
                        AllArchNames = (from Arch in Architectures.Split('+')
                                        from GPUArch in GPUArchitectures.Split('+')
                                        select "-" + Arch + "-" + GPUArch).ToList();
                    }
                    else if (!String.IsNullOrWhiteSpace(Architectures))
                    {
                        AllArchNames = Architectures.Split('+').ToList();
                    }
                    // if there aren't any, use the default
                    else
                    {
                        AllArchNames = new List <string>()
                        {
                            Architecture
                        };
                    }

                    // Check whether this platform should only be used for content based projects
                    EProjectType ProjectType = ContentOnlyPlatforms.Contains(CodeTargetPlatform) ? EProjectType.Content : EProjectType.Any;

                    // Allow Content only platforms to be shown as options in all projects
                    bool bCanBeDisplayed = ProjectType == EProjectType.Content;
                    foreach (UnrealTargetConfiguration CodeTargetConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration)))
                    {
                        Dictionary <String, TargetType> Targets = new Dictionary <string, TargetType>()
                        {
                            { "UE4Game", TargetType.Game },
                            { "UE4Client", TargetType.Client },
                            { "UE4Server", TargetType.Server }
                        };
                        foreach (KeyValuePair <string, TargetType> Target in Targets)
                        {
                            string     CurrentTargetName = Target.Key;
                            TargetType CurrentTargetType = Target.Value;

                            // Need to check for development receipt as we use that for the Engine code in DebugGame
                            UnrealTargetConfiguration EngineConfiguration = (CodeTargetConfiguration == UnrealTargetConfiguration.DebugGame) ? UnrealTargetConfiguration.Development : CodeTargetConfiguration;

                            // Android has multiple architecture flavors built without receipts, so use the default arch target instead
                            if (CodeTargetPlatform == UnrealTargetPlatform.Android)
                            {
                                FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(new DirectoryReference(OutputEnginePath), CurrentTargetName, CodeTargetPlatform, EngineConfiguration, Architecture);
                                if (FileReference.Exists(ReceiptFileName))
                                {
                                    // Strip the output folder so that this can be used on any machine
                                    string RelativeReceiptFileName = ReceiptFileName.MakeRelativeTo(new DirectoryReference(OutputDir));

                                    // Blindly append all of the architecture names
                                    if (AllArchNames.Count > 0)
                                    {
                                        foreach (string Arch in AllArchNames)
                                        {
                                            InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, CurrentTargetType, Arch, RelativeReceiptFileName, ProjectType, bCanBeDisplayed));
                                        }
                                    }
                                    // if for some reason we didn't specify any flavors, just add the default one.
                                    else
                                    {
                                        InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, CurrentTargetType, Architecture, RelativeReceiptFileName, ProjectType, bCanBeDisplayed));
                                    }
                                }
                            }
                            // If we're not Android, check the existence of the target receipts for each architecture specified.
                            else
                            {
                                foreach (string Arch in AllArchNames)
                                {
                                    FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(new DirectoryReference(OutputEnginePath), CurrentTargetName, CodeTargetPlatform, EngineConfiguration, Arch);
                                    if (FileReference.Exists(ReceiptFileName))
                                    {
                                        string RelativeReceiptFileName = ReceiptFileName.MakeRelativeTo(new DirectoryReference(OutputDir));
                                        InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, CurrentTargetType, Arch, RelativeReceiptFileName, ProjectType, bCanBeDisplayed));
                                    }
                                }
                            }
                        }
                    }
                }
            }

            UnrealBuildTool.InstalledPlatformInfo.WriteConfigFileEntries(InstalledConfigs, ref IniLines);

            if (!String.IsNullOrEmpty(AnalyticsTypeOverride))
            {
                // Write Custom Analytics type setting
                IniLines.Add("");
                IniLines.Add("[Analytics]");
                IniLines.Add(String.Format("UE4TypeOverride=\"{0}\"", AnalyticsTypeOverride));
            }

            // Make sure we can write to the the config file
            File.SetAttributes(OutputBaseEnginePath, OutputAttributes & ~FileAttributes.ReadOnly);
            File.AppendAllLines(OutputBaseEnginePath, IniLines);
            File.SetAttributes(OutputBaseEnginePath, OutputAttributes);
        }
예제 #8
0
        public static int Main()
        {
            var CommandLine = SharedUtils.ParseCommandLine();

            HostPlatform.Initialize();

            LogUtils.InitLogging(CommandLine);
            Log.WriteLine(TraceEventType.Information, "Running on {0}", HostPlatform.Current.GetType().Name);

            XmlConfigLoader.Init();

            // Log if we're running from the launcher
            var ExecutingAssemblyLocation = CommandUtils.CombinePaths(Assembly.GetExecutingAssembly().Location);

            if (String.Compare(ExecutingAssemblyLocation, CommandUtils.CombinePaths(InternalUtils.ExecutingAssemblyLocation), true) != 0)
            {
                Log.WriteLine(TraceEventType.Information, "Executed from AutomationToolLauncher ({0})", ExecutingAssemblyLocation);
            }
            Log.WriteLine(TraceEventType.Information, "CWD={0}", Environment.CurrentDirectory);

            // Hook up exit callbacks
            var Domain = AppDomain.CurrentDomain;

            Domain.ProcessExit  += Domain_ProcessExit;
            Domain.DomainUnload += Domain_ProcessExit;
            HostPlatform.Current.SetConsoleCtrlHandler(ProgramCtrlHandler);

            var Version = InternalUtils.ExecutableVersion;

            Log.WriteLine(TraceEventType.Verbose, "{0} ver. {1}", Version.ProductName, Version.ProductVersion);

            try
            {
                // Don't allow simultaneous execution of AT (in the same branch)
                ReturnCode = InternalUtils.RunSingleInstance(MainProc, CommandLine);
            }
            catch (Exception Ex)
            {
                Log.WriteLine(TraceEventType.Error, "AutomationTool terminated with exception:");
                Log.WriteLine(TraceEventType.Error, LogUtils.FormatException(Ex));
                Log.WriteLine(TraceEventType.Error, Ex.Message);
                if (ReturnCode == 0)
                {
                    ReturnCode = (int)ErrorCodes.Error_Unknown;
                }
            }

            // Make sure there's no directiories on the stack.
            CommandUtils.ClearDirStack();
            Environment.ExitCode = ReturnCode;

            // Try to kill process before app domain exits to leave the other KillAll call to extreme edge cases
            if (ShouldKillProcesses && !Utils.IsRunningOnMono)
            {
                ProcessManager.KillAll();
            }

            Log.WriteLine(TraceEventType.Information, "AutomationTool exiting with ExitCode={0}", ReturnCode);
            LogUtils.CloseFileLogging();

            return(ReturnCode);
        }
예제 #9
0
        /// <summary>
        /// Compiles all script modules.
        /// </summary>
        /// <param name="Modules">Module project filenames.</param>
        private static void CompileModules(List <string> Modules)
        {
            string DependencyFile = Path.Combine(CommandUtils.CmdEnv.EngineSavedFolder, "UATModuleHashes.xml");

            if (AreDependenciesUpToDate(Modules, DependencyFile) && !GlobalCommandLine.IgnoreDependencies)
            {
                Log.TraceInformation("Dependencies are up to date. Skipping compile.");
                return;
            }

            Log.TraceInformation("Dependencies are out of date. Compiling scripts....");

            // clean old assemblies
            CleanupScriptsAssemblies();

            DateTime StartTime = DateTime.Now;

            string BuildTool = CommandUtils.CmdEnv.MsBuildExe;

            // msbuild (standard on windows, in mono >=5.0 is preferred due to speed and parallel compilation)
            bool UseParallelMsBuild = Path.GetFileNameWithoutExtension(BuildTool).ToLower() == "msbuild";

            if (UseParallelMsBuild)
            {
                string ModulesList = string.Join(";", Modules);

                // Mono has an issue where arugments with semicolons or commas can't be passed through to
                // as arguments so we need to manually construct a temp file with the list of modules
                // see (https://github.com/Microsoft/msbuild/issues/471)
                var UATProjTemplate = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, @"Engine\Source\Programs\AutomationTool\Scripts\UAT.proj");
                var UATProjFile     = Path.Combine(CommandUtils.CmdEnv.EngineSavedFolder, "UATTempProj.proj");

                string ProjContents = File.ReadAllText(UATProjTemplate);
                ProjContents = ProjContents.Replace("$(Modules)", ModulesList);

                Directory.CreateDirectory(Path.GetDirectoryName(UATProjFile));
                File.WriteAllText(UATProjFile, ProjContents);

                string MsBuildVerbosity = Log.OutputLevel >= LogEventType.Verbose ? "minimal" : "quiet";

                var CmdLine = String.Format("\"{0}\" /p:Configuration={1} /verbosity:{2} /nologo", UATProjFile, BuildConfig, MsBuildVerbosity);
                // suppress the run command because it can be long and intimidating, making the logs around this code harder to read.
                var Result = CommandUtils.Run(BuildTool, CmdLine, Options: CommandUtils.ERunOptions.Default | CommandUtils.ERunOptions.NoLoggingOfRunCommand | CommandUtils.ERunOptions.LoggingOfRunDuration);
                if (Result.ExitCode != 0)
                {
                    throw new AutomationException(String.Format("Failed to build \"{0}\":{1}{2}", UATProjFile, Environment.NewLine, Result.Output));
                }
            }
            else
            {
                // Make sure DefaultScriptsDLLName is compiled first
                var DefaultScriptsProjName = Path.ChangeExtension(DefaultScriptsDLLName, "csproj");

                // Primary modules must be built first
                List <string> PrimaryModules = Modules.Where(M => M.IndexOf(DefaultScriptsProjName, StringComparison.InvariantCultureIgnoreCase) >= 0).ToList();

                foreach (var ModuleName in PrimaryModules)
                {
                    Log.TraceInformation("Building script module: {0}", ModuleName);
                    try
                    {
                        CompileScriptModule(ModuleName);
                    }
                    catch (Exception Ex)
                    {
                        CommandUtils.LogError(LogUtils.FormatException(Ex));
                        throw new AutomationException("Failed to compile module {0}", ModuleName);
                    }
                    break;
                }

                // Second pass, compile everything else
                List <string> SecondaryModules = Modules.Where(M => !PrimaryModules.Contains(M)).ToList();

                // Non-parallel method
                foreach (var ModuleName in SecondaryModules)
                {
                    Log.TraceInformation("Building script module: {0}", ModuleName);
                    try
                    {
                        CompileScriptModule(ModuleName);
                    }
                    catch (Exception Ex)
                    {
                        CommandUtils.LogError(LogUtils.FormatException(Ex));
                        throw new AutomationException("Failed to compile module {0}", ModuleName);
                    }
                }
            }

            TimeSpan Duration = DateTime.Now - StartTime;

            Log.TraceInformation("Compiled {0} modules in {1} secs", Modules.Count, Duration.TotalSeconds);

            HashCollection NewHashes = HashModules(Modules);

            if (NewHashes == null)
            {
                Log.TraceWarning("Failed to save dependency info!");
            }
            else
            {
                NewHashes.SaveToFile(DependencyFile);
                Log.TraceVerbose("Wrote depencencies to {0}", DependencyFile);
            }
        }
예제 #10
0
        private void WriteJson(List <BuildNode> OrderedToDo, bool bSkipTriggers)
        {
            using (JsonWriter JsonWriter = new JsonWriter(CommandUtils.CombinePaths(CommandUtils.CmdEnv.LogFolder, "JobSteps.json")))
            {
                JsonWriter.WriteObjectStart();
                JsonWriter.WriteArrayStart("JobSteps");

                string CurrentAgentGroup = "";
                foreach (BuildNode NodeToDo in OrderedToDo)
                {
                    if (!NodeToDo.IsComplete)                     // if something is already finished, we don't put it into EC
                    {
                        // Write the agent group object
                        string AgentGroup = GetAgentGroupOrSticky(NodeToDo);
                        if (AgentGroup != CurrentAgentGroup)
                        {
                            if (CurrentAgentGroup != "")
                            {
                                JsonWriter.WriteArrayEnd();
                                JsonWriter.WriteObjectEnd();
                            }
                            CurrentAgentGroup = AgentGroup;
                            if (CurrentAgentGroup != "")
                            {
                                JsonWriter.WriteObjectStart();
                                JsonWriter.WriteValue("Group", AgentGroup);
                                JsonWriter.WriteValue("AgentPlatform", NodeToDo.AgentPlatform.ToString());
                                JsonWriter.WriteArrayStart("JobSteps");
                            }
                        }

                        // Add this node
                        JsonWriter.WriteObjectStart();
                        JsonWriter.WriteValue("Node", NodeToDo.Name);
                        if (CurrentAgentGroup == "")
                        {
                            JsonWriter.WriteValue("AgentPlatform", NodeToDo.AgentPlatform.ToString());
                        }
                        if (!String.IsNullOrEmpty(NodeToDo.AgentRequirements))
                        {
                            JsonWriter.WriteValue("AgentRequirements", NodeToDo.AgentRequirements);
                        }

                        // Write all the dependencies
                        StringBuilder DependsOnList = new StringBuilder();
                        foreach (BuildNode Dep in FindDirectOrderDependencies(NodeToDo))
                        {
                            if (!Dep.IsComplete && OrderedToDo.Contains(Dep))                             // if something is already finished, we don't put it into EC
                            {
                                if (OrderedToDo.IndexOf(Dep) > OrderedToDo.IndexOf(NodeToDo))
                                {
                                    throw new AutomationException("Topological sort error, node {0} has a dependency of {1} which sorted after it.", NodeToDo.Name, Dep.Name);
                                }
                                if (DependsOnList.Length > 0)
                                {
                                    DependsOnList.Append(";");
                                }
                                string DepAgentGroup = GetAgentGroupOrSticky(Dep);
                                if (DepAgentGroup != "")
                                {
                                    DependsOnList.AppendFormat("{0}/", DepAgentGroup);
                                }
                                DependsOnList.Append(Dep.Name);
                            }
                        }
                        JsonWriter.WriteValue("DependsOn", DependsOnList.ToString());

                        // Add any trigger-specific settings
                        TriggerNode TriggerNodeToDo = NodeToDo as TriggerNode;
                        if (TriggerNodeToDo != null && !TriggerNodeToDo.IsTriggered)
                        {
                            JsonWriter.WriteValue("TriggerState", TriggerNodeToDo.StateName);
                            JsonWriter.WriteValue("TriggerActionText", TriggerNodeToDo.ActionText);
                            JsonWriter.WriteValue("TriggerDescriptionText", TriggerNodeToDo.DescriptionText);
                            if (NodeToDo.RecipientsForFailureEmails.Length > 0)
                            {
                                JsonWriter.WriteValue("TriggerEmailRecipients", String.Join(" ", NodeToDo.RecipientsForFailureEmails));
                            }
                        }

                        JsonWriter.WriteObjectEnd();
                    }
                }
                if (CurrentAgentGroup != "")
                {
                    JsonWriter.WriteArrayEnd();
                    JsonWriter.WriteObjectEnd();
                }
                JsonWriter.WriteArrayEnd();
                JsonWriter.WriteObjectEnd();
            }
        }
        /// <summary>
        /// Execute the node
        /// </summary>
        /// <param name="BuildProducts">List of build products to run</param>
        /// <returns>True if the task succeeded</returns>
        public override bool Execute(List <string> BuildProducts)
        {
            if (Language == ScriptTaskLanguage.Batch)
            {
                // Write the script to a batch file
                string FileName = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Intermediate", "GUBP", "Temp.bat");
                CommandUtils.CreateDirectory(Path.GetDirectoryName(FileName));
                CommandUtils.WriteAllText(FileName, Text);

                // Run it through the command processor
                int ExitCode;
                CommandUtils.RunAndLog(Path.Combine(Environment.SystemDirectory, "cmd.exe"), "/Q /C " + CommandUtils.MakePathSafeToUseWithCommandLine(FileName), out ExitCode);
                return(ExitCode == 0);
            }
            else if (Language == ScriptTaskLanguage.CSharp)
            {
                // Build the full C# source file containing the given fragment. We assume it's a function body.
                StringBuilder FullScript = new StringBuilder();
                FullScript.AppendLine("using System;");
                FullScript.AppendLine("using System.IO;");
                FullScript.AppendLine("using System.Collections.Generic;");
                FullScript.AppendLine("using System.Linq;");
                FullScript.AppendLine("using AutomationTool;");
                FullScript.AppendLine();
                FullScript.AppendLine("public static class TaskHarness");
                FullScript.AppendLine("{");
                FullScript.AppendLine("\tpublic static void Execute()");
                FullScript.AppendLine("\t{");
                FullScript.AppendLine(Text);
                FullScript.AppendLine("\t}");
                FullScript.AppendLine("}");

                // Compile it into an in-memory assembly
                CompilerParameters Parameters = new CompilerParameters();
                Parameters.GenerateExecutable = false;
                Parameters.GenerateInMemory   = true;
                Parameters.ReferencedAssemblies.Add("mscorlib.dll");
                Parameters.ReferencedAssemblies.Add("System.dll");
                Parameters.ReferencedAssemblies.Add("System.Core.dll");
                Parameters.ReferencedAssemblies.Add("System.Data.Linq.dll");
                Parameters.ReferencedAssemblies.Add(typeof(CommandUtils).Assembly.Location);

                CSharpCodeProvider Compiler = new CSharpCodeProvider();
                CompilerResults    Results  = Compiler.CompileAssemblyFromSource(Parameters, FullScript.ToString());

                if (Results.Errors.HasErrors)
                {
                    throw new AutomationException("Failed to compile C# script:\n" + String.Join("\n", Results.Errors.OfType <CompilerError>().Select(x => x.ToString())));
                }

                // Execute the code
                Type CompiledType = Results.CompiledAssembly.GetType("TaskHarness");
                try
                {
                    CompiledType.GetMethod("Execute").Invoke(null, new object[0]);
                }
                catch (Exception Ex)
                {
                    throw new AutomationException(Ex, "Task script threw an exception.\n");
                }
                return(true);
            }
            else
            {
                throw new NotImplementedException(String.Format("Script language {0} has not been implemented", Language));
            }
        }
예제 #12
0
        /// <summary>
        /// Runs UBT with the specified commandline. Automatically creates a logfile. When
        /// no LogName is specified, the executable name is used as logfile base name.
        /// </summary>
        /// <param name="Env">Environment to use.</param>
        /// <param name="CommandLine">Commandline to pass on to UBT.</param>
        /// <param name="LogName">Optional logfile name.</param>
        public static void RunUBT(CommandEnvironment Env, string UBTExecutable, string CommandLine)
        {
            if (!FileExists(UBTExecutable))
            {
                throw new AutomationException("Unable to find UBT executable: " + UBTExecutable);
            }

            string BaseLogName = String.Format("UBT-{0}", String.Join("-", SharedUtils.ParseCommandLine(CommandLine).Where(x => !x.Contains('/') && !x.Contains('\\') && !x.StartsWith("-"))));
            string LogName;

            for (int Attempt = 1;; Attempt++)
            {
                LogName = String.Format("{0}.txt", (Attempt == 1)? BaseLogName : String.Format("{0}_{1}", BaseLogName, Attempt));

                FileReference LogLocation = FileReference.Combine(new DirectoryReference(Env.LogFolder), LogName);
                if (!FileReference.Exists(LogLocation))
                {
                    CommandLine += String.Format(" -log=\"{0}\"", LogLocation);
                    break;
                }

                if (Attempt >= 50)
                {
                    throw new AutomationException("Unable to find name for UBT log file after {0} attempts", Attempt);
                }
            }

            IProcessResult Result = Run(UBTExecutable, CommandLine, Options: ERunOptions.AllowSpew | ERunOptions.NoStdOutCapture);

            if (Result.ExitCode != 0)
            {
                throw new AutomationException((ExitCode)Result.ExitCode, "UnrealBuildTool failed. See log for more details. ({0})", CommandUtils.CombinePaths(Env.FinalLogFolder, LogName))
                      {
                          OutputFormat = AutomationExceptionOutputFormat.Minimal
                      };
            }
        }
예제 #13
0
        private static void FindAndCompileScriptModules(List <string> AdditionalScriptsFolders)
        {
            var OldCWD             = Environment.CurrentDirectory;
            var UnrealBuildToolCWD = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Source");

            // Convert script folders to be relative to UnrealBuildTool's expected CWD
            var RemappedAdditionalScriptFolders = new List <string>();

            foreach (var CurFolder in AdditionalScriptsFolders)
            {
                RemappedAdditionalScriptFolders.Add(UnrealBuildTool.Utils.MakePathRelativeTo(CurFolder, UnrealBuildToolCWD));
            }

            Environment.CurrentDirectory = UnrealBuildToolCWD;

            // Configure the rules compiler
            // Get all game folders and convert them to build subfolders.
            var AllGameFolders = UnrealBuildTool.UEBuildTarget.DiscoverAllGameFolders();
            var BuildFolders   = new List <string>(AllGameFolders.Count);

            foreach (var Folder in AllGameFolders)
            {
                var GameBuildFolder = CommandUtils.CombinePaths(Folder, "Build");
                if (Directory.Exists(GameBuildFolder))
                {
                    BuildFolders.Add(GameBuildFolder);
                }
            }
            RemappedAdditionalScriptFolders.AddRange(BuildFolders);

            Log.TraceVerbose("Discovering game folders.");
            UnrealBuildTool.RulesCompiler.SetAssemblyNameAndGameFolders("UnrealAutomationToolRules", AllGameFolders);

            var DiscoveredModules = UnrealBuildTool.RulesCompiler.FindAllRulesSourceFiles(UnrealBuildTool.RulesCompiler.RulesFileType.AutomationModule, RemappedAdditionalScriptFolders);
            var ModulesToCompile  = new List <string>(DiscoveredModules.Count);

            foreach (var ModuleFilename in DiscoveredModules)
            {
                if (HostPlatform.Current.IsScriptModuleSupported(CommandUtils.GetFilenameWithoutAnyExtensions(ModuleFilename)))
                {
                    ModulesToCompile.Add(ModuleFilename);
                }
                else
                {
                    CommandUtils.LogVerbose("Script module {0} filtered by the Host Platform and will not be compiled.", ModuleFilename);
                }
            }

            if ((UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealBuildTool.UnrealTargetPlatform.Win64) ||
                (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealBuildTool.UnrealTargetPlatform.Win32))
            {
                string Modules = string.Join(";", ModulesToCompile.ToArray());
                var    UATProj = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, @"Engine\Source\Programs\AutomationTool\Scripts\UAT.proj");
                var    CmdLine = String.Format("\"{0}\" /p:Modules=\"{1}\" /p:Configuration={2} /verbosity:minimal", UATProj, Modules, BuildConfig);
                Log.TraceInformation("Building Automation projects in parallel...");
                // supress the run command because it can be long and intimidating, making the logs around this code harder to read.
                var Result = CommandUtils.Run(CommandUtils.CmdEnv.MsBuildExe, CmdLine, Options: CommandUtils.ERunOptions.Default | CommandUtils.ERunOptions.NoLoggingOfRunCommand | CommandUtils.ERunOptions.LoggingOfRunDuration);
                if (Result.ExitCode != 0)
                {
                    throw new AutomationException(String.Format("Failed to build \"{0}\":{1}{2}", UATProj, Environment.NewLine, Result.Output));
                }
            }
            else
            {
                CompileModules(ModulesToCompile);
            }


            Environment.CurrentDirectory = OldCWD;
        }
예제 #14
0
        /// <summary>
        /// Entry point for the commandlet
        /// </summary>
        public override void ExecuteBuild()
        {
            string OutputDir = ParseParamValue("OutputDir");
            string ContentOnlyPlatformsString = ParseParamValue("ContentOnlyPlatforms");
            IEnumerable <UnrealTargetPlatform> ContentOnlyPlatforms = Enumerable.Empty <UnrealTargetPlatform>();

            if (!String.IsNullOrWhiteSpace(ContentOnlyPlatformsString))
            {
                ContentOnlyPlatforms = ContentOnlyPlatformsString.Split(';').Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => (UnrealTargetPlatform)Enum.Parse(typeof(UnrealTargetPlatform), x));
            }
            string AnalyticsTypeOverride = ParseParamValue("AnalyticsTypeOverride");

            // Write InstalledBuild.txt to indicate Engine is installed
            string InstalledBuildFile = CommandUtils.CombinePaths(OutputDir, "Engine/Build/InstalledBuild.txt");

            CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(InstalledBuildFile));
            CommandUtils.WriteAllText(InstalledBuildFile, "");

            // Write InstalledBuild.txt to indicate Engine is installed
            string Project = ParseParamValue("Project");

            if (Project != null)
            {
                string InstalledProjectBuildFile = CommandUtils.CombinePaths(OutputDir, "Engine/Build/InstalledProjectBuild.txt");
                CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(InstalledProjectBuildFile));
                CommandUtils.WriteAllText(InstalledProjectBuildFile, new FileReference(Project).MakeRelativeTo(new DirectoryReference(OutputDir)));
            }

            string         OutputEnginePath     = Path.Combine(OutputDir, "Engine");
            string         OutputBaseEnginePath = Path.Combine(OutputEnginePath, "Config", "BaseEngine.ini");
            FileAttributes OutputAttributes     = FileAttributes.ReadOnly;
            List <String>  IniLines             = new List <String>();

            // Should always exist but if not, we don't need extra line
            if (File.Exists(OutputBaseEnginePath))
            {
                OutputAttributes = File.GetAttributes(OutputBaseEnginePath);
                IniLines.Add("");
            }
            else
            {
                CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(OutputBaseEnginePath));
                CommandUtils.WriteAllText(OutputBaseEnginePath, "");
                OutputAttributes = File.GetAttributes(OutputBaseEnginePath) | OutputAttributes;
            }

            // Create list of platform configurations installed in a Rocket build
            List <InstalledPlatformInfo.InstalledPlatformConfiguration> InstalledConfigs = new List <InstalledPlatformInfo.InstalledPlatformConfiguration>();

            foreach (UnrealTargetPlatform CodeTargetPlatform in Enum.GetValues(typeof(UnrealTargetPlatform)))
            {
                if (PlatformExports.IsPlatformAvailable(CodeTargetPlatform))
                {
                    string Architecture = PlatformExports.GetDefaultArchitecture(CodeTargetPlatform, null);

                    // Try to parse additional Architectures from the command line
                    string Architectures    = ParseParamValue(CodeTargetPlatform.ToString() + "Architectures");
                    string GPUArchitectures = ParseParamValue(CodeTargetPlatform.ToString() + "GPUArchitectures");

                    // Build a list of pre-compiled architecture combinations for this platform if any
                    List <string> AllArchNames;

                    if (!String.IsNullOrWhiteSpace(Architectures) && !String.IsNullOrWhiteSpace(GPUArchitectures))
                    {
                        AllArchNames = (from Arch in Architectures.Split('+')
                                        from GPUArch in GPUArchitectures.Split('+')
                                        select "-" + Arch + "-" + GPUArch).ToList();
                    }
                    else if (!String.IsNullOrWhiteSpace(Architectures))
                    {
                        AllArchNames = Architectures.Split('+').ToList();
                    }
                    else
                    {
                        AllArchNames = new List <string>();
                    }

                    // Check whether this platform should only be used for content based projects
                    EProjectType ProjectType = ContentOnlyPlatforms.Contains(CodeTargetPlatform) ? EProjectType.Content : EProjectType.Any;

                    // Allow Content only platforms to be shown as options in all projects
                    bool bCanBeDisplayed = ProjectType == EProjectType.Content;
                    foreach (UnrealTargetConfiguration CodeTargetConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration)))
                    {
                        // Need to check for development receipt as we use that for the Engine code in DebugGame
                        UnrealTargetConfiguration EngineConfiguration = (CodeTargetConfiguration == UnrealTargetConfiguration.DebugGame) ? UnrealTargetConfiguration.Development : CodeTargetConfiguration;
                        string ReceiptFileName = TargetReceipt.GetDefaultPath(OutputEnginePath, "UE4Game", CodeTargetPlatform, EngineConfiguration, Architecture);

                        if (File.Exists(ReceiptFileName))
                        {
                            // Strip the output folder so that this can be used on any machine
                            ReceiptFileName = new FileReference(ReceiptFileName).MakeRelativeTo(new DirectoryReference(OutputDir));

                            // If we have pre-compiled architectures for this platform then add an entry for each of these -
                            // there isn't a receipt for each architecture like some other platforms
                            if (AllArchNames.Count > 0)
                            {
                                foreach (string Arch in AllArchNames)
                                {
                                    InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, TargetType.Game, Arch, ReceiptFileName, ProjectType, bCanBeDisplayed));
                                }
                            }
                            else
                            {
                                InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, TargetType.Game, Architecture, ReceiptFileName, ProjectType, bCanBeDisplayed));
                            }
                        }
                    }
                }
            }

            UnrealBuildTool.InstalledPlatformInfo.WriteConfigFileEntries(InstalledConfigs, ref IniLines);

            if (!String.IsNullOrEmpty(AnalyticsTypeOverride))
            {
                // Write Custom Analytics type setting
                IniLines.Add("");
                IniLines.Add("[Analytics]");
                IniLines.Add(String.Format("UE4TypeOverride=\"{0}\"", AnalyticsTypeOverride));
            }

            // Make sure we can write to the the config file
            File.SetAttributes(OutputBaseEnginePath, OutputAttributes & ~FileAttributes.ReadOnly);
            File.AppendAllLines(OutputBaseEnginePath, IniLines);
            File.SetAttributes(OutputBaseEnginePath, OutputAttributes);
        }
		/// <summary>
		/// Runs the task, filtering the list of build products
		/// </summary>
		/// <param name="BuildProducts"></param>
		/// <returns>True if the task succeeds</returns>
		public override bool Execute(List<string> BuildProducts)
		{
			if(AddFiles != null)
			{
				BuildProducts.AddRange(AddFiles.ApplyToDirectory(BaseDirectory, true).Select(x => CommandUtils.CombinePaths(BaseDirectory, x)));
			}
			if(FilterFiles != null)
			{
				BuildProducts.RemoveAll(x => UnrealBuildTool.Utils.IsFileUnderDirectory(x, BaseDirectory) && !FilterFiles.Matches(UnrealBuildTool.Utils.StripBaseDirectory(x, BaseDirectory)));
			}
			return true;
		}
예제 #16
0
        /// <summary>
        /// Attempts to autodetect project properties.
        /// </summary>
        /// <param name="RawProjectPath">Full project path.</param>
        /// <returns>Project properties.</returns>
        private static ProjectProperties DetectProjectProperties(string RawProjectPath)
        {
            var Properties = new ProjectProperties();

            Properties.RawProjectPath = RawProjectPath;

            if (CommandUtils.CmdEnv.HasCapabilityToCompile)
            {
                DetectTargetsForProject(Properties);
                Properties.bIsCodeBasedProject = !CommandUtils.IsNullOrEmpty(Properties.Targets) || !CommandUtils.IsNullOrEmpty(Properties.Programs);
            }
            else
            {
                // should never ask for engine targets if we can't compile
                if (String.IsNullOrEmpty(RawProjectPath))
                {
                    throw new AutomationException("Cannot dtermine engine targets if we can't compile.");
                }

                Properties.bIsCodeBasedProject = false;
                // if there's a Source directory with source code in it, then mark us as having source code
                string SourceDir = CommandUtils.CombinePaths(Path.GetDirectoryName(RawProjectPath), "Source");
                if (Directory.Exists(SourceDir))
                {
                    string[] CppFiles = Directory.GetFiles(SourceDir, "*.cpp", SearchOption.AllDirectories);
                    string[] HFiles   = Directory.GetFiles(SourceDir, "*.h", SearchOption.AllDirectories);
                    Properties.bIsCodeBasedProject = CppFiles.Length > 0 || HFiles.Length > 0;
                }
            }

            // check to see if the uproject loads modules, only if we haven't already determined it is a code based project
            if (!Properties.bIsCodeBasedProject)
            {
                string uprojectStr = File.ReadAllText(RawProjectPath);
                Properties.bIsCodeBasedProject = uprojectStr.Contains("\"Modules\"");
            }

            // Get all ini files
            if (!String.IsNullOrWhiteSpace(RawProjectPath))
            {
                CommandUtils.Log("Loading ini files for {0}", RawProjectPath);

                var EngineDirectory = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine");
                foreach (UnrealTargetPlatform TargetPlatformType in Enum.GetValues(typeof(UnrealTargetPlatform)))
                {
                    if (TargetPlatformType != UnrealTargetPlatform.Unknown)
                    {
                        var Config = new ConfigCacheIni(TargetPlatformType, "Engine", Path.GetDirectoryName(RawProjectPath), EngineDirectory);
                        Properties.EngineConfigs.Add(TargetPlatformType, Config);
                    }
                }

                foreach (UnrealTargetPlatform TargetPlatformType in Enum.GetValues(typeof(UnrealTargetPlatform)))
                {
                    if (TargetPlatformType != UnrealTargetPlatform.Unknown)
                    {
                        var Config = new ConfigCacheIni(TargetPlatformType, "Game", Path.GetDirectoryName(RawProjectPath));
                        Properties.GameConfigs.Add(TargetPlatformType, Config);
                    }
                }
            }

            return(Properties);
        }
예제 #17
0
        public void DoCommanderSetup(IEnumerable <BuildNode> AllNodes, IEnumerable <AggregateNode> AllAggregates, List <BuildNode> OrdereredToDo, List <BuildNode> SortedNodes, int TimeIndex, int TimeQuantum, bool bSkipTriggers, bool bFake, bool bFakeEC, string CLString, TriggerNode ExplicitTrigger, List <TriggerNode> UnfinishedTriggers, string FakeFail)
        {
            List <AggregateNode> SeparatePromotables = FindPromotables(AllAggregates);
            Dictionary <BuildNode, List <AggregateNode> > DependentPromotions = FindDependentPromotables(AllNodes, SeparatePromotables);

            Dictionary <BuildNode, int> FullNodeListSortKey = GetDisplayOrder(SortedNodes);

            if (OrdereredToDo.Count == 0)
            {
                throw new AutomationException("No nodes to do!");
            }
            List <string> ECProps = new List <string>();

            ECProps.Add(String.Format("TimeIndex={0}", TimeIndex));
            foreach (BuildNode Node in SortedNodes.Where(x => x.FrequencyShift != BuildNode.ExplicitFrequencyShift))
            {
                ECProps.Add(string.Format("AllNodes/{0}={1}", Node.Name, GetNodeForAllNodesProperty(Node, TimeQuantum)));
            }
            foreach (KeyValuePair <BuildNode, int> NodePair in FullNodeListSortKey.Where(x => x.Key.FrequencyShift != BuildNode.ExplicitFrequencyShift))
            {
                ECProps.Add(string.Format("SortKey/{0}={1}", NodePair.Key.Name, NodePair.Value));
            }
            foreach (KeyValuePair <BuildNode, List <AggregateNode> > NodePair in DependentPromotions)
            {
                ECProps.Add(string.Format("DependentPromotions/{0}={1}", NodePair.Key.Name, String.Join(" ", NodePair.Value.Select(x => x.Name))));
            }
            foreach (AggregateNode Node in SeparatePromotables)
            {
                ECProps.Add(string.Format("PossiblePromotables/{0}={1}", Node.Name, ""));
            }
            List <string> ECJobProps = new List <string>();

            if (ExplicitTrigger != null)
            {
                ECJobProps.Add("IsRoot=0");
            }
            else
            {
                ECJobProps.Add("IsRoot=1");
            }

            // here we are just making sure everything before the explicit trigger is completed.
            if (ExplicitTrigger != null)
            {
                foreach (BuildNode NodeToDo in OrdereredToDo)
                {
                    if (!NodeToDo.IsComplete && NodeToDo != ExplicitTrigger && !NodeToDo.DependsOn(ExplicitTrigger))                     // if something is already finished, we don't put it into EC
                    {
                        throw new AutomationException("We are being asked to process node {0}, however, this is an explicit trigger {1}, so everything before it should already be handled. It seems likely that you waited too long to run the trigger. You will have to do a new build from scratch.", NodeToDo.Name, ExplicitTrigger.Name);
                    }
                }
            }

            BuildNode     LastSticky   = null;
            bool          HitNonSticky = false;
            bool          bHaveECNodes = false;
            List <string> StepList     = new List <string>();

            StepList.Add("use strict;");
            StepList.Add("use diagnostics;");
            StepList.Add("use ElectricCommander();");
            StepList.Add("my $ec = new ElectricCommander;");
            StepList.Add("$ec->setTimeout(600);");
            StepList.Add("my $batch = $ec->newBatch(\"serial\");");
            // sticky nodes are ones that we run on the main agent. We run then first and they must not be intermixed with parallel jobs
            foreach (BuildNode NodeToDo in OrdereredToDo)
            {
                if (!NodeToDo.IsComplete)                 // if something is already finished, we don't put it into EC
                {
                    bHaveECNodes = true;
                    if (NodeToDo.IsSticky)
                    {
                        LastSticky = NodeToDo;
                        if (HitNonSticky && !bSkipTriggers)
                        {
                            throw new AutomationException("Sticky and non-sticky jobs did not sort right.");
                        }
                    }
                    else
                    {
                        HitNonSticky = true;
                    }
                }
            }

            using (CommandUtils.TelemetryStopwatch PerlOutputStopwatch = new CommandUtils.TelemetryStopwatch("PerlOutput"))
            {
                string ParentPath = Command.ParseParamValue("ParentPath");
                string BaseArgs   = String.Format("$batch->createJobStep({{parentPath => '{0}'", ParentPath);

                bool bHasNoop = false;
                if (LastSticky == null && bHaveECNodes)
                {
                    // if we don't have any sticky nodes and we have other nodes, we run a fake noop just to release the resource
                    string Args = String.Format("{0}, subprocedure => 'GUBP_UAT_Node', parallel => '0', jobStepName => 'Noop', actualParameter => [{{actualParameterName => 'NodeName', value => 'Noop'}}, {{actualParameterName => 'Sticky', value =>'1' }}], releaseMode => 'release'}});", BaseArgs);
                    StepList.Add(Args);
                    bHasNoop = true;
                }

                Dictionary <string, List <BuildNode> > AgentGroupChains = new Dictionary <string, List <BuildNode> >();
                List <BuildNode> StickyChain = new List <BuildNode>();
                foreach (BuildNode NodeToDo in OrdereredToDo)
                {
                    if (!NodeToDo.IsComplete)                     // if something is already finished, we don't put it into EC
                    {
                        string MyAgentGroup = NodeToDo.AgentSharingGroup;
                        if (MyAgentGroup != "")
                        {
                            if (!AgentGroupChains.ContainsKey(MyAgentGroup))
                            {
                                AgentGroupChains.Add(MyAgentGroup, new List <BuildNode> {
                                    NodeToDo
                                });
                            }
                            else
                            {
                                AgentGroupChains[MyAgentGroup].Add(NodeToDo);
                            }
                        }
                    }
                    if (NodeToDo.IsSticky)
                    {
                        if (!StickyChain.Contains(NodeToDo))
                        {
                            StickyChain.Add(NodeToDo);
                        }
                    }
                }
                foreach (BuildNode NodeToDo in OrdereredToDo)
                {
                    if (!NodeToDo.IsComplete)                     // if something is already finished, we don't put it into EC
                    {
                        List <string> NodeProps = GetECPropsForNode(NodeToDo);
                        ECProps.AddRange(NodeProps);

                        bool Sticky = NodeToDo.IsSticky;
                        if (NodeToDo.IsSticky)
                        {
                            if (NodeToDo.AgentSharingGroup != "")
                            {
                                throw new AutomationException("Node {0} is both agent sharing and sitcky.", NodeToDo.Name);
                            }
                            if (NodeToDo.AgentPlatform != UnrealTargetPlatform.Win64)
                            {
                                throw new AutomationException("Node {0} is sticky, but {1} hosted. Sticky nodes must be PC hosted.", NodeToDo.Name, NodeToDo.AgentPlatform);
                            }
                            if (NodeToDo.AgentRequirements != "")
                            {
                                throw new AutomationException("Node {0} is sticky but has agent requirements.", NodeToDo.Name);
                            }
                        }

                        string ProcedureInfix = "";
                        if (NodeToDo.AgentPlatform != UnrealTargetPlatform.Unknown && NodeToDo.AgentPlatform != UnrealTargetPlatform.Win64)
                        {
                            ProcedureInfix = "_" + NodeToDo.AgentPlatform.ToString();
                        }

                        bool DoParallel = !Sticky || NodeToDo.IsParallelAgentShareEditor;

                        TriggerNode TriggerNodeToDo = NodeToDo as TriggerNode;

                        List <Tuple <string, string> > Parameters = new List <Tuple <string, string> >();

                        Parameters.Add(new Tuple <string, string>("NodeName", NodeToDo.Name));
                        Parameters.Add(new Tuple <string, string>("Sticky", NodeToDo.IsSticky ? "1" : "0"));

                        if (NodeToDo.AgentSharingGroup != "")
                        {
                            Parameters.Add(new Tuple <string, string>("AgentSharingGroup", NodeToDo.AgentSharingGroup));
                        }

                        string Procedure;
                        if (TriggerNodeToDo == null || TriggerNodeToDo.IsTriggered)
                        {
                            if (NodeToDo.IsParallelAgentShareEditor)
                            {
                                Procedure = "GUBP_UAT_Node_Parallel_AgentShare_Editor";
                            }
                            else
                            {
                                Procedure = "GUBP" + ProcedureInfix + "_UAT_Node";
                                if (!NodeToDo.IsSticky)
                                {
                                    Procedure += "_Parallel";
                                }
                                if (NodeToDo.AgentSharingGroup != "")
                                {
                                    Procedure += "_AgentShare";
                                }
                            }
                            if (NodeToDo.IsSticky && NodeToDo == LastSticky)
                            {
                                Procedure += "_Release";
                            }
                        }
                        else
                        {
                            if (TriggerNodeToDo.RequiresRecursiveWorkflow)
                            {
                                Procedure = "GUBP_UAT_Trigger";                 //here we run a recursive workflow to wait for the trigger
                            }
                            else
                            {
                                Procedure = "GUBP_Hardcoded_Trigger";                                 //here we advance the state in the hardcoded workflow so folks can approve
                            }

                            Parameters.Add(new Tuple <string, string>("TriggerState", TriggerNodeToDo.StateName));
                            Parameters.Add(new Tuple <string, string>("ActionText", TriggerNodeToDo.ActionText));
                            Parameters.Add(new Tuple <string, string>("DescText", TriggerNodeToDo.DescriptionText));

                            if (NodeToDo.RecipientsForFailureEmails.Length > 0)
                            {
                                Parameters.Add(new Tuple <string, string>("EmailsForTrigger", String.Join(" ", NodeToDo.RecipientsForFailureEmails)));
                            }
                        }

                        string ActualParameterArgs = String.Join(", ", Parameters.Select(x => String.Format("{{actualParameterName => '{0}', value => '{1}'}}", x.Item1, x.Item2)));
                        string Args = String.Format("{0}, subprocedure => '{1}', parallel => '{2}', jobStepName => '{3}', actualParameter => [{4}]", BaseArgs, Procedure, DoParallel? 1 : 0, NodeToDo.Name, ActualParameterArgs);

                        List <BuildNode> UncompletedEcDeps = new List <BuildNode>();
                        {
                            foreach (BuildNode Dep in NodeToDo.AllDirectDependencies)
                            {
                                if (!Dep.IsComplete && OrdereredToDo.Contains(Dep))                                 // if something is already finished, we don't put it into EC
                                {
                                    if (OrdereredToDo.IndexOf(Dep) > OrdereredToDo.IndexOf(NodeToDo))
                                    {
                                        throw new AutomationException("Topological sort error, node {0} has a dependency of {1} which sorted after it.", NodeToDo.Name, Dep.Name);
                                    }
                                    UncompletedEcDeps.Add(Dep);
                                }
                            }
                        }

                        string PreCondition = GetPreConditionForNode(OrdereredToDo, ParentPath, bHasNoop, AgentGroupChains, StickyChain, NodeToDo, UncompletedEcDeps);
                        string RunCondition = GetRunConditionForNode(UncompletedEcDeps, ParentPath);

                        string MyAgentGroup          = NodeToDo.AgentSharingGroup;
                        bool   bDoNestedJobstep      = false;
                        bool   bDoFirstNestedJobstep = false;

                        string NodeParentPath = ParentPath;
                        if (MyAgentGroup != "")
                        {
                            bDoNestedJobstep = true;
                            NodeParentPath   = ParentPath + "/jobSteps[" + MyAgentGroup + "]";

                            List <BuildNode> MyChain = AgentGroupChains[MyAgentGroup];
                            int MyIndex = MyChain.IndexOf(NodeToDo);
                            if (MyIndex <= 0)
                            {
                                bDoFirstNestedJobstep = bDoNestedJobstep;
                            }
                        }

                        if (bDoNestedJobstep)
                        {
                            if (bDoFirstNestedJobstep)
                            {
                                {
                                    string NestArgs = String.Format("$batch->createJobStep({{parentPath => '{0}', jobStepName => '{1}', parallel => '1'",
                                                                    ParentPath, MyAgentGroup);
                                    if (!String.IsNullOrEmpty(PreCondition))
                                    {
                                        NestArgs = NestArgs + ", precondition => " + PreCondition;
                                    }
                                    NestArgs = NestArgs + "});";
                                    StepList.Add(NestArgs);
                                }
                                {
                                    string NestArgs = String.Format("$batch->createJobStep({{parentPath => '{0}/jobSteps[{1}]', jobStepName => '{2}_GetPool', subprocedure => 'GUBP{3}_AgentShare_GetPool', parallel => '1', actualParameter => [{{actualParameterName => 'AgentSharingGroup', value => '{4}'}}, {{actualParameterName => 'NodeName', value => '{5}'}}]",
                                                                    ParentPath, MyAgentGroup, MyAgentGroup, ProcedureInfix, MyAgentGroup, NodeToDo.Name);
                                    if (!String.IsNullOrEmpty(PreCondition))
                                    {
                                        NestArgs = NestArgs + ", precondition => " + PreCondition;
                                    }
                                    NestArgs = NestArgs + "});";
                                    StepList.Add(NestArgs);
                                }
                                {
                                    string NestArgs = String.Format("$batch->createJobStep({{parentPath => '{0}/jobSteps[{1}]', jobStepName => '{2}_GetAgent', subprocedure => 'GUBP{3}_AgentShare_GetAgent', parallel => '1', exclusiveMode => 'call', resourceName => '{4}', actualParameter => [{{actualParameterName => 'AgentSharingGroup', value => '{5}'}}, {{actualParameterName => 'NodeName', value=> '{6}'}}]",
                                                                    ParentPath, MyAgentGroup, MyAgentGroup, ProcedureInfix,
                                                                    String.Format("$[/myJob/jobSteps[{0}]/ResourcePool]", MyAgentGroup),
                                                                    MyAgentGroup, NodeToDo.Name);
                                    {
                                        NestArgs = NestArgs + ", precondition  => ";
                                        NestArgs = NestArgs + "\"\\$\" . \"[/javascript if(";
                                        NestArgs = NestArgs + "getProperty('" + ParentPath + "/jobSteps[" + MyAgentGroup + "]/jobSteps[" + MyAgentGroup + "_GetPool]/status') == 'completed'";
                                        NestArgs = NestArgs + ") true;]\"";
                                    }
                                    NestArgs = NestArgs + "});";
                                    StepList.Add(NestArgs);
                                }
                                {
                                    PreCondition = "\"\\$\" . \"[/javascript if(";
                                    PreCondition = PreCondition + "getProperty('" + ParentPath + "/jobSteps[" + MyAgentGroup + "]/jobSteps[" + MyAgentGroup + "_GetAgent]/status') == 'completed'";
                                    PreCondition = PreCondition + ") true;]\"";
                                }
                            }
                            Args = Args.Replace(String.Format("parentPath => '{0}'", ParentPath), String.Format("parentPath => '{0}'", NodeParentPath));
                            Args = Args.Replace("UAT_Node_Parallel_AgentShare", "UAT_Node_Parallel_AgentShare3");
                        }

                        if (!String.IsNullOrEmpty(PreCondition))
                        {
                            Args = Args + ", precondition => " + PreCondition;
                        }
                        if (!String.IsNullOrEmpty(RunCondition))
                        {
                            Args = Args + ", condition => " + RunCondition;
                        }
                #if false
                        // this doesn't work because it includes precondition time
                        if (GUBPNodes[NodeToDo].TimeoutInMinutes() > 0)
                        {
                            Args = Args + String.Format(" --timeLimitUnits minutes --timeLimit {0}", GUBPNodes[NodeToDo].TimeoutInMinutes());
                        }
                #endif
                        if (Sticky && NodeToDo == LastSticky)
                        {
                            Args = Args + ", releaseMode => 'release'";
                        }
                        Args = Args + "});";
                        StepList.Add(Args);

                        if (MyAgentGroup != "" && !bDoNestedJobstep)
                        {
                            List <BuildNode> MyChain = AgentGroupChains[MyAgentGroup];
                            int MyIndex = MyChain.IndexOf(NodeToDo);
                            if (MyIndex == MyChain.Count - 1)
                            {
                                string RelPreCondition = "\"\\$\" . \"[/javascript if(";
                                // this runs "parallel", but we a precondition to serialize it
                                RelPreCondition = RelPreCondition + "getProperty('" + ParentPath + "/jobSteps[" + NodeToDo.Name + "]/status') == 'completed'";
                                RelPreCondition = RelPreCondition + ") true;]\"";
                                // we need to release the resource
                                string RelArgs = String.Format("{0}, subprocedure => 'GUBP_Release_AgentShare', parallel => '1', jobStepName => 'Release_{1}', actualParameter => [{{actualParameterName => 'AgentSharingGroup', valued => '{2}'}}], releaseMode => 'release', precondition => '{3}'",
                                                               BaseArgs, MyAgentGroup, MyAgentGroup, RelPreCondition);
                                StepList.Add(RelArgs);
                            }
                        }
                    }
                }
                WriteECPerl(StepList);
            }
            bool bHasTests = OrdereredToDo.Any(x => x.Node.IsTest());
            RunECTool(String.Format("setProperty \"/myWorkflow/HasTests\" \"{0}\"", bHasTests));
            {
                ECProps.Add("GUBP_LoadedProps=1");
                string BranchDefFile = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LogFolder, "BranchDef.properties");
                CommandUtils.WriteAllLines(BranchDefFile, ECProps.ToArray());
                RunECTool(String.Format("setProperty \"/myWorkflow/BranchDefFile\" \"{0}\"", BranchDefFile.Replace("\\", "\\\\")));
            }
            {
                ECProps.Add("GUBP_LoadedJobProps=1");
                string BranchJobDefFile = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LogFolder, "BranchJobDef.properties");
                CommandUtils.WriteAllLines(BranchJobDefFile, ECProps.ToArray());
                RunECTool(String.Format("setProperty \"/myJob/BranchJobDefFile\" \"{0}\"", BranchJobDefFile.Replace("\\", "\\\\")));
            }
        }
예제 #18
0
        /// <summary>
        /// Detects the current code changelist the workspace is synced to.
        /// </summary>
        /// <param name="ClientRootPath">Workspace path.</param>
        /// <returns>Changelist number as a string.</returns>
        private static string DetectCurrentCodeCL(P4Connection Connection, string ClientRootPath)
        {
            CommandUtils.LogVerbose("uebp_CodeCL not set, detecting last code CL...");

            // Retrieve the current changelist
            string         P4Cmd    = String.Format("changes -m 1 \"{0}/....cpp#have\" \"{0}/....h#have\" \"{0}/....inl#have\" \"{0}/....cs#have\" \"{0}/....usf#have\"", CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath));
            IProcessResult P4Result = Connection.P4(P4Cmd, AllowSpew: false);

            // Loop through all the lines of the output. Even though we requested one result, we'll get one for each search pattern.
            int CL = 0;

            foreach (string Line in P4Result.Output.Split('\n'))
            {
                string[] Tokens = Line.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (Tokens.Length >= 2)
                {
                    int LineCL = Int32.Parse(Tokens[1]);
                    CL = Math.Max(CL, LineCL);
                }
            }
            return(CL.ToString());
        }
        /// <summary>
        /// Finds all targets for the project.
        /// </summary>
        /// <param name="Properties">Project properties.</param>
        /// <param name="ExtraSearchPaths">Additional search paths.</param>
        private static void DetectTargetsForProject(ProjectProperties Properties, List <string> ExtraSearchPaths = null)
        {
            Properties.Targets = new Dictionary <TargetType, SingleTargetProperties>();
            FileReference TargetsDllFilename;
            string        FullProjectPath = null;

            var GameFolders = new List <DirectoryReference>();
            var RulesFolder = new DirectoryReference(GetRulesAssemblyFolder());

            if (Properties.RawProjectPath != null)
            {
                CommandUtils.LogVerbose("Looking for targets for project {0}", Properties.RawProjectPath);

                TargetsDllFilename = FileReference.Combine(RulesFolder, String.Format("UATRules{0}.dll", Properties.RawProjectPath.GetHashCode()));

                FullProjectPath = CommandUtils.GetDirectoryName(Properties.RawProjectPath.FullName);
                GameFolders.Add(new DirectoryReference(FullProjectPath));
                CommandUtils.LogVerbose("Searching for target rule files in {0}", FullProjectPath);
            }
            else
            {
                TargetsDllFilename = FileReference.Combine(RulesFolder, String.Format("UATRules{0}.dll", "_BaseEngine_"));
            }

            // the UBT code assumes a certain CWD, but artists don't have this CWD.
            var  SourceDir = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Source");
            bool DirPushed = false;

            if (CommandUtils.DirectoryExists_NoExceptions(SourceDir))
            {
                CommandUtils.PushDir(SourceDir);
                DirPushed = true;
            }
            var ExtraSearchDirectories = (ExtraSearchPaths == null)? null : ExtraSearchPaths.Select(x => new DirectoryReference(x)).ToList();
            var TargetScripts          = RulesCompiler.FindAllRulesSourceFiles(RulesCompiler.RulesFileType.Target, GameFolders: GameFolders, ForeignPlugins: null, AdditionalSearchPaths: ExtraSearchDirectories, bIncludeEnterprise: false);

            if (DirPushed)
            {
                CommandUtils.PopDir();
            }

            if (!CommandUtils.IsNullOrEmpty(TargetScripts))
            {
                // We only care about project target script so filter out any scripts not in the project folder, or take them all if we are just doing engine stuff
                var ProjectTargetScripts = new List <FileReference>();
                foreach (var TargetScript in TargetScripts)
                {
                    if (FullProjectPath == null || TargetScript.IsUnderDirectory(new DirectoryReference(FullProjectPath)))
                    {
                        ProjectTargetScripts.Add(TargetScript);
                    }
                }
                TargetScripts = ProjectTargetScripts;
            }

            if (!CommandUtils.IsNullOrEmpty(TargetScripts))
            {
                CommandUtils.LogVerbose("Found {0} target rule files:", TargetScripts.Count);
                foreach (var Filename in TargetScripts)
                {
                    CommandUtils.LogVerbose("  {0}", Filename);
                }

                // Check if the scripts require compilation
                bool DoNotCompile = false;
                if (!CommandUtils.IsBuildMachine && !CheckIfScriptAssemblyIsOutOfDate(TargetsDllFilename, TargetScripts))
                {
                    Log.TraceVerbose("Targets DLL {0} is up to date.", TargetsDllFilename);
                    DoNotCompile = true;
                }
                if (!DoNotCompile && CommandUtils.FileExists_NoExceptions(TargetsDllFilename.FullName))
                {
                    if (!CommandUtils.DeleteFile_NoExceptions(TargetsDllFilename.FullName, true))
                    {
                        DoNotCompile = true;
                        CommandUtils.LogVerbose("Could not delete {0} assuming it is up to date and reusable for a recursive UAT call.", TargetsDllFilename);
                    }
                }

                CompileAndLoadTargetsAssembly(Properties, TargetsDllFilename, DoNotCompile, TargetScripts);
            }
        }
예제 #20
0
        /// <summary>
        /// Attempts to autodetect project properties.
        /// </summary>
        /// <param name="RawProjectPath">Full project path.</param>
        /// <returns>Project properties.</returns>
        private static ProjectProperties DetectProjectProperties(string RawProjectPath, List <UnrealTargetPlatform> ClientTargetPlatforms)
        {
            var Properties = new ProjectProperties();

            Properties.RawProjectPath = RawProjectPath;

            // detect if the project is content only, but has non-default build settings
            List <string> ExtraSearchPaths = null;

            if (!string.IsNullOrEmpty(RawProjectPath))
            {
                if (RequiresTempTarget(RawProjectPath, ClientTargetPlatforms))
                {
                    GenerateTempTarget(RawProjectPath);
                    Properties.bWasGenerated = true;
                    ExtraSearchPaths         = new List <string>();
                    ExtraSearchPaths.Add(CommandUtils.CombinePaths(Path.GetDirectoryName(RawProjectPath), "Intermediate", "Source"));
                }
                else if (File.Exists(Path.Combine(Path.GetDirectoryName(RawProjectPath), "Intermediate", "Source", Path.GetFileNameWithoutExtension(RawProjectPath) + ".Target.cs")))
                {
                    File.Delete(Path.Combine(Path.GetDirectoryName(RawProjectPath), "Intermediate", "Source", Path.GetFileNameWithoutExtension(RawProjectPath) + ".Target.cs"));
                }
            }

            if (CommandUtils.CmdEnv.HasCapabilityToCompile)
            {
                DetectTargetsForProject(Properties, ExtraSearchPaths);
                Properties.bIsCodeBasedProject = !CommandUtils.IsNullOrEmpty(Properties.Targets) || !CommandUtils.IsNullOrEmpty(Properties.Programs);
            }
            else
            {
                // should never ask for engine targets if we can't compile
                if (String.IsNullOrEmpty(RawProjectPath))
                {
                    throw new AutomationException("Cannot dtermine engine targets if we can't compile.");
                }

                Properties.bIsCodeBasedProject = Properties.bWasGenerated;
                // if there's a Source directory with source code in it, then mark us as having source code
                string SourceDir = CommandUtils.CombinePaths(Path.GetDirectoryName(RawProjectPath), "Source");
                if (Directory.Exists(SourceDir))
                {
                    string[] CppFiles = Directory.GetFiles(SourceDir, "*.cpp", SearchOption.AllDirectories);
                    string[] HFiles   = Directory.GetFiles(SourceDir, "*.h", SearchOption.AllDirectories);
                    Properties.bIsCodeBasedProject |= (CppFiles.Length > 0 || HFiles.Length > 0);
                }
            }

            // check to see if the uproject loads modules, only if we haven't already determined it is a code based project
            if (!Properties.bIsCodeBasedProject)
            {
                string uprojectStr = File.ReadAllText(RawProjectPath);
                Properties.bIsCodeBasedProject = uprojectStr.Contains("\"Modules\"");
            }

            // Get all ini files
            if (!String.IsNullOrWhiteSpace(RawProjectPath))
            {
                CommandUtils.Log("Loading ini files for {0}", RawProjectPath);

                var EngineDirectory = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine");
                foreach (UnrealTargetPlatform TargetPlatformType in Enum.GetValues(typeof(UnrealTargetPlatform)))
                {
                    if (TargetPlatformType != UnrealTargetPlatform.Unknown)
                    {
                        var Config = new ConfigCacheIni(TargetPlatformType, "Engine", Path.GetDirectoryName(RawProjectPath), EngineDirectory);
                        Properties.EngineConfigs.Add(TargetPlatformType, Config);
                    }
                }

                foreach (UnrealTargetPlatform TargetPlatformType in Enum.GetValues(typeof(UnrealTargetPlatform)))
                {
                    if (TargetPlatformType != UnrealTargetPlatform.Unknown)
                    {
                        var Config = new ConfigCacheIni(TargetPlatformType, "Game", Path.GetDirectoryName(RawProjectPath));
                        Properties.GameConfigs.Add(TargetPlatformType, Config);
                    }
                }
            }

            return(Properties);
        }
예제 #21
0
 public override string GetUE4ExePath(string UE4Exe)
 {
     return(CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, RelativeBinariesFolder, UE4Exe));
 }
예제 #22
0
        /// <summary>
        /// Finds all targets for the project.
        /// </summary>
        /// <param name="Properties">Project properties.</param>
        /// <param name="ExtraSearchPaths">Additional search paths.</param>
        private static void DetectTargetsForProject(ProjectProperties Properties, List <string> ExtraSearchPaths = null)
        {
            Properties.Targets = new Dictionary <TargetRules.TargetType, SingleTargetProperties>();
            string TargetsDllFilename;
            string FullProjectPath = null;

            var GameFolders = new List <string>();
            var RulesFolder = GetRulesAssemblyFolder();

            if (!String.IsNullOrEmpty(Properties.RawProjectPath))
            {
                CommandUtils.Log("Looking for targets for project {0}", Properties.RawProjectPath);

                TargetsDllFilename = CommandUtils.CombinePaths(RulesFolder, String.Format("UATRules{0}.dll", Properties.RawProjectPath.GetHashCode()));

                FullProjectPath = CommandUtils.GetDirectoryName(Properties.RawProjectPath);
                GameFolders.Add(FullProjectPath);
                CommandUtils.Log("Searching for target rule files in {0}", FullProjectPath);
            }
            else
            {
                TargetsDllFilename = CommandUtils.CombinePaths(RulesFolder, String.Format("UATRules{0}.dll", "_BaseEngine_"));
            }
            RulesCompiler.SetAssemblyNameAndGameFolders(TargetsDllFilename, GameFolders);

            // the UBT code assumes a certain CWD, but artists don't have this CWD.
            var  SourceDir = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Source");
            bool DirPushed = false;

            if (CommandUtils.DirectoryExists_NoExceptions(SourceDir))
            {
                CommandUtils.PushDir(SourceDir);
                DirPushed = true;
            }
            var TargetScripts = RulesCompiler.FindAllRulesSourceFiles(RulesCompiler.RulesFileType.Target, ExtraSearchPaths);

            if (DirPushed)
            {
                CommandUtils.PopDir();
            }

            if (!CommandUtils.IsNullOrEmpty(TargetScripts))
            {
                // We only care about project target script so filter out any scripts not in the project folder, or take them all if we are just doing engine stuff
                var ProjectTargetScripts = new List <string>();
                foreach (var Filename in TargetScripts)
                {
                    var FullScriptPath = CommandUtils.CombinePaths(Path.GetFullPath(Filename));
                    if (FullProjectPath == null || FullScriptPath.StartsWith(FullProjectPath, StringComparison.InvariantCultureIgnoreCase))
                    {
                        ProjectTargetScripts.Add(FullScriptPath);
                    }
                }
                TargetScripts = ProjectTargetScripts;
            }

            if (!CommandUtils.IsNullOrEmpty(TargetScripts))
            {
                CommandUtils.LogVerbose("Found {0} target rule files:", TargetScripts.Count);
                foreach (var Filename in TargetScripts)
                {
                    CommandUtils.LogVerbose("  {0}", Filename);
                }

                // Check if the scripts require compilation
                bool DoNotCompile = false;
                if (!CommandUtils.IsBuildMachine && !CheckIfScriptAssemblyIsOutOfDate(TargetsDllFilename, TargetScripts))
                {
                    Log.TraceInformation("Targets DLL {0} is up to date.", TargetsDllFilename);
                    DoNotCompile = true;
                }
                if (!DoNotCompile && CommandUtils.FileExists_NoExceptions(TargetsDllFilename))
                {
                    if (!CommandUtils.DeleteFile_NoExceptions(TargetsDllFilename, true))
                    {
                        DoNotCompile = true;
                        CommandUtils.Log("Could not delete {0} assuming it is up to date and reusable for a recursive UAT call.", TargetsDllFilename);
                    }
                }

                CompileAndLoadTargetsAssembly(Properties, TargetsDllFilename, DoNotCompile, TargetScripts);
            }
        }
예제 #23
0
 private static string GetScriptAssemblyFolder()
 {
     return(CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Binaries", "DotNET", "AutomationScripts"));
 }
예제 #24
0
        /// <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 void FindAndCompileAllScripts(string ScriptsForProjectFileName, List <string> AdditionalScriptsFolders)
        {
            bool DoCompile = false;

            if (GlobalCommandLine.Compile)
            {
                DoCompile = true;
            }

            // Change to Engine\Source (if exists) to properly discover all UBT classes
            var OldCWD             = Environment.CurrentDirectory;
            var UnrealBuildToolCWD = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Source");

            if (Directory.Exists(UnrealBuildToolCWD))
            {
                Environment.CurrentDirectory = UnrealBuildToolCWD;
            }
            // Register all the classes inside UBT
            Environment.CurrentDirectory = OldCWD;

            // Compile only if not disallowed.
            if (DoCompile && !String.IsNullOrEmpty(CommandUtils.CmdEnv.MsBuildExe))
            {
                CleanupScriptsAssemblies();
                FindAndCompileScriptModules(ScriptsForProjectFileName, AdditionalScriptsFolders);
            }

            var ScriptAssemblies = new List <Assembly>();

            LoadPreCompiledScriptAssemblies(ScriptAssemblies);

            // Setup platforms
            Platform.InitializePlatforms(ScriptAssemblies.ToArray());

            // Instantiate all the automation classes for interrogation
            Log.TraceVerbose("Creating commands.");
            ScriptCommands = new CaselessDictionary <Type>();
            foreach (var CompiledScripts in ScriptAssemblies)
            {
                try
                {
                    foreach (var ClassType in CompiledScripts.GetTypes())
                    {
                        if (ClassType.IsSubclassOf(typeof(BuildCommand)) && ClassType.IsAbstract == false)
                        {
                            if (ScriptCommands.ContainsKey(ClassType.Name) == false)
                            {
                                ScriptCommands.Add(ClassType.Name, ClassType);
                            }
                            else
                            {
                                Log.TraceWarning("Unable to add command {0} twice. Previous: {1}, Current: {2}", ClassType.Name,
                                                 ClassType.AssemblyQualifiedName, ScriptCommands[ClassType.Name].AssemblyQualifiedName);
                            }
                        }
                    }
                }
                catch (Exception Ex)
                {
                    throw new AutomationException("Failed to add commands from {0}. {1}", CompiledScripts, Ex);
                }
            }
        }
예제 #25
0
        /// <summary>
        /// Initializes the environment.
        /// </summary>
        internal CommandEnvironment()
        {
            // Get the path to the UAT executable
            UATExe = Assembly.GetEntryAssembly().GetOriginalLocation();
            if (!CommandUtils.FileExists(UATExe))
            {
                throw new AutomationException("Could not find AutomationTool.exe. Reflection indicated it was here: {0}", UATExe);
            }

            // Find the root directory (containing the Engine folder)
            LocalRoot = CommandUtils.GetEnvVar(EnvVarNames.LocalRoot);
            if (String.IsNullOrEmpty(LocalRoot))
            {
                LocalRoot = CommandUtils.ConvertSeparators(PathSeparator.Slash, Path.GetFullPath(Path.Combine(Path.GetDirectoryName(UATExe), "..", "..", "..")));
                CommandUtils.ConditionallySetEnvVar(EnvVarNames.LocalRoot, LocalRoot);
            }

            string SavedPath = CommandUtils.GetEnvVar(EnvVarNames.EngineSavedFolder);

            if (String.IsNullOrEmpty(SavedPath))
            {
                SavedPath = CommandUtils.CombinePaths(PathSeparator.Slash, LocalRoot, "Engine", "Programs", "AutomationTool", "Saved");
                CommandUtils.SetEnvVar(EnvVarNames.EngineSavedFolder, SavedPath);
            }

            EngineSavedFolder = CommandUtils.GetEnvVar(EnvVarNames.EngineSavedFolder);
            CSVFile           = CommandUtils.GetEnvVar(EnvVarNames.CSVFile);

            LogFolder = CommandUtils.GetEnvVar(EnvVarNames.LogFolder);
            if (String.IsNullOrEmpty(LogFolder))
            {
                if (GlobalCommandLine.Installed)
                {
                    LogFolder = GetInstalledLogFolder();
                }
                else
                {
                    LogFolder = CommandUtils.CombinePaths(PathSeparator.Slash, EngineSavedFolder, "Logs");
                }
                CommandUtils.SetEnvVar(EnvVarNames.LogFolder, LogFolder);
            }

            // clear the logfolder if we're the only running instance
            if (InternalUtils.IsSoleInstance)
            {
                ClearLogFolder(LogFolder);
            }

            FinalLogFolder = CommandUtils.GetEnvVar(EnvVarNames.FinalLogFolder);
            if (String.IsNullOrEmpty(FinalLogFolder))
            {
                FinalLogFolder = LogFolder;
                CommandUtils.SetEnvVar(EnvVarNames.FinalLogFolder, FinalLogFolder);
            }

            RobocopyExe    = GetSystemExePath("robocopy.exe");
            MountExe       = GetSystemExePath("mount.exe");
            CmdExe         = Utils.IsRunningOnMono ? "/bin/sh" : GetSystemExePath("cmd.exe");
            MallocNanoZone = "0";
            CommandUtils.SetEnvVar(EnvVarNames.MacMallocNanoZone, MallocNanoZone);

            int IsChildInstanceInt;

            int.TryParse(CommandUtils.GetEnvVar("uebp_UATChildInstance", "0"), out IsChildInstanceInt);
            IsChildInstance = (IsChildInstanceInt != 0);

            // Setup the timestamp string
            DateTime LocalTime = DateTime.Now;

            string TimeStamp = LocalTime.Year + "-"
                               + LocalTime.Month.ToString("00") + "-"
                               + LocalTime.Day.ToString("00") + "_"
                               + LocalTime.Hour.ToString("00") + "."
                               + LocalTime.Minute.ToString("00") + "."
                               + LocalTime.Second.ToString("00");

            TimestampAsString = TimeStamp;

            SetupBuildEnvironment();

            LogSettings();
        }
        /// <summary>
        /// Initializes the environement.
        /// </summary>
        protected virtual void InitEnvironment()
        {
            SetUATLocation();

            LocalRoot = CommandUtils.GetEnvVar(EnvVarNames.LocalRoot);
            if (String.IsNullOrEmpty(CommandUtils.GetEnvVar(EnvVarNames.EngineSavedFolder)))
            {
                SetUATSavedPath();
            }

            if (LocalRoot.EndsWith(":"))
            {
                LocalRoot += Path.DirectorySeparatorChar;
            }

            EngineSavedFolder = CommandUtils.GetEnvVar(EnvVarNames.EngineSavedFolder);
            CSVFile           = CommandUtils.GetEnvVar(EnvVarNames.CSVFile);
            LogFolder         = CommandUtils.GetEnvVar(EnvVarNames.LogFolder);
            RobocopyExe       = CommandUtils.CombinePaths(Environment.SystemDirectory, "robocopy.exe");
            MountExe          = CommandUtils.CombinePaths(Environment.SystemDirectory, "mount.exe");
            CmdExe            = Utils.IsRunningOnMono ? "/bin/sh" : CommandUtils.CombinePaths(Environment.SystemDirectory, "cmd.exe");

            if (String.IsNullOrEmpty(LogFolder))
            {
                throw new AutomationException("Environment is not set up correctly: LogFolder is not set!");
            }

            if (String.IsNullOrEmpty(LocalRoot))
            {
                throw new AutomationException("Environment is not set up correctly: LocalRoot is not set!");
            }

            if (String.IsNullOrEmpty(EngineSavedFolder))
            {
                throw new AutomationException("Environment is not set up correctly: EngineSavedFolder is not set!");
            }

            // Make sure that the log folder exists
            var LogFolderInfo = new DirectoryInfo(LogFolder);

            if (!LogFolderInfo.Exists)
            {
                LogFolderInfo.Create();
            }

            // Setup the timestamp string
            DateTime LocalTime = DateTime.Now;

            string TimeStamp = LocalTime.Year + "-"
                               + LocalTime.Month.ToString("00") + "-"
                               + LocalTime.Day.ToString("00") + "_"
                               + LocalTime.Hour.ToString("00") + "."
                               + LocalTime.Minute.ToString("00") + "."
                               + LocalTime.Second.ToString("00");

            TimestampAsString = TimeStamp;

            SetupBuildEnvironment();

            LogSettings();
        }