You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Mostly a find/replace, though I have looked through the changes and attempted to update references to other things as necessary (eg. renaming IOS plist files for IOS). I'm not set up to test on any platforms other than windows, and was hoping to get your blessing to submit and give QA enough time as possible to uncover issues before the next milestone release. Particular things that I know I'm not sure about: - Android references /UE4Game/ paths everywhere (for paths on device, I think). I have no idea if I've got them all. - I've renamed the iOS mobileprovisions, but I don't know if they need regenerating for the new app name. - Likewise, not sure what needs to be updated for icon bundles on iOS. Things that have not been changed: - Windows still uses IDI_UE4ICON for its icon - UE4CommandLine.txt - There's still a UE4Game module which is used by content-only projects #rb none [CL 14301890 by Ben Marsh in ue5-main branch]
355 lines
16 KiB
C#
355 lines
16 KiB
C#
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using AutomationTool;
|
|
using UnrealBuildTool;
|
|
using Tools.DotNETCommon;
|
|
using System.Text;
|
|
|
|
[Help("Builds a plugin, and packages it for distribution")]
|
|
[Help("Plugin", "Specify the path to the descriptor file for the plugin that should be packaged")]
|
|
[Help("NoHostPlatform", "Prevent compiling for the editor platform on the host")]
|
|
[Help("TargetPlatforms", "Specify a list of target platforms to build, separated by '+' characters (eg. -TargetPlatforms=Win32+Win64). Default is all the Rocket target platforms.")]
|
|
[Help("Package", "The path which the build artifacts should be packaged to, ready for distribution.")]
|
|
[Help("StrictIncludes", "Disables precompiled headers and unity build in order to check all source files have self-contained headers.")]
|
|
[Help("Unversioned", "Do not embed the current engine version into the descriptor")]
|
|
class BuildPlugin : BuildCommand
|
|
{
|
|
const string AndroidArchitectures = "armv7+arm64";
|
|
const string HoloLensArchitecture = "arm64+x64";
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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());
|
|
}
|
|
|
|
FileReference[] CompilePlugin(FileReference HostProjectFile, FileReference HostProjectPluginFile, PluginDescriptor Plugin, List<UnrealTargetPlatform> HostPlatforms, List<UnrealTargetPlatform> TargetPlatforms, string AdditionalArgs, bool bVS2019)
|
|
{
|
|
List<FileReference> ManifestFileNames = new List<FileReference>();
|
|
|
|
// Build the host platforms
|
|
if(HostPlatforms.Count > 0)
|
|
{
|
|
CommandUtils.LogInformation("Building plugin for host platforms: {0}", String.Join(", ", HostPlatforms));
|
|
foreach (UnrealTargetPlatform HostPlatform in HostPlatforms)
|
|
{
|
|
if (Plugin.SupportedPrograms != null && Plugin.SupportedPrograms.Contains("UnrealHeaderTool"))
|
|
{
|
|
CompilePluginWithUBT(HostProjectFile, HostProjectPluginFile, Plugin, "UnrealHeaderTool", TargetType.Program, HostPlatform, UnrealTargetConfiguration.Development, ManifestFileNames, String.Format("{0} -plugin={1}", AdditionalArgs, CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName)));
|
|
}
|
|
CompilePluginWithUBT(HostProjectFile, HostProjectPluginFile, Plugin, "UnrealEditor", TargetType.Editor, HostPlatform, UnrealTargetConfiguration.Development, ManifestFileNames, AdditionalArgs);
|
|
}
|
|
}
|
|
|
|
// Add the game targets
|
|
if(TargetPlatforms.Count > 0)
|
|
{
|
|
CommandUtils.LogInformation("Building plugin for target platforms: {0}", String.Join(", ", TargetPlatforms));
|
|
foreach (UnrealTargetPlatform TargetPlatform in TargetPlatforms)
|
|
{
|
|
if(Plugin.SupportsTargetPlatform(TargetPlatform))
|
|
{
|
|
string AdditionalTargetArgs = AdditionalArgs + (bVS2019 ? "" : " -2017");
|
|
CompilePluginWithUBT(HostProjectFile, HostProjectPluginFile, Plugin, "UnrealGame", TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Development, ManifestFileNames, AdditionalTargetArgs);
|
|
CompilePluginWithUBT(HostProjectFile, HostProjectPluginFile, Plugin, "UnrealGame", TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Shipping, ManifestFileNames, AdditionalTargetArgs);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Package the plugin to the output folder
|
|
HashSet<FileReference> BuildProducts = new HashSet<FileReference>();
|
|
foreach(FileReference ManifestFileName in ManifestFileNames)
|
|
{
|
|
BuildManifest Manifest = CommandUtils.ReadManifest(ManifestFileName);
|
|
BuildProducts.UnionWith(Manifest.BuildProducts.Select(x => new FileReference(x)));
|
|
}
|
|
return BuildProducts.ToArray();
|
|
}
|
|
|
|
void CompilePluginWithUBT(FileReference HostProjectFile, FileReference HostProjectPluginFile, PluginDescriptor Plugin, string TargetName, TargetType TargetType, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, List<FileReference> ManifestFileNames, string InAdditionalArgs)
|
|
{
|
|
// Find a list of modules that need to be built for this plugin
|
|
bool bCompilePlatform = false;
|
|
if (Plugin.Modules != null)
|
|
{
|
|
foreach (ModuleDescriptor Module in Plugin.Modules)
|
|
{
|
|
bool bBuildDeveloperTools = (TargetType == TargetType.Editor || TargetType == TargetType.Program);
|
|
bool bBuildRequiresCookedData = (TargetType != TargetType.Editor && TargetType != TargetType.Program);
|
|
if (Module.IsCompiledInConfiguration(Platform, Configuration, TargetName, TargetType, bBuildDeveloperTools, bBuildRequiresCookedData))
|
|
{
|
|
bCompilePlatform = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add these modules to the build agenda
|
|
if(bCompilePlatform)
|
|
{
|
|
if (Platform == UnrealTargetPlatform.HoloLens)
|
|
{
|
|
// Make sure to save the manifests for each architecture with unique names so they don't get overwritten.
|
|
// This fixes packaging issues when building from binary engine releases, where the build produces a manifest for the plugin for ARM64, which
|
|
// then gets overwritten by the manifest for x64. Then during packaging, the plugin is referencing a manifest for the wrong architecture.
|
|
foreach (string Arch in HoloLensArchitecture.Split('+'))
|
|
{
|
|
FileReference ManifestFileName = FileReference.Combine(HostProjectFile.Directory, "Saved", String.Format("Manifest-{0}-{1}-{2}-{3}.xml", TargetName, Platform, Configuration, Arch));
|
|
ManifestFileNames.Add(ManifestFileName);
|
|
string Arguments = String.Format("-plugin={0} -iwyu -noubtmakefiles -manifest={1} -nohotreload", CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName), CommandUtils.MakePathSafeToUseWithCommandLine(ManifestFileName.FullName));
|
|
Arguments += String.Format(" -Architecture={0}", Arch);
|
|
if (!String.IsNullOrEmpty(InAdditionalArgs))
|
|
{
|
|
Arguments += InAdditionalArgs;
|
|
}
|
|
CommandUtils.RunUBT(CmdEnv, UE4Build.GetUBTExecutable(), HostProjectFile, TargetName, Platform, Configuration, Arguments);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FileReference ManifestFileName = FileReference.Combine(HostProjectFile.Directory, "Saved", String.Format("Manifest-{0}-{1}-{2}.xml", TargetName, Platform, Configuration));
|
|
ManifestFileNames.Add(ManifestFileName);
|
|
|
|
string Arguments = String.Format("-plugin={0} -iwyu -noubtmakefiles -manifest={1} -nohotreload", CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName), CommandUtils.MakePathSafeToUseWithCommandLine(ManifestFileName.FullName));
|
|
if (Platform == UnrealTargetPlatform.Android)
|
|
{
|
|
Arguments += String.Format(" -architectures={0}", AndroidArchitectures);
|
|
}
|
|
|
|
if (!String.IsNullOrEmpty(InAdditionalArgs))
|
|
{
|
|
Arguments += InAdditionalArgs;
|
|
}
|
|
|
|
CommandUtils.RunUBT(CmdEnv, UE4Build.GetUBTExecutable(), HostProjectFile, TargetName, Platform, Configuration, Arguments);
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static IEnumerable<FileReference> FilterPluginFiles(FileReference PluginFile, IEnumerable<FileReference> BuildProducts)
|
|
{
|
|
// Set up the default filter
|
|
FileFilter Filter = new FileFilter();
|
|
Filter.AddRuleForFile(PluginFile, PluginFile.Directory, FileFilterType.Include);
|
|
Filter.AddRuleForFiles(BuildProducts, PluginFile.Directory, FileFilterType.Include);
|
|
Filter.Include("/Binaries/ThirdParty/...");
|
|
Filter.Include("/Resources/...");
|
|
Filter.Include("/Content/...");
|
|
Filter.Include("/Intermediate/Build/.../Inc/...");
|
|
Filter.Include("/Shaders/...");
|
|
Filter.Include("/Source/...");
|
|
|
|
// Add custom rules for each platform
|
|
FileReference FilterFile = FileReference.Combine(PluginFile.Directory, "Config", "FilterPlugin.ini");
|
|
if(FileReference.Exists(FilterFile))
|
|
{
|
|
CommandUtils.LogInformation("Reading filter rules from {0}", FilterFile);
|
|
Filter.ReadRulesFromFile(FilterFile, "FilterPlugin");
|
|
}
|
|
|
|
// Apply the standard exclusion rules
|
|
foreach (string RestrictedFolderName in RestrictedFolder.GetNames())
|
|
{
|
|
Filter.AddRule(String.Format(".../{0}/...", RestrictedFolderName), FileFilterType.Exclude);
|
|
}
|
|
|
|
// Apply the filter to the plugin directory
|
|
return Filter.ApplyToDirectory(PluginFile.Directory, true);
|
|
}
|
|
|
|
static List<UnrealTargetPlatform> GetTargetPlatforms(BuildCommand Command, UnrealTargetPlatform HostPlatform)
|
|
{
|
|
List<UnrealTargetPlatform> TargetPlatforms = new List<UnrealTargetPlatform>();
|
|
if(!Command.ParseParam("NoTargetPlatforms"))
|
|
{
|
|
// Only interested in building for Platforms that support code projects
|
|
TargetPlatforms = PlatformExports.GetRegisteredPlatforms().Where(x => InstalledPlatformInfo.IsValidPlatform(x, EProjectType.Code)).ToList();
|
|
|
|
// only build Mac on Mac
|
|
if (HostPlatform != UnrealTargetPlatform.Mac && TargetPlatforms.Contains(UnrealTargetPlatform.Mac))
|
|
{
|
|
TargetPlatforms.Remove(UnrealTargetPlatform.Mac);
|
|
}
|
|
// only build Windows on Windows
|
|
if (HostPlatform != UnrealTargetPlatform.Win64 && TargetPlatforms.Contains(UnrealTargetPlatform.Win64))
|
|
{
|
|
TargetPlatforms.Remove(UnrealTargetPlatform.Win64);
|
|
TargetPlatforms.Remove(UnrealTargetPlatform.Win32);
|
|
}
|
|
// build Linux on Windows and Linux
|
|
if (HostPlatform != UnrealTargetPlatform.Win64 && HostPlatform != UnrealTargetPlatform.Linux)
|
|
{
|
|
if (TargetPlatforms.Contains(UnrealTargetPlatform.Linux))
|
|
TargetPlatforms.Remove(UnrealTargetPlatform.Linux);
|
|
|
|
if (TargetPlatforms.Contains(UnrealTargetPlatform.LinuxAArch64))
|
|
TargetPlatforms.Remove(UnrealTargetPlatform.LinuxAArch64);
|
|
}
|
|
|
|
// Remove any platforms that aren't enabled on the command line
|
|
string TargetPlatformFilter = Command.ParseParamValue("TargetPlatforms", null);
|
|
if(TargetPlatformFilter != null)
|
|
{
|
|
List<UnrealTargetPlatform> NewTargetPlatforms = new List<UnrealTargetPlatform>();
|
|
foreach (string TargetPlatformName in TargetPlatformFilter.Split(new char[]{ '+' }, StringSplitOptions.RemoveEmptyEntries))
|
|
{
|
|
UnrealTargetPlatform TargetPlatform;
|
|
if (!UnrealTargetPlatform.TryParse(TargetPlatformName, out TargetPlatform))
|
|
{
|
|
throw new AutomationException("Unknown target platform '{0}' specified on command line", TargetPlatformName);
|
|
}
|
|
if(TargetPlatforms.Contains(TargetPlatform))
|
|
{
|
|
NewTargetPlatforms.Add(TargetPlatform);
|
|
}
|
|
}
|
|
TargetPlatforms = NewTargetPlatforms;
|
|
}
|
|
}
|
|
return TargetPlatforms;
|
|
}
|
|
}
|
|
|