/// <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); } }
/// <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); }
/// <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)); } }
/// <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(); } } }
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); }
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); }