/// <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); } // HACK: including private headers from public headers in the same module int PrivateIdx = IncludeFile.FullName.IndexOf("\\Private\\", StringComparison.InvariantCultureIgnoreCase); if (PrivateIdx != -1) { DirectoryReference BaseDir = new DirectoryReference(IncludeFile.FullName.Substring(0, PrivateIdx)); if (FromDirectory.IsUnderDirectory(BaseDir)) { IncludeText = "\"" + IncludeFile.MakeRelativeTo(FromDirectory).Replace('\\', '/') + "\""; return(true); } } // Otherwise we don't know where it came from IncludeText = null; return(false); }
//#nv begin #Blast Linux build void StageBootstrapExecutable(DeploymentContext SC, StageTarget Target, string ExeName, string TargetFile, string StagedRelativeTargetPath, string StagedArguments) //@third party code - NVSTUDIOS Set LD_LIBRARY_PATH //nv end { // create a temp script file location DirectoryReference IntermediateDir = DirectoryReference.Combine(SC.ProjectRoot, "Intermediate", "Staging"); FileReference IntermediateFile = FileReference.Combine(IntermediateDir, ExeName); DirectoryReference.CreateDirectory(IntermediateDir); // make sure slashes are good StagedRelativeTargetPath = StagedRelativeTargetPath.Replace("\\", "/"); // make contents StringBuilder Script = new StringBuilder(); string EOL = "\n"; Script.Append("#!/bin/sh" + EOL); // allow running from symlinks Script.AppendFormat("UE4_TRUE_SCRIPT_NAME=$(echo \\\"$0\\\" | xargs readlink -f)" + EOL); Script.AppendFormat("UE4_PROJECT_ROOT=$(dirname \"$UE4_TRUE_SCRIPT_NAME\")" + EOL); Script.AppendFormat("chmod +x \"$UE4_PROJECT_ROOT/{0}\"" + EOL, StagedRelativeTargetPath); //#nv begin #Blast Linux build //The Blast .so files are not loaded by dlopen so we we need to setup the search paths //Really UE should be doing this for all dependent libraries, but they usually statically link HashSet <string> LDLibraryPaths = new HashSet <string>(); DirectoryReference TargetFileDir = (new FileReference(TargetFile)).Directory; DirectoryReference SourceEngineDir = SC.LocalRoot; DirectoryReference SourceProjectDir = SC.ProjectRoot; foreach (var RuntimeDependency in Target.Receipt.RuntimeDependencies) { foreach (FileReference File in CommandUtils.ResolveFilespec(CommandUtils.RootDirectory, RuntimeDependency.Path.FullName, new string[] { })) { if (FileReference.Exists(File) && File.GetExtension().Equals(".so", StringComparison.OrdinalIgnoreCase)) { string FileRelativePath = null; DirectoryReference SharedLibFolder = File.Directory; if (SharedLibFolder.IsUnderDirectory(SourceProjectDir)) { FileRelativePath = Path.Combine(SharedLibFolder.MakeRelativeTo(SourceProjectDir), SC.RelativeProjectRootForStage.ToString()); } else if (SharedLibFolder.IsUnderDirectory(SourceEngineDir)) { FileRelativePath = SharedLibFolder.MakeRelativeTo(SourceEngineDir); } if (FileRelativePath != null) { FileRelativePath = Path.Combine("$UE4_PROJECT_ROOT", FileRelativePath); FileRelativePath = FileRelativePath.Replace("\\", "/"); //Escape spaces FileRelativePath = FileRelativePath.Replace(" ", @"\ "); LDLibraryPaths.Add(FileRelativePath); } } } } if (LDLibraryPaths.Count > 0) { Script.AppendFormat("export LD_LIBRARY_PATH={0}" + EOL, string.Join(":", LDLibraryPaths)); } //nv end Script.AppendFormat("\"$UE4_PROJECT_ROOT/{0}\" {1} $@ " + EOL, StagedRelativeTargetPath, StagedArguments); // write out the FileReference.WriteAllText(IntermediateFile, Script.ToString()); if (Utils.IsRunningOnMono) { var Result = CommandUtils.Run("sh", string.Format("-c 'chmod +x \\\"{0}\\\"'", IntermediateFile)); if (Result.ExitCode != 0) { throw new AutomationException(string.Format("Failed to chmod \"{0}\"", IntermediateFile)); } } SC.StageFile(StagedFileType.NonUFS, IntermediateFile, new StagedFileReference(ExeName)); }
public override void ExecuteBuild() { // Get the plugin filename string PluginParam = ParseParamValue("Plugin"); if (PluginParam == null) { throw new AutomationException("Missing -Plugin=... argument"); } // Check it exists FileReference PluginFile = new FileReference(PluginParam); if (!FileReference.Exists(PluginFile)) { throw new AutomationException("Plugin '{0}' not found", PluginFile.FullName); } // Get the output directory string PackageParam = ParseParamValue("Package"); if (PackageParam == null) { throw new AutomationException("Missing -Package=... argument"); } // Option for verifying that all include directive s bool bStrictIncludes = ParseParam("StrictIncludes"); // Whether to use VS2019 for compiling all targets. By default, we currently use 2017 for compiling static libraries for maximum compatibility. bool bVS2019 = ParseParam("VS2019"); // Make sure the packaging directory is valid DirectoryReference PackageDir = new DirectoryReference(PackageParam); if (PluginFile.IsUnderDirectory(PackageDir)) { throw new AutomationException("Packaged plugin output directory must be different to source"); } if (PackageDir.IsUnderDirectory(DirectoryReference.Combine(CommandUtils.RootDirectory, "Engine"))) { throw new AutomationException("Output directory for packaged plugin must be outside engine directory"); } // Clear the output directory of existing stuff if (DirectoryReference.Exists(PackageDir)) { CommandUtils.DeleteDirectoryContents(PackageDir.FullName); } else { DirectoryReference.CreateDirectory(PackageDir); } // Create a placeholder FilterPlugin.ini with instructions on how to use it FileReference SourceFilterFile = FileReference.Combine(PluginFile.Directory, "Config", "FilterPlugin.ini"); if (!FileReference.Exists(SourceFilterFile)) { List <string> Lines = new List <string>(); Lines.Add("[FilterPlugin]"); Lines.Add("; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and"); Lines.Add("; may include \"...\", \"*\", and \"?\" wildcards to match directories, files, and individual characters respectively."); Lines.Add(";"); Lines.Add("; Examples:"); Lines.Add("; /README.txt"); Lines.Add("; /Extras/..."); Lines.Add("; /Binaries/ThirdParty/*.dll"); DirectoryReference.CreateDirectory(SourceFilterFile.Directory); CommandUtils.WriteAllLines_NoExceptions(SourceFilterFile.FullName, Lines.ToArray()); } // Create a host project for the plugin. For script generator plugins, we need to have UHT be able to load it, which can only happen if it's enabled in a project. FileReference HostProjectFile = FileReference.Combine(PackageDir, "HostProject", "HostProject.uproject"); FileReference HostProjectPluginFile = CreateHostProject(HostProjectFile, PluginFile); // Read the plugin CommandUtils.LogInformation("Reading plugin from {0}...", HostProjectPluginFile); PluginDescriptor Plugin = PluginDescriptor.FromFile(HostProjectPluginFile); // Get the arguments for the compile StringBuilder AdditionalArgs = new StringBuilder(); if (bStrictIncludes) { CommandUtils.LogInformation("Building with precompiled headers and unity disabled"); AdditionalArgs.Append(" -NoPCH -NoSharedPCH -DisableUnity"); } // Compile the plugin for all the target platforms List <UnrealTargetPlatform> HostPlatforms = ParseParam("NoHostPlatform")? new List <UnrealTargetPlatform>() : new List <UnrealTargetPlatform> { BuildHostPlatform.Current.Platform }; List <UnrealTargetPlatform> TargetPlatforms = GetTargetPlatforms(this, BuildHostPlatform.Current.Platform); FileReference[] BuildProducts = CompilePlugin(HostProjectFile, HostProjectPluginFile, Plugin, HostPlatforms, TargetPlatforms, AdditionalArgs.ToString(), bVS2019); // Package up the final plugin data PackagePlugin(HostProjectPluginFile, BuildProducts, PackageDir, ParseParam("unversioned")); // Remove the host project if (!ParseParam("NoDeleteHostProject")) { CommandUtils.DeleteDirectory(HostProjectFile.Directory.FullName); } }
public override void ExecuteBuild() { // Get the plugin filename string PluginParam = ParseParamValue("Plugin"); if(PluginParam == null) { throw new AutomationException("Missing -Plugin=... argument"); } // Check it exists FileReference PluginFile = new FileReference(PluginParam); if (!PluginFile.Exists()) { throw new AutomationException("Plugin '{0}' not found", PluginFile.FullName); } // Get the output directory string PackageParam = ParseParamValue("Package"); if (PackageParam == null) { throw new AutomationException("Missing -Package=... argument"); } // Make sure the packaging directory is valid DirectoryReference PackageDir = new DirectoryReference(PackageParam); if (PluginFile.IsUnderDirectory(PackageDir)) { throw new AutomationException("Packaged plugin output directory must be different to source"); } if (PackageDir.IsUnderDirectory(DirectoryReference.Combine(CommandUtils.RootDirectory, "Engine"))) { throw new AutomationException("Output directory for packaged plugin must be outside engine directory"); } // Clear the output directory of existing stuff if (PackageDir.Exists()) { CommandUtils.DeleteDirectoryContents(PackageDir.FullName); } else { PackageDir.CreateDirectory(); } // Create a placeholder FilterPlugin.ini with instructions on how to use it FileReference SourceFilterFile = FileReference.Combine(PluginFile.Directory, "Config", "FilterPlugin.ini"); if (!SourceFilterFile.Exists()) { List<string> Lines = new List<string>(); Lines.Add("[FilterPlugin]"); Lines.Add("; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and"); Lines.Add("; may include \"...\", \"*\", and \"?\" wildcards to match directories, files, and individual characters respectively."); Lines.Add(";"); Lines.Add("; Examples:"); Lines.Add("; /README.txt"); Lines.Add("; /Extras/..."); Lines.Add("; /Binaries/ThirdParty/*.dll"); SourceFilterFile.Directory.CreateDirectory(); CommandUtils.WriteAllLines_NoExceptions(SourceFilterFile.FullName, Lines.ToArray()); } // Create a host project for the plugin. For script generator plugins, we need to have UHT be able to load it, which can only happen if it's enabled in a project. FileReference HostProjectFile = FileReference.Combine(PackageDir, "HostProject", "HostProject.uproject"); FileReference HostProjectPluginFile = CreateHostProject(HostProjectFile, PluginFile); // Read the plugin CommandUtils.Log("Reading plugin from {0}...", HostProjectPluginFile); PluginDescriptor Plugin = PluginDescriptor.FromFile(HostProjectPluginFile, false); // Compile the plugin for all the target platforms List<UnrealTargetPlatform> HostPlatforms = ParseParam("NoHostPlatform")? new List<UnrealTargetPlatform>() : new List<UnrealTargetPlatform> { BuildHostPlatform.Current.Platform }; List<UnrealTargetPlatform> TargetPlatforms = GetTargetPlatforms(this, BuildHostPlatform.Current.Platform).Where(x => IsCodeTargetPlatform(BuildHostPlatform.Current.Platform, x)).ToList(); FileReference[] BuildProducts = CompilePlugin(HostProjectFile, HostProjectPluginFile, Plugin, HostPlatforms, TargetPlatforms, ""); // Package up the final plugin data PackagePlugin(HostProjectPluginFile, BuildProducts, PackageDir); // Remove the host project if(!ParseParam("NoDeleteHostProject")) { CommandUtils.DeleteDirectory(HostProjectFile.Directory.FullName); } }