/// <summary>
        /// Creates a text file with the given contents.  If the contents of the text file aren't changed, it won't write the new contents to
        /// the file to avoid causing an action to be considered outdated.
        /// </summary>
        /// <param name="Location">Path to the intermediate file to create</param>
        /// <param name="Contents">Contents of the new file</param>
        /// <returns>File item for the newly created file</returns>
        public static FileItem CreateIntermediateTextFile(FileReference Location, string Contents)
        {
            // Only write the file if its contents have changed.
            if (!FileReference.Exists(Location))
            {
                DirectoryReference.CreateDirectory(Location.Directory);
                FileReference.WriteAllText(Location, Contents, GetEncodingForString(Contents));
            }
            else
            {
                string CurrentContents = Utils.ReadAllText(Location.FullName);
                if (!String.Equals(CurrentContents, Contents, StringComparison.InvariantCultureIgnoreCase))
                {
                    FileReference BackupFile = new FileReference(Location.FullName + ".old");
                    try
                    {
                        Log.TraceLog("Updating {0}: contents have changed. Saving previous version to {1}.", Location, BackupFile);
                        FileReference.Delete(BackupFile);
                        FileReference.Move(Location, BackupFile);
                    }
                    catch (Exception Ex)
                    {
                        Log.TraceWarning("Unable to rename {0} to {1}", Location, BackupFile);
                        Log.TraceLog("{0}", ExceptionUtils.FormatExceptionDetails(Ex));
                    }
                    FileReference.WriteAllText(Location, Contents, GetEncodingForString(Contents));
                }
            }

            // Reset the file info, in case it already knows about the old file
            FileItem Item = GetItemByFileReference(Location);

            Item.ResetCachedInfo();
            return(Item);
        }
        /// <summary>
        /// Reads data for this dependency cache from disk
        /// </summary>
        private void Read()
        {
            try
            {
                using (BinaryArchiveReader Reader = new BinaryArchiveReader(Location))
                {
                    int Version = Reader.ReadInt();
                    if (Version != CurrentVersion)
                    {
                        Log.TraceLog("Unable to read dependency cache from {0}; version {1} vs current {2}", Location, Version, CurrentVersion);
                        return;
                    }

                    int Count = Reader.ReadInt();
                    for (int Idx = 0; Idx < Count; Idx++)
                    {
                        FileItem File = Reader.ReadFileItem();
                        DependencyFileToInfo[File] = DependencyInfo.Read(Reader);
                    }
                }
            }
            catch (Exception Ex)
            {
                Log.TraceWarning("Unable to read {0}. See log for additional information.", Location);
                Log.TraceLog("{0}", ExceptionUtils.FormatExceptionDetails(Ex));
            }
        }
        /// <summary>
        /// Reads data for this dependency cache from disk
        /// </summary>
        private void Read()
        {
            try
            {
                using (BinaryArchiveReader Reader = new BinaryArchiveReader(Location))
                {
                    int Version = Reader.ReadInt();
                    if (Version != CurrentVersion)
                    {
                        Log.TraceLog("Unable to read dependency cache from {0}; version {1} vs current {2}", Location, Version, CurrentVersion);
                        return;
                    }

                    int FileToFirstIncludeCount = Reader.ReadInt();
                    for (int Idx = 0; Idx < FileToFirstIncludeCount; Idx++)
                    {
                        FileItem File = Reader.ReadCompactFileItem();

                        IncludeInfo IncludeInfo = new IncludeInfo();
                        IncludeInfo.LastWriteTimeUtc = Reader.ReadLong();
                        IncludeInfo.IncludeText      = Reader.ReadString();

                        FileToIncludeInfo[File] = IncludeInfo;
                    }

                    int FileToMarkupFlagCount = Reader.ReadInt();
                    for (int Idx = 0; Idx < FileToMarkupFlagCount; Idx++)
                    {
                        FileItem File = Reader.ReadCompactFileItem();

                        ReflectionInfo ReflectionInfo = new ReflectionInfo();
                        ReflectionInfo.LastWriteTimeUtc = Reader.ReadLong();
                        ReflectionInfo.bContainsMarkup  = Reader.ReadBool();

                        FileToReflectionInfo[File] = ReflectionInfo;
                    }
                }
            }
            catch (Exception Ex)
            {
                Log.TraceWarning("Unable to read {0}. See log for additional information.", Location);
                Log.TraceLog("{0}", ExceptionUtils.FormatExceptionDetails(Ex));
            }
        }
        /// <summary>
        /// Attempts to read the dependencies from the given input file
        /// </summary>
        /// <param name="InputFile">File to be read</param>
        /// <param name="OutDependencyItems">Receives a list of output items</param>
        /// <returns>True if the input file exists and the dependencies were read</returns>
        public bool TryGetDependencies(FileItem InputFile, out List <FileItem> OutDependencyItems)
        {
            if (!InputFile.Exists)
            {
                OutDependencyItems = null;
                return(false);
            }

            try
            {
                return(TryGetDependenciesInternal(InputFile, out OutDependencyItems));
            }
            catch (Exception Ex)
            {
                Log.TraceLog("Unable to read {0}:\n{1}", InputFile, ExceptionUtils.FormatExceptionDetails(Ex));
                OutDependencyItems = null;
                return(false);
            }
        }
示例#5
0
        /// <summary>
        /// Attempts to read a manifest from the given location
        /// </summary>
        /// <param name="ManifestFileName">Path to the manifest</param>
        /// <param name="Manifest">If successful, receives the manifest that was read</param>
        /// <returns>True if the manifest was read correctly, false otherwise</returns>
        public static bool TryReadManifest(FileReference ManifestFileName, out ModuleManifest Manifest)
        {
            if (FileReference.Exists(ManifestFileName))
            {
                try
                {
                    Manifest = ModuleManifest.Read(ManifestFileName);
                    return(true);
                }
                catch (Exception Ex)
                {
                    Log.TraceWarning("Unable to read '{0}'; ignoring.", ManifestFileName);
                    Log.TraceLog(ExceptionUtils.FormatExceptionDetails(Ex));
                }
            }

            Manifest = null;
            return(false);
        }
示例#6
0
        /// <summary>
        /// Attempts to load this action history from disk
        /// </summary>
        void Load()
        {
            try
            {
                using (BinaryArchiveReader Reader = new BinaryArchiveReader(Location))
                {
                    int Version = Reader.ReadInt();
                    if (Version != CurrentVersion)
                    {
                        Log.TraceLog("Unable to read action history from {0}; version {1} vs current {2}", Location, Version, CurrentVersion);
                        return;
                    }

                    OutputItemToAttributeHash = new ConcurrentDictionary <FileItem, byte[]>(Reader.ReadDictionary(() => Reader.ReadFileItem(), () => Reader.ReadFixedSizeByteArray(HashLength)));
                }
            }
            catch (Exception Ex)
            {
                Log.TraceWarning("Unable to read {0}. See log for additional information.", Location);
                Log.TraceLog("{0}", ExceptionUtils.FormatExceptionDetails(Ex));
            }
        }
示例#7
0
        /// <summary>
        /// Main entry point. Parses any global options and initializes the logging system, then invokes the appropriate command.
        /// </summary>
        /// <param name="ArgumentsArray">Command line arguments</param>
        /// <returns>Zero on success, non-zero on error</returns>
        private static int Main(string[] ArgumentsArray)
        {
            SingleInstanceMutex Mutex = null;

            try
            {
                // Start capturing performance info
                Timeline.Start();

                // Parse the command line arguments
                CommandLineArguments Arguments = new CommandLineArguments(ArgumentsArray);

                // Parse the global options
                GlobalOptions Options = new GlobalOptions(Arguments);

                // Configure the log system
                Log.OutputLevel       = Options.LogOutputLevel;
                Log.IncludeTimestamps = Options.bLogTimestamps;
                Log.IncludeProgramNameWithSeverityPrefix = Options.bLogFromMsBuild;

                // Configure the progress writer
                ProgressWriter.bWriteMarkup = Options.bWriteProgressMarkup;

                // Add the log writer if requested. When building a target, we'll create the writer for the default log file later.
                if (Options.LogFileName != null)
                {
                    Log.AddFileWriter("LogTraceListener", Options.LogFileName);
                }

                // Ensure we can resolve any external assemblies that are not in the same folder as our assembly.
                AssemblyUtils.InstallAssemblyResolver(Path.GetDirectoryName(Assembly.GetEntryAssembly().GetOriginalLocation()));

                // Change the working directory to be the Engine/Source folder. We are likely running from Engine/Binaries/DotNET
                // This is critical to be done early so any code that relies on the current directory being Engine/Source will work.
                DirectoryReference.SetCurrentDirectory(UnrealBuildTool.EngineSourceDirectory);

                // Get the type of the mode to execute, using a fast-path for the build mode.
                Type ModeType = typeof(BuildMode);
                if (Options.Mode != null)
                {
                    // Find all the valid modes
                    Dictionary <string, Type> ModeNameToType = new Dictionary <string, Type>(StringComparer.OrdinalIgnoreCase);
                    foreach (Type Type in Assembly.GetExecutingAssembly().GetTypes())
                    {
                        if (Type.IsClass && !Type.IsAbstract && Type.IsSubclassOf(typeof(ToolMode)))
                        {
                            ToolModeAttribute Attribute = Type.GetCustomAttribute <ToolModeAttribute>();
                            if (Attribute == null)
                            {
                                throw new BuildException("Class '{0}' should have a ToolModeAttribute", Type.Name);
                            }
                            ModeNameToType.Add(Attribute.Name, Type);
                        }
                    }

                    // Try to get the correct mode
                    if (!ModeNameToType.TryGetValue(Options.Mode, out ModeType))
                    {
                        Log.TraceError("No mode named '{0}'. Available modes are:\n  {1}", Options.Mode, String.Join("\n  ", ModeNameToType.Keys));
                        return(1);
                    }
                }

                // Get the options for which systems have to be initialized for this mode
                ToolModeOptions ModeOptions = ModeType.GetCustomAttribute <ToolModeAttribute>().Options;

                // Start prefetching the contents of the engine folder
                if ((ModeOptions & ToolModeOptions.StartPrefetchingEngine) != 0)
                {
                    using (Timeline.ScopeEvent("FileMetadataPrefetch.QueueEngineDirectory()"))
                    {
                        FileMetadataPrefetch.QueueEngineDirectory();
                    }
                }

                // Read the XML configuration files
                if ((ModeOptions & ToolModeOptions.XmlConfig) != 0)
                {
                    using (Timeline.ScopeEvent("XmlConfig.ReadConfigFiles()"))
                    {
                        string XmlConfigMutexName = SingleInstanceMutex.GetUniqueMutexForPath("UnrealBuildTool_Mutex_XmlConfig", Assembly.GetExecutingAssembly().CodeBase);
                        using (SingleInstanceMutex XmlConfigMutex = new SingleInstanceMutex(XmlConfigMutexName, true))
                        {
                            FileReference XmlConfigCache = Arguments.GetFileReferenceOrDefault("-XmlConfigCache=", null);
                            XmlConfig.ReadConfigFiles(XmlConfigCache);
                        }
                    }
                }

                // Acquire a lock for this branch
                if ((ModeOptions & ToolModeOptions.SingleInstance) != 0 && !Options.bNoMutex)
                {
                    using (Timeline.ScopeEvent("SingleInstanceMutex.Acquire()"))
                    {
                        string MutexName = SingleInstanceMutex.GetUniqueMutexForPath("UnrealBuildTool_Mutex", Assembly.GetExecutingAssembly().CodeBase);
                        Mutex = new SingleInstanceMutex(MutexName, Options.bWaitMutex);
                    }
                }

                // Register all the build platforms
                if ((ModeOptions & ToolModeOptions.BuildPlatforms) != 0)
                {
                    using (Timeline.ScopeEvent("UEBuildPlatform.RegisterPlatforms()"))
                    {
                        UEBuildPlatform.RegisterPlatforms(false);
                    }
                }
                if ((ModeOptions & ToolModeOptions.BuildPlatformsForValidation) != 0)
                {
                    using (Timeline.ScopeEvent("UEBuildPlatform.RegisterPlatforms()"))
                    {
                        UEBuildPlatform.RegisterPlatforms(true);
                    }
                }

                // Create the appropriate handler
                ToolMode Mode = (ToolMode)Activator.CreateInstance(ModeType);

                // Execute the mode
                int Result = Mode.Execute(Arguments);
                if ((ModeOptions & ToolModeOptions.ShowExecutionTime) != 0)
                {
                    Log.TraceInformation("Total execution time: {0:0.00} seconds", Timeline.Elapsed.TotalSeconds);
                }
                return(Result);
            }
            catch (CompilationResultException Ex)
            {
                // Used to return a propagate a specific exit code after an error has occurred. Does not log any message.
                Log.TraceLog(ExceptionUtils.FormatExceptionDetails(Ex));
                return((int)Ex.Result);
            }
            catch (BuildException Ex)
            {
                // BuildExceptions should have nicely formatted messages. We can log these directly.
                Log.TraceError(ExceptionUtils.FormatException(Ex));
                Log.TraceLog(ExceptionUtils.FormatExceptionDetails(Ex));
                return((int)CompilationResult.OtherCompilationError);
            }
            catch (Exception Ex)
            {
                // Unhandled exception.
                Log.TraceError("Unhandled exception: {0}", ExceptionUtils.FormatException(Ex));
                Log.TraceLog(ExceptionUtils.FormatExceptionDetails(Ex));
                return((int)CompilationResult.OtherCompilationError);
            }
            finally
            {
                // Cancel the prefetcher
                using (Timeline.ScopeEvent("FileMetadataPrefetch.Stop()"))
                {
                    FileMetadataPrefetch.Stop();
                }

                // Print out all the performance info
                Timeline.Print(TimeSpan.FromMilliseconds(20.0), LogEventType.Log);

                // Make sure we flush the logs however we exit
                Trace.Close();

                // Dispose of the mutex. Must be done last to ensure that another process does not startup and start trying to write to the same log file.
                if (Mutex != null)
                {
                    Mutex.Dispose();
                }
            }
        }
示例#8
0
        public static bool IsAvailable()
        {
            string XgConsoleExe;

            if (!TryGetXgConsoleExecutable(out XgConsoleExe))
            {
                return(false);
            }

            // on windows check the service is actually running
            if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64)
            {
                try
                {
                    // will throw if the service doesn't exist, which it should if IB is present but just incase...
                    System.ServiceProcess.ServiceController SC = new System.ServiceProcess.ServiceController("Incredibuild Agent");
                    if (SC.Status != System.ServiceProcess.ServiceControllerStatus.Running)
                    {
                        return(false);
                    }
                }
                catch (Exception Ex)
                {
                    Log.TraceLog("Unable to query for status of Incredibuild service: {0}", ExceptionUtils.FormatExceptionDetails(Ex));
                    return(false);
                }
            }

            // Check if we're connected over VPN
            if (!bAllowOverVpn && VpnSubnets != null && VpnSubnets.Length > 0)
            {
                string CoordinatorHost;
                if (TryGetCoordinatorHost(out CoordinatorHost) && IsHostOnVpn(CoordinatorHost))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#9
0
        public static bool IsHostOnVpn(string HostName)
        {
            // If there aren't any defined subnets, just early out
            if (VpnSubnets == null || VpnSubnets.Length == 0)
            {
                return(false);
            }

            // Parse all the subnets from the config file
            List <Subnet> ParsedVpnSubnets = new List <Subnet>();

            foreach (string VpnSubnet in VpnSubnets)
            {
                ParsedVpnSubnets.Add(Subnet.Parse(VpnSubnet));
            }

            // Check if any network adapters have an IP within one of these subnets
            try
            {
                NetworkInterface Interface = GetInterfaceForHost(HostName);
                if (Interface != null && Interface.OperationalStatus == OperationalStatus.Up)
                {
                    IPInterfaceProperties Properties = Interface.GetIPProperties();
                    foreach (UnicastIPAddressInformation UnicastAddressInfo in Properties.UnicastAddresses)
                    {
                        byte[] AddressBytes = UnicastAddressInfo.Address.GetAddressBytes();
                        foreach (Subnet Subnet in ParsedVpnSubnets)
                        {
                            if (Subnet.Contains(AddressBytes))
                            {
                                Log.TraceInformationOnce("XGE coordinator {0} will be not be used over VPN (adapter '{1}' with IP {2} is in subnet {3}). Set <XGE><bAllowOverVpn>true</bAllowOverVpn></XGE> in BuildConfiguration.xml to override.", HostName, Interface.Description, UnicastAddressInfo.Address, Subnet);
                                return(true);
                            }
                        }
                    }
                }
            }
            catch (Exception Ex)
            {
                Log.TraceWarning("Unable to check whether host {0} is connected to VPN:\n{1}", HostName, ExceptionUtils.FormatExceptionDetails(Ex));
            }
            return(false);
        }