/// <summary> /// Format an include of the given file /// </summary> /// <param name="FromDirectory">The directory containing the file with the #include directive</param> /// <param name="IncludeFile">File to include</param> /// <param name="IncludePaths">Directories to base relative include paths from</param> /// <param name="SystemIncludePaths">Directories to base system include paths from</param> /// <returns>Formatted include path, with surrounding quotes</returns> public static bool TryFormatInclude(DirectoryReference FromDirectory, FileReference IncludeFile, IEnumerable <DirectoryReference> IncludePaths, IEnumerable <DirectoryReference> SystemIncludePaths, out string IncludeText) { // Generated headers are always included without a path if (IncludeFile.FullName.Contains(".generated.") || IncludeFile.FullName.EndsWith("Classes.h")) { IncludeText = String.Format("\"{0}\"", IncludeFile.GetFileName()); return(true); } // Try to write an include relative to one of the system include paths foreach (DirectoryReference SystemIncludePath in SystemIncludePaths) { if (IncludeFile.IsUnderDirectory(SystemIncludePath)) { IncludeText = String.Format("<{0}>", IncludeFile.MakeRelativeTo(SystemIncludePath).Replace('\\', '/')); return(true); } } // Try to write an include relative to one of the standard include paths foreach (DirectoryReference IncludePath in IncludePaths) { if (IncludeFile.IsUnderDirectory(IncludePath)) { IncludeText = String.Format("\"{0}\"", IncludeFile.MakeRelativeTo(IncludePath).Replace('\\', '/')); return(true); } } // Try to write an include relative to the file if (IncludeFile.IsUnderDirectory(FromDirectory)) { IncludeText = String.Format("\"{0}\"", IncludeFile.MakeRelativeTo(FromDirectory).Replace('\\', '/')); return(true); } // HACK: VsPerf.h is in the compiler environment, but the include path is added directly if (IncludeFile.FullName.EndsWith("\\PerfSDK\\VSPerf.h", StringComparison.InvariantCultureIgnoreCase)) { IncludeText = "\"VSPerf.h\""; return(true); } // HACK: public Paper2D header in classes folder including private Paper2D header if (IncludeFile.FullName.IndexOf("\\Paper2D\\Private\\", StringComparison.InvariantCultureIgnoreCase) != -1) { IncludeText = "\"" + IncludeFile.GetFileName() + "\""; return(true); } if (IncludeFile.FullName.IndexOf("\\OnlineSubsystemUtils\\Private\\", StringComparison.InvariantCultureIgnoreCase) != -1) { IncludeText = "\"" + IncludeFile.GetFileName() + "\""; return(true); } // Otherwise we don't know where it came from IncludeText = null; return(false); }
static void PackagePlugin(FileReference SourcePluginFile, IEnumerable <FileReference> BuildProducts, DirectoryReference TargetDir, bool bUnversioned) { DirectoryReference SourcePluginDir = SourcePluginFile.Directory; // Copy all the files to the output directory FileReference[] SourceFiles = FilterPluginFiles(SourcePluginFile, BuildProducts).ToArray(); foreach (FileReference SourceFile in SourceFiles) { FileReference TargetFile = FileReference.Combine(TargetDir, SourceFile.MakeRelativeTo(SourcePluginDir)); CommandUtils.CopyFile(SourceFile.FullName, TargetFile.FullName); CommandUtils.SetFileAttributes(TargetFile.FullName, ReadOnly: false); } // Get the output plugin filename FileReference TargetPluginFile = FileReference.Combine(TargetDir, SourcePluginFile.GetFileName()); PluginDescriptor NewDescriptor = PluginDescriptor.FromFile(TargetPluginFile); NewDescriptor.bEnabledByDefault = null; NewDescriptor.bInstalled = true; if (!bUnversioned) { BuildVersion Version; if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version)) { NewDescriptor.EngineVersion = String.Format("{0}.{1}.0", Version.MajorVersion, Version.MinorVersion); } } NewDescriptor.Save(TargetPluginFile.FullName); }
UProjectInfo(FileReference InFilePath, bool bInIsCodeProject) { GameName = InFilePath.GetFileNameWithoutExtension(); FileName = InFilePath.GetFileName(); FilePath = InFilePath; Folder = FilePath.Directory; bIsCodeProject = bInIsCodeProject; }
/// <summary> /// Format an include of the given file /// </summary> /// <param name="FromDirectory">The directory containing the file with the #include directive</param> /// <param name="IncludeFile">File to include</param> /// <param name="IncludePaths">Directories to base relative include paths from</param> /// <param name="SystemIncludePaths">Directories to base system include paths from</param> /// <returns>Formatted include path, with surrounding quotes</returns> public static string FormatInclude(DirectoryReference FromDirectory, FileReference IncludeFile, IEnumerable <DirectoryReference> IncludePaths, IEnumerable <DirectoryReference> SystemIncludePaths, TextWriter Log) { string IncludeText; if (!TryFormatInclude(FromDirectory, IncludeFile, IncludePaths, SystemIncludePaths, out IncludeText)) { Log.WriteLine("warning: cannot create relative path for {0}; assuming <{1}>", IncludeFile.FullName, IncludeFile.GetFileName()); IncludeText = "<" + IncludeFile.GetFileName() + ">"; } return(IncludeText); }
/// <summary> /// Gets a WorkspaceFile object for the file at the given location. Throws an exception if the file does not exist. /// </summary> /// <param name="Location">Location of the file</param> /// <returns>The unique WorkspaceFile object for the given file</returns> public static WorkspaceFile GetFile(FileReference Location) { // Find the parent directory WorkspaceDirectory Directory = GetDirectory(Location.Directory); // Find the file within it WorkspaceFile Result; if (!Directory.TryGetFile(Location.GetFileName(), out Result)) { throw new DirectoryNotFoundException(String.Format("Couldn't find file {0}", Location.FullName)); } return(Result); }
FileReference CreateHostProject(FileReference HostProjectFile, FileReference PluginFile) { DirectoryReference HostProjectDir = HostProjectFile.Directory; DirectoryReference.CreateDirectory(HostProjectDir); // Create the new project descriptor File.WriteAllText(HostProjectFile.FullName, "{ \"FileVersion\": 3, \"Plugins\": [ { \"Name\": \"" + PluginFile.GetFileNameWithoutExtension() + "\", \"Enabled\": true } ] }"); // Get the plugin directory in the host project, and copy all the files in DirectoryReference HostProjectPluginDir = DirectoryReference.Combine(HostProjectDir, "Plugins", PluginFile.GetFileNameWithoutExtension()); CommandUtils.ThreadedCopyFiles(PluginFile.Directory.FullName, HostProjectPluginDir.FullName); CommandUtils.DeleteDirectory(true, DirectoryReference.Combine(HostProjectPluginDir, "Intermediate").FullName); // Return the path to the plugin file in the host project return(FileReference.Combine(HostProjectPluginDir, PluginFile.GetFileName())); }
/// <summary> /// Determine the compiler type /// </summary> /// <param name="Compiler">Path to the compiler</param> /// <param name="CompilerType">Type of the compiler</param> /// <returns>True if the path is a valid known compiler, and CompilerType is set</returns> static bool GetCompilerType(FileReference Compiler, out CompilerType CompilerType) { string FileName = Compiler.GetFileName().ToLowerInvariant(); if (FileName == "cl.exe") { CompilerType = CompilerType.VisualC; return(true); } else if (FileName == "clang++.exe") { CompilerType = CompilerType.Clang; return(true); } else { CompilerType = CompilerType.Unknown; return(false); } }
static void PackagePlugin(FileReference SourcePluginFile, IEnumerable <FileReference> BuildProducts, DirectoryReference TargetDir) { DirectoryReference SourcePluginDir = SourcePluginFile.Directory; // Copy all the files to the output directory FileReference[] SourceFiles = FilterPluginFiles(SourcePluginFile, BuildProducts).ToArray(); foreach (FileReference SourceFile in SourceFiles) { FileReference TargetFile = FileReference.Combine(TargetDir, SourceFile.MakeRelativeTo(SourcePluginDir)); CommandUtils.CopyFile(SourceFile.FullName, TargetFile.FullName); CommandUtils.SetFileAttributes(TargetFile.FullName, ReadOnly: false); } // Get the output plugin filename FileReference TargetPluginFile = FileReference.Combine(TargetDir, SourcePluginFile.GetFileName()); PluginDescriptor NewDescriptor = PluginDescriptor.FromFile(TargetPluginFile, false); NewDescriptor.bEnabledByDefault = true; NewDescriptor.bInstalled = true; NewDescriptor.Save(TargetPluginFile.FullName, false); }
public override void ExecuteBuild() { // Get the plugin filename string PluginParam = ParseParamValue("Plugin"); if (PluginParam == null) { throw new AutomationException("Plugin file name was not specified via the -plugin argument"); } // Read the plugin FileReference PluginFile = new FileReference(PluginParam); DirectoryReference PluginDirectory = PluginFile.Directory; PluginDescriptor Plugin = PluginDescriptor.FromFile(PluginFile); // Clean the intermediate build directory DirectoryReference IntermediateBuildDirectory = DirectoryReference.Combine(PluginDirectory, "Intermediate", "Build"); if (CommandUtils.DirectoryExists(IntermediateBuildDirectory.FullName)) { CommandUtils.DeleteDirectory(IntermediateBuildDirectory.FullName); } // Create a host project for the plugin. For script generator plugins, we need to have UHT be able to load it - and that can only happen if it's enabled in a project. DirectoryReference HostProjectDirectory = DirectoryReference.Combine(new DirectoryReference(CommandUtils.CmdEnv.LocalRoot), "HostProject"); if (CommandUtils.DirectoryExists(HostProjectDirectory.FullName)) { CommandUtils.DeleteDirectory(HostProjectDirectory.FullName); } DirectoryReference HostProjectPluginDirectory = DirectoryReference.Combine(HostProjectDirectory, "Plugins", PluginFile.GetFileNameWithoutExtension()); string[] CopyPluginFiles = Directory.EnumerateFiles(PluginDirectory.FullName, "*", SearchOption.AllDirectories).ToArray(); foreach (string CopyPluginFile in CopyPluginFiles) { CommandUtils.CopyFile(CopyPluginFile, CommandUtils.MakeRerootedFilePath(CopyPluginFile, PluginDirectory.FullName, HostProjectPluginDirectory.FullName)); } FileReference HostProjectPluginFile = FileReference.Combine(HostProjectPluginDirectory, PluginFile.GetFileName()); FileReference HostProjectFile = FileReference.Combine(HostProjectDirectory, "HostProject.uproject"); File.WriteAllText(HostProjectFile.FullName, "{ \"FileVersion\": 3, \"Plugins\": [ { \"Name\": \"" + PluginFile.GetFileNameWithoutExtension() + "\", \"Enabled\": true } ] }"); // Get any additional arguments from the commandline string AdditionalArgs = ""; // Build the host platforms List <string> ReceiptFileNames = new List <string>(); UnrealTargetPlatform HostPlatform = BuildHostPlatform.Current.Platform; if (!ParseParam("NoHostPlatform")) { if (Plugin.bCanBeUsedWithUnrealHeaderTool) { BuildPluginWithUBT(PluginFile, Plugin, null, "UnrealHeaderTool", TargetRules.TargetType.Program, HostPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, String.Format("{0} -plugin {1}", AdditionalArgs, CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName))); } BuildPluginWithUBT(PluginFile, Plugin, HostProjectFile, "UE4Editor", TargetRules.TargetType.Editor, HostPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, AdditionalArgs); } // Add the game targets List <UnrealTargetPlatform> TargetPlatforms = Rocket.RocketBuild.GetTargetPlatforms(this, HostPlatform); foreach (UnrealTargetPlatform TargetPlatform in TargetPlatforms) { if (Rocket.RocketBuild.IsCodeTargetPlatform(HostPlatform, TargetPlatform)) { BuildPluginWithUBT(PluginFile, Plugin, HostProjectFile, "UE4Game", TargetRules.TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, AdditionalArgs); BuildPluginWithUBT(PluginFile, Plugin, HostProjectFile, "UE4Game", TargetRules.TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Shipping, ReceiptFileNames, AdditionalArgs); } } // Package the plugin to the output folder string PackageDirectory = ParseParamValue("Package"); if (PackageDirectory != null) { List <BuildProduct> BuildProducts = GetBuildProductsFromReceipts(UnrealBuildTool.UnrealBuildTool.EngineDirectory, HostProjectDirectory, ReceiptFileNames); PackagePlugin(HostProjectPluginFile, BuildProducts, PackageDirectory); } }
/// <summary> /// Constructor /// </summary> /// <param name="Type">The type of probe to create</param> /// <param name="Node">The node to optimize</param> /// <param name="IntermediateDir">Directory for intermediate files</param> /// <param name="UniqueName">Unique name prefix for all temporary files</param> public SequenceProbe(SequenceProbeType Type, SourceFragment[] Fragments, Tuple <int, SourceFile>[] IncludeHistory, CompileEnvironment CompileEnvironment, DirectoryReference IntermediateDir, IEnumerable <DirectoryReference> ExtraSystemIncludePaths, string UniqueName) { this.Type = Type; this.IntermediateDir = IntermediateDir; this.Fragments = Fragments; this.LastFragment = Fragments[Fragments.Length - 1]; this.UniqueName = UniqueName; this.TaskStateFile = FileReference.Combine(IntermediateDir, UniqueName + ((Type == SequenceProbeType.Verify)? ".verify.state" : ".state")); this.SummaryLogFile = FileReference.Combine(IntermediateDir, UniqueName + ".summary.txt"); this.CompileLogFile = FileReference.Combine(IntermediateDir, UniqueName + ".compile.txt"); // Get the file to use for trying to compile different permutations FileReference PermutationFile = FileReference.Combine(IntermediateDir, UniqueName + ".permutation"); // Create the response file FileReference ResponseFile = FileReference.Combine(IntermediateDir, UniqueName + ".response"); CompileEnvironment WorkerCompileEnvironment = new CompileEnvironment(CompileEnvironment); if (WorkerCompileEnvironment.CompilerType == CompilerType.Clang) { WorkerCompileEnvironment.Options.Add(new CompileOption("-o", FileReference.Combine(IntermediateDir, UniqueName + ".o").FullName.Replace('\\', '/'))); } else { WorkerCompileEnvironment.Options.RemoveAll(x => x.Name == "/Z7" || x.Name == "/Zi" || x.Name == "/ZI"); WorkerCompileEnvironment.Options.Add(new CompileOption("/Fo", FileReference.Combine(IntermediateDir, UniqueName + ".obj").FullName)); WorkerCompileEnvironment.Options.Add(new CompileOption("/WX", null)); } WorkerCompileEnvironment.WriteResponseFile(ResponseFile, PermutationFile); string ResponseFileDigest = Utility.ComputeDigest(ResponseFile); // Keep track of the include stack, so we can format the flat fragment list with context int IncludeHistoryIdx = 0; List <SourceFile> IncludeStack = new List <SourceFile>(); // Create the script for the probe List <Tuple <int, string> > Lines = new List <Tuple <int, string> >(); for (int Idx = 0; Idx < Fragments.Length; Idx++) { SourceFragment Fragment = Fragments[Idx]; // Figure out which tag it's bound to int Tag = (Fragment.File.Counterpart == null)? Idx : -1; // Update the stack for new includes while (IncludeHistoryIdx < IncludeHistory.Length && IncludeHistory[IncludeHistoryIdx].Item1 == Idx) { if (IncludeHistory[IncludeHistoryIdx].Item2 == null) { SourceFile IncludeFile = IncludeStack[IncludeStack.Count - 1]; IncludeStack.RemoveAt(IncludeStack.Count - 1); Lines.Add(new Tuple <int, string>(Tag, String.Format("{0}// END INCLUDE {1}", new string(' ', IncludeStack.Count * 4), IncludeFile.Location.FullName))); IncludeHistoryIdx++; } else if (IncludeHistoryIdx + 1 < IncludeHistory.Length && IncludeHistory[IncludeHistoryIdx + 1].Item2 == null) { IncludeHistoryIdx += 2; } else { SourceFile IncludeFile = IncludeHistory[IncludeHistoryIdx].Item2; Lines.Add(new Tuple <int, string>(Tag, String.Format("{0}// INCLUDE {1}", new string(' ', IncludeStack.Count * 4), IncludeFile.Location.FullName))); IncludeStack.Add(IncludeFile); IncludeHistoryIdx++; } } // Get the indent at this point string Indent = new string(' ', (IncludeStack.Count - 0) * 4); // Write out the forward declarations for every symbol referenced in this fragment. We don't want false dependencies caused by forward declarations in other fragments // if the heuristic for detecting when to use them doesn't work. if ((Fragment.File.Flags & SourceFileFlags.TranslationUnit) == 0) { foreach (KeyValuePair <Symbol, SymbolReferenceType> ReferencedSymbol in Fragment.ReferencedSymbols) { if (!String.IsNullOrEmpty(ReferencedSymbol.Key.ForwardDeclaration)) { Lines.Add(Tuple.Create(Tag, Indent + ReferencedSymbol.Key.ForwardDeclaration)); } } } // Some Clang/GCC system header wrappers require including as system includes in order to make the #include_next directive work DirectoryReference BaseSystemIncludePath = ExtraSystemIncludePaths.FirstOrDefault(x => Fragment.Location.IsUnderDirectory(x)); if (BaseSystemIncludePath != null) { Lines.Add(Tuple.Create(Tag, String.Format("{0}#include <{1}>", Indent, Fragment.Location.MakeRelativeTo(BaseSystemIncludePath)))); } else { Lines.Add(Tuple.Create(Tag, String.Format("{0}#include \"{1}\"", Indent, Fragment.Location.FullName))); } } // Create the new task string[] FragmentFileNames = Fragments.Select(Fragment => Fragment.Location.FullName).ToArray(); string[] FragmentDigests = Fragments.Select(Fragment => Fragment.Digest ?? "").ToArray(); Worker = new SequenceWorker(PermutationFile.FullName, ResponseFile.FullName, ResponseFileDigest, FragmentFileNames, FragmentDigests, Lines.ToArray(), CompileEnvironment.Compiler.FullName); AddDependency(Worker, Fragments, Fragments.Length - 1); // Log the referenced symbols if (LastFragment.ReferencedSymbols.Count > 0) { List <string> ReferenceLog = new List <string>(); ReferenceLog.Add(String.Format("Referenced symbols for {0}:", LastFragment.Location)); foreach (KeyValuePair <Symbol, SymbolReferenceType> Pair in LastFragment.ReferencedSymbols.OrderBy(x => x.Key.Type).ThenBy(x => x.Key.Name)) { Symbol ReferencedSymbol = Pair.Key; ReferenceLog.Add(String.Format(" {0}: {1} ({2}; {3})", ReferencedSymbol.Type.ToString(), ReferencedSymbol.Name, Pair.Value.ToString(), ReferencedSymbol.Fragment.Location)); } ReferenceLog.Add(""); Worker.SummaryLog.InsertRange(0, ReferenceLog); } // Check to see if an existing version of the task exists which we can continue if (Type == SequenceProbeType.Optimize && TaskStateFile.Exists()) { // Try to read the old task SequenceWorker OldWorker; try { OldWorker = SequenceWorker.Deserialize(TaskStateFile.FullName); } catch (Exception) { OldWorker = null; } // If it succeeded, compare it to the new task if (OldWorker != null) { SequenceWorker NewWorker = Worker; // Create a list of fragments which can be ignored, because they're already determined to be not part of the result for the old task HashSet <string> IgnoreFragments = new HashSet <string>(); for (int Idx = 0; Idx < OldWorker.FragmentCount; Idx++) { if (!OldWorker.KnownDependencies.Contains(Idx) && Idx >= OldWorker.RemainingFragmentCount) { IgnoreFragments.Add(OldWorker.FragmentFileNames[Idx]); } } IgnoreFragments.ExceptWith(NewWorker.KnownDependencies.Select(x => NewWorker.FragmentFileNames[x])); // Compute digests for the old and new tasks string OldDigest = CreateDigest(OldWorker, IgnoreFragments); string NewDigest = CreateDigest(NewWorker, IgnoreFragments); if (OldDigest == NewDigest) { // Build a map of fragment file names to their new index Dictionary <string, int> FragmentFileNameToNewIndex = new Dictionary <string, int>(); for (int Idx = 0; Idx < FragmentFileNames.Length; Idx++) { string FragmentFileName = FragmentFileNames[Idx]; FragmentFileNameToNewIndex[FragmentFileName] = Idx; } // Add known dependencies to the new worker foreach (int OldKnownDependency in OldWorker.KnownDependencies) { string OldFragmentFileName = OldWorker.FragmentFileNames[OldKnownDependency]; int NewKnownDependency = FragmentFileNameToNewIndex[OldFragmentFileName]; NewWorker.KnownDependencies.Add(NewKnownDependency); } // Update the remaining count. All these fragments must match, because they're not part of the ignore list. NewWorker.RemainingFragmentCount = OldWorker.RemainingFragmentCount; } } } // If this is a cpp file, make sure we have a dependency on the header file with the same name. It may specify linkage for the functions we declare. FileReference MainFileLocation = Fragments[Fragments.Length - 1].File.Location; if (MainFileLocation.HasExtension(".cpp")) { string HeaderFileName = Path.ChangeExtension(MainFileLocation.GetFileName(), ".h"); for (int FragmentIdx = 0; FragmentIdx < Fragments.Length; FragmentIdx++) { if (String.Compare(Fragments[FragmentIdx].File.Location.GetFileName(), HeaderFileName, true) == 0) { AddDependency(Worker, Fragments, FragmentIdx); } } } // Update the finished fragment if we're done, otherwise clear out all the intermediate files if (Worker.RemainingFragmentCount == 0) { SetCompletedDependencies(); } else { Worker.Serialize(TaskStateFile.FullName); PermutationFile.Delete(); SummaryLogFile.Delete(); CompileLogFile.Delete(); } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // if (UnrealBuildTool.BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { // copy the icons/launch screens from the engine { DirectoryReference SourcePath = DirectoryReference.Combine(SC.LocalRoot, "Engine", "Binaries", "TVOS", "AssetCatalog"); SC.StageFiles(StagedFileType.NonUFS, SourcePath, "Assets.car", false, null, StagedDirectoryReference.Root, true, false); } // copy any additional framework assets that will be needed at runtime { DirectoryReference SourcePath = DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Intermediate", "TVOS", "FrameworkAssets"); if (DirectoryReference.Exists(SourcePath)) { SC.StageFiles(StagedFileType.NonUFS, SourcePath, "*.*", true, null, StagedDirectoryReference.Root, true, false); } } // copy the icons/launch screens from the game (may stomp the engine copies) { DirectoryReference SourcePath = DirectoryReference.Combine(SC.ProjectRoot, "Binaries", "TVOS", "AssetCatalog"); SC.StageFiles(StagedFileType.NonUFS, SourcePath, "Assets.car", false, null, StagedDirectoryReference.Root, true, false); } // copy the plist (only if code signing, as it's protected by the code sign blob in the executable and can't be modified independently) if (GetCodeSignDesirability(Params)) { DirectoryReference SourcePath = DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Intermediate", "TVOS"); FileReference TargetPListFile = FileReference.Combine(SourcePath, (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game") + "-Info.plist"); // if (!File.Exists(TargetPListFile)) { // ensure the plist, entitlements, and provision files are properly copied Console.WriteLine("CookPlat {0}, this {1}", GetCookPlatform(false, false), ToString()); if (!SC.IsCodeBasedProject) { UnrealBuildTool.PlatformExports.SetRemoteIniPath(SC.ProjectRoot.FullName); } if (SC.StageTargetConfigurations.Count != 1) { throw new AutomationException("iOS is currently only able to package one target configuration at a time, but StageTargetConfigurations contained {0} configurations", SC.StageTargetConfigurations.Count); } var TargetConfiguration = SC.StageTargetConfigurations[0]; bool bSupportsPortrait = false; bool bSupportsLandscape = false; bool bSkipIcons = false; DeployGeneratePList(SC.RawProjectPath, TargetConfiguration, (SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), !SC.IsCodeBasedProject, (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game"), SC.ShortProjectName, SC.EngineRoot, DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Binaries", "TVOS", "Payload", (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game") + ".app"), out bSupportsPortrait, out bSupportsLandscape, out bSkipIcons); } SC.StageFiles(StagedFileType.NonUFS, SourcePath, TargetPListFile.GetFileName(), false, null, StagedDirectoryReference.Root, false, false, "Info.plist"); } } // copy the movies from the project { SC.StageFiles(StagedFileType.NonUFS, DirectoryReference.Combine(SC.ProjectRoot, "Build/TVOS/Resources/Movies"), "*", false, null, StagedDirectoryReference.Root, true, false); SC.StageFiles(StagedFileType.NonUFS, DirectoryReference.Combine(SC.ProjectRoot, "Content/Movies"), "*", true, null, StagedDirectoryReference.Root, true, false); } }
FileReference CreateHostProject(FileReference HostProjectFile, FileReference PluginFile) { DirectoryReference HostProjectDir = HostProjectFile.Directory; HostProjectDir.CreateDirectory(); // Create the new project descriptor File.WriteAllText(HostProjectFile.FullName, "{ \"FileVersion\": 3, \"Plugins\": [ { \"Name\": \"" + PluginFile.GetFileNameWithoutExtension() + "\", \"Enabled\": true } ] }"); // Get the plugin directory in the host project, and copy all the files in DirectoryReference HostProjectPluginDir = DirectoryReference.Combine(HostProjectDir, "Plugins", PluginFile.GetFileNameWithoutExtension()); CommandUtils.ThreadedCopyFiles(PluginFile.Directory.FullName, HostProjectPluginDir.FullName); CommandUtils.DeleteDirectory(true, DirectoryReference.Combine(HostProjectPluginDir, "Intermediate").FullName); // Return the path to the plugin file in the host project return FileReference.Combine(HostProjectPluginDir, PluginFile.GetFileName()); }
private static bool RequiresTempTarget(FileReference RawProjectPath, List <UnrealTargetPlatform> Platforms, List <UnrealTargetConfiguration> Configurations, bool AssetNativizationRequested) { bool bHasCode = ProjectHasCode(RawProjectPath); foreach (UnrealTargetPlatform Platform in Platforms) { foreach (UnrealTargetConfiguration Configuration in Configurations) { string Reason; if (RequiresTempTarget(RawProjectPath, bHasCode, Platform, Configuration, TargetType.Game, AssetNativizationRequested, true, out Reason)) { Log.TraceInformation("{0} requires a temporary target.cs to be generated ({1})", RawProjectPath.GetFileName(), Reason); return(true); } } } return(false); }
/// <summary> /// Constructs a file pattern which matches a single file /// </summary> /// <param name="File">Location of the file</param> public FilePattern(FileReference File) { BaseDirectory = File.Directory; Tokens.Add(File.GetFileName()); }
/// <summary> /// Updates EC properties in the background /// </summary> private void BackgroundWorker() { bool bHasSetDiagFile = false; int NumErrors = 0; int NumWarnings = 0; string Outcome = null; List <ErrorMatch> Errors = new List <ErrorMatch>(); for (; ;) { // Copy the current set of errors bool bReadyToDispose; lock (LockObject) { if (NewErrors.Count > 0) { Errors.AddRange(NewErrors); NewErrors.Clear(); } bReadyToDispose = bDisposing; } // Write them to disk Write(OutputFile, Errors); // On the first run, set the path to the diagnostics file if (!bHasSetDiagFile) { SetProperty("/myJobStep/diagFile", OutputFile.GetFileName()); bHasSetDiagFile = true; } // Check if the number of errors has changed int NewNumErrors = Errors.Count(x => x.Severity == ErrorSeverity.Error); if (NewNumErrors > NumErrors) { SetProperty("/myJobStep/errors", NewNumErrors.ToString()); NumErrors = NewNumErrors; } // Check if the number of warnings has changed int NewNumWarnings = Errors.Count(x => x.Severity == ErrorSeverity.Warning); if (NewNumWarnings > NumWarnings) { SetProperty("/myJobStep/warnings", NewNumWarnings.ToString()); NumWarnings = NewNumWarnings; } // Check if the outcome has changed string NewOutcome = (NumErrors > 0) ? "error" : (NumWarnings > 0) ? "warning" : null; if (NewOutcome != Outcome) { SetProperty("/myJobStep/outcome", NewOutcome); Outcome = NewOutcome; } // Exit once we've flushed everything if (bReadyToDispose) { break; } // Wait until the next update UpdateEvent.WaitOne(); } }
/// <summary> /// Checks if a file exists. /// </summary> /// <param name="fileSystem">The file system</param> /// <param name="filePath">The path to the file</param> /// <returns>A bool indicating if the file exists</returns> public static bool FileExists(this IFileSystem fileSystem, FileReference filePath) { return fileSystem.ListFilesInDirectory(filePath.GetDirectory()) .Contains(filePath.GetFileName().FileLocation); }
static void PackagePlugin(FileReference PluginFile, List <BuildProduct> BuildProducts, string PackageDirectory) { // Clear the output directory CommandUtils.DeleteDirectoryContents(PackageDirectory); // Copy all the files to the output directory List <string> MatchingFileNames = FilterPluginFiles(PluginFile.FullName, BuildProducts); foreach (string MatchingFileName in MatchingFileNames) { string SourceFileName = Path.Combine(Path.GetDirectoryName(PluginFile.FullName), MatchingFileName); string TargetFileName = Path.Combine(PackageDirectory, MatchingFileName); CommandUtils.CopyFile(SourceFileName, TargetFileName); CommandUtils.SetFileAttributes(TargetFileName, ReadOnly: false); } // Get the output plugin filename FileReference TargetPluginFile = FileReference.Combine(new DirectoryReference(PackageDirectory), PluginFile.GetFileName()); PluginDescriptor NewDescriptor = PluginDescriptor.FromFile(TargetPluginFile); NewDescriptor.bEnabledByDefault = true; NewDescriptor.bInstalled = true; NewDescriptor.Save(TargetPluginFile.FullName); }
/// <summary> /// Gets the default location to stage an input file /// </summary> /// <param name="InputFile">Location of the file in the file system</param> /// <returns>Staged file location</returns> public StagedFileReference GetStagedFileLocation(FileReference InputFile) { StagedFileReference OutputFile; if (InputFile.IsUnderDirectory(ProjectRoot)) { OutputFile = StagedFileReference.Combine(RelativeProjectRootForStage, InputFile.MakeRelativeTo(ProjectRoot)); } else if (InputFile.HasExtension(".uplugin")) { DirectoryReference EnterpriseRoot = DirectoryReference.Combine(EngineRoot, "..", "Enterprise"); // Enterprise plugins aren't under the project additional plugin directories, so they shouldn't be remapped if (InputFile.IsUnderDirectory(EngineRoot) || InputFile.IsUnderDirectory(EnterpriseRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { // This is a plugin that lives outside of the Engine/Plugins or Game/Plugins directory so needs to be remapped for staging/packaging // We need to remap C:\SomePath\PluginName\PluginName.uplugin to RemappedPlugins\PluginName\PluginName.uplugin OutputFile = new StagedFileReference(String.Format("RemappedPlugins/{0}/{1}", InputFile.GetFileNameWithoutExtension(), InputFile.GetFileName())); } } else if (InputFile.IsUnderDirectory(LocalRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { throw new AutomationException("Can't deploy {0} because it doesn't start with {1} or {2}", InputFile, ProjectRoot, LocalRoot); } return(OutputFile); }
/// <summary> /// Allocates a generator-specific source file object /// </summary> /// <param name="InitFilePath">Path to the source file on disk</param> /// <param name="InitProjectSubFolder">Optional sub-folder to put the file in. If empty, this will be determined automatically from the file's path relative to the project file</param> /// <returns>The newly allocated source file object</returns> public override SourceFile AllocSourceFile(FileReference InitFilePath, DirectoryReference InitProjectSubFolder) { if (InitFilePath.GetFileName().StartsWith(".")) { return null; } return new XcodeSourceFile(InitFilePath, InitProjectSubFolder); }
public void StageFile(StagedFileType FileType, FileReference InputFile, StagedFileReference OutputFile = null, bool bRemap = true) { if (OutputFile == null) { if (InputFile.IsUnderDirectory(ProjectRoot)) { OutputFile = StagedFileReference.Combine(RelativeProjectRootForStage, InputFile.MakeRelativeTo(ProjectRoot)); } else if (InputFile.HasExtension(".uplugin")) { if (InputFile.IsUnderDirectory(EngineRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { // This is a plugin that lives outside of the Engine/Plugins or Game/Plugins directory so needs to be remapped for staging/packaging // We need to remap C:\SomePath\PluginName\PluginName.uplugin to RemappedPlugins\PluginName\PluginName.uplugin OutputFile = new StagedFileReference(String.Format("RemappedPlugins/{0}/{1}", InputFile.GetFileNameWithoutExtension(), InputFile.GetFileName())); } } else if (InputFile.IsUnderDirectory(LocalRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { throw new AutomationException("Can't deploy {0} because it doesn't start with {1} or {2}", InputFile, ProjectRoot, LocalRoot); } } if (bRemap) { OutputFile = StageTargetPlatform.Remap(OutputFile); } FilesToStage.Add(FileType, OutputFile, InputFile); }
/// <summary> /// Find all the build products created by compiling the given project file /// </summary> /// <param name="ProjectFiles">Initial project file to read. All referenced projects will also be read.</param> /// <param name="InitialProperties">Mapping of property name to value</param> /// <param name="OutBuildProducts">Receives a set of build products on success</param> /// <param name="OutReferences">Receives a set of non-private references on success</param> /// <returns>True if the build products were found, false otherwise.</returns> static bool FindBuildProducts(HashSet <FileReference> ProjectFiles, Dictionary <string, string> InitialProperties, out HashSet <FileReference> OutBuildProducts, out HashSet <FileReference> OutReferences) { // Read all the project information into a dictionary Dictionary <FileReference, CsProjectInfo> FileToProjectInfo = new Dictionary <FileReference, CsProjectInfo>(); foreach (FileReference ProjectFile in ProjectFiles) { if (!ReadProjectsRecursively(ProjectFile, InitialProperties, FileToProjectInfo)) { OutBuildProducts = null; OutReferences = null; return(false); } } // Find all the build products and references HashSet <FileReference> BuildProducts = new HashSet <FileReference>(); HashSet <FileReference> References = new HashSet <FileReference>(); foreach (KeyValuePair <FileReference, CsProjectInfo> Pair in FileToProjectInfo) { CsProjectInfo ProjectInfo = Pair.Value; // Add the standard build products DirectoryReference OutputDir = ProjectInfo.GetOutputDir(Pair.Key.Directory); ProjectInfo.AddBuildProducts(OutputDir, BuildProducts); // Add the referenced assemblies foreach (KeyValuePair <FileReference, bool> Reference in ProjectInfo.References) { FileReference OtherAssembly = Reference.Key; if (Reference.Value) { // Add reference from the output dir FileReference OutputFile = FileReference.Combine(OutputDir, OtherAssembly.GetFileName()); BuildProducts.Add(OutputFile); FileReference OutputSymbolFile = OutputFile.ChangeExtension(".pdb"); if (FileReference.Exists(OutputSymbolFile)) { BuildProducts.Add(OutputSymbolFile); } } else { // Add reference directly References.Add(OtherAssembly); FileReference SymbolFile = OtherAssembly.ChangeExtension(".pdb"); if (FileReference.Exists(SymbolFile)) { References.Add(SymbolFile); } } } // Add build products from all the referenced projects. MSBuild only copy the directly referenced build products, not recursive references or other assemblies. foreach (CsProjectInfo OtherProjectInfo in ProjectInfo.ProjectReferences.Where(x => x.Value).Select(x => FileToProjectInfo[x.Key])) { OtherProjectInfo.AddBuildProducts(OutputDir, BuildProducts); } } // Update the output set OutBuildProducts = BuildProducts; OutReferences = References; return(true); }
// @todo Mac: Full implementation. public override void CompileCSharpProject(CSharpEnvironment CompileEnvironment, FileReference ProjectFileName, FileReference DestinationFile) { string ProjectDirectory = Path.GetDirectoryName(ProjectFileName.FullName); if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { RPCUtilHelper.CopyFile(ProjectFileName.FullName, ConvertPath(ProjectFileName.FullName), true); RPCUtilHelper.CopyFile("Engine/Source/Programs/DotNETCommon/MetaData.cs", ConvertPath("Engine/Source/Programs/DotNETCommon/MetaData.cs"), true); string[] FileList = Directory.GetFiles(ProjectDirectory, "*.cs", SearchOption.AllDirectories); foreach (string File in FileList) { RPCUtilHelper.CopyFile(File, ConvertPath(File), true); } } string XBuildArgs = "/verbosity:quiet /nologo /target:Rebuild /property:Configuration=Development /property:Platform=AnyCPU " + ProjectFileName.GetFileName(); if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { RPCUtilHelper.Command(ConvertPath(ProjectDirectory), "xbuild", XBuildArgs, null); } else { Process XBuildProcess = new Process(); XBuildProcess.StartInfo.WorkingDirectory = ProjectDirectory; XBuildProcess.StartInfo.FileName = "sh"; XBuildProcess.StartInfo.Arguments = "-c 'xbuild " + XBuildArgs + " |grep -i error; if [ $? -ne 1 ]; then exit 1; else exit 0; fi'"; XBuildProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedDataEventHandler); XBuildProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedDataEventHandler); Utils.RunLocalProcess(XBuildProcess); } }
static void PackagePlugin(FileReference SourcePluginFile, IEnumerable<FileReference> BuildProducts, DirectoryReference TargetDir) { DirectoryReference SourcePluginDir = SourcePluginFile.Directory; // Copy all the files to the output directory FileReference[] SourceFiles = FilterPluginFiles(SourcePluginFile, BuildProducts).ToArray(); foreach(FileReference SourceFile in SourceFiles) { FileReference TargetFile = FileReference.Combine(TargetDir, SourceFile.MakeRelativeTo(SourcePluginDir)); CommandUtils.CopyFile(SourceFile.FullName, TargetFile.FullName); CommandUtils.SetFileAttributes(TargetFile.FullName, ReadOnly: false); } // Get the output plugin filename FileReference TargetPluginFile = FileReference.Combine(TargetDir, SourcePluginFile.GetFileName()); PluginDescriptor NewDescriptor = PluginDescriptor.FromFile(TargetPluginFile, false); NewDescriptor.bEnabledByDefault = true; NewDescriptor.bInstalled = true; NewDescriptor.Save(TargetPluginFile.FullName, false); }
public override void CompileCSharpProject(CSharpEnvironment CompileEnvironment, FileReference ProjectFileName, FileReference DestinationFile) { // Initialize environment variables required for spawned tools. VCEnvironment EnvVars = VCEnvironment.SetEnvironment(CompileEnvironment.EnvironmentTargetPlatform, bSupportWindowsXP); Action BuildProjectAction = new Action(ActionType.BuildProject); // Specify the source file (prerequisite) for the action FileItem ProjectFileItem = FileItem.GetExistingItemByFileReference(ProjectFileName); if (ProjectFileItem == null) { throw new BuildException("Expected C# project file {0} to exist.", ProjectFileName); } // Add the project and the files contained to the prerequisites. BuildProjectAction.PrerequisiteItems.Add(ProjectFileItem); VCSharpProjectFile ProjectFile = new VCSharpProjectFile(ProjectFileName); List<string> ProjectPreReqs = ProjectFile.GetCSharpDependencies(); DirectoryReference ProjectFolder = ProjectFileName.Directory; foreach (string ProjectPreReqRelativePath in ProjectPreReqs) { FileReference ProjectPreReqAbsolutePath = FileReference.Combine(ProjectFolder, ProjectPreReqRelativePath); FileItem ProjectPreReqFileItem = FileItem.GetExistingItemByFileReference(ProjectPreReqAbsolutePath); if (ProjectPreReqFileItem == null) { throw new BuildException("Expected C# dependency {0} to exist.", ProjectPreReqAbsolutePath); } BuildProjectAction.PrerequisiteItems.Add(ProjectPreReqFileItem); } // We might be able to distribute this safely, but it doesn't take any time. BuildProjectAction.bCanExecuteRemotely = false; // Setup execution via MSBuild. BuildProjectAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName; BuildProjectAction.StatusDescription = ProjectFileName.GetFileName(); BuildProjectAction.CommandPath = EnvVars.MSBuildPath; if (CompileEnvironment.TargetConfiguration == CSharpTargetConfiguration.Debug) { BuildProjectAction.CommandArguments = " /target:rebuild /property:Configuration=Debug"; } else { BuildProjectAction.CommandArguments = " /target:rebuild /property:Configuration=Development"; } // Be less verbose BuildProjectAction.CommandArguments += " /nologo /verbosity:minimal"; // Add project BuildProjectAction.CommandArguments += String.Format(" \"{0}\"", ProjectFileItem.AbsolutePath); // Specify the output files. FileReference PDBFilePath = FileReference.Combine(DestinationFile.Directory, DestinationFile.GetFileNameWithoutExtension() + ".pdb"); FileItem PDBFile = FileItem.GetItemByFileReference(PDBFilePath); BuildProjectAction.ProducedItems.Add(FileItem.GetItemByFileReference(DestinationFile)); BuildProjectAction.ProducedItems.Add(PDBFile); }
private static bool RequiresTempTarget(FileReference RawProjectPath, List <UnrealTargetPlatform> ClientTargetPlatforms, List <UnrealTargetConfiguration> ClientTargetConfigurations, bool AssetNativizationRequested) { string Reason; if (RequiresTempTarget(RawProjectPath, ClientTargetPlatforms, ClientTargetConfigurations, AssetNativizationRequested, out Reason)) { Log.TraceInformation("{0} requires a temporary target.cs to be generated ({1})", RawProjectPath.GetFileName(), Reason); return(true); } return(false); }