Example #1
0
        /// <summary>
        /// Execute the mode
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns></returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);

            // Create the build configuration object, and read the settings
            BuildConfiguration BuildConfiguration = new BuildConfiguration();

            XmlConfig.ApplyTo(BuildConfiguration);
            Arguments.ApplyTo(BuildConfiguration);

            // Ensure the path to the output file is valid
            if (OutputFile == null)
            {
                OutputFile = GetDefaultOutputFile(ProjectFile);
            }

            // Create the rules assembly
            RulesAssembly Assembly;

            if (ProjectFile == null)
            {
                Assembly = RulesCompiler.CreateEnterpriseRulesAssembly(BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile);
            }
            else
            {
                Assembly = RulesCompiler.CreateProjectRulesAssembly(ProjectFile, BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile);
            }

            // Write information about these targets
            WriteTargetInfo(ProjectFile, Assembly, OutputFile, Arguments);
            Log.TraceInformation("Written {0}", OutputFile);
            return(0);
        }
Example #2
0
        public override bool PrepTargetForDeployment(UEBuildTarget InTarget)
        {
            string InAppName = InTarget.AppName;

            Log.TraceInformation("Prepping {0} for deployment to {1}", InAppName, InTarget.Platform.ToString());
            System.DateTime PrepDeployStartTime = DateTime.UtcNow;

            string TargetFilename      = RulesCompiler.GetTargetFilename(InAppName);
            string ProjectSourceFolder = new FileInfo(TargetFilename).DirectoryName + "/";

            string RelativeTargetDirectory;
            string EngineSourceRelativeBinaryPath;

            UWPProjectGenerator.GetTargetUWPPaths(InAppName, InTarget.Rules, out EngineSourceRelativeBinaryPath, out RelativeTargetDirectory);

            PrepForUATPackageOrDeploy(InAppName, InTarget.ProjectDirectory, InTarget.OutputPath, BuildConfiguration.RelativeEnginePath, false, "");

            // TODO - richiem - restore this if we find that it's needed.
            //Log.TraceInformation("...copying the CELL dll...");
            //string CELLPath = "../../../Engine/Source/" + UEBuildConfiguration.UEThirdPartySourceDirectory + "CELL/lib/win64/";
            //string CELLPathRelease = CELLPath + "Release/";
            //string CELLDllRelease = "CommonEventLoggingLibrary.dll";
            //string CELLPathDebug = CELLPath + "Debug/";
            //string CELLDllDebug = "CommonEventLoggingLibraryd.dll";

            //CopyFile(EngineSourceRelativeBinaryPath + CELLPathRelease + CELLDllRelease, EngineSourceRelativeBinaryPath + CELLDllRelease, true);
            //CopyFile(EngineSourceRelativeBinaryPath + CELLPathDebug + CELLDllDebug, EngineSourceRelativeBinaryPath + CELLDllDebug, true);

            //string XSAPIPath            = EngineSourceRelativeBinaryPath + "../../../Engine/Source/ThirdParty/XSAPI/lib/";
            //string XboxServicesConfig   = "xboxservices.config";
            //string DesktopLogin         = "******";

            //Log.TraceInformation("...copying xboxservices.config");
            //CopyFile(XSAPIPath + XboxServicesConfig, EngineSourceRelativeBinaryPath + XboxServicesConfig, true);
            //Log.TraceInformation("...copying DesktopLogin.exe...");
            //CopyFile(XSAPIPath + DesktopLogin, EngineSourceRelativeBinaryPath + DesktopLogin, true);

            // TODO - richiem - restore this if we find that it's needed.
            //if (InTarget.Configuration == UnrealTargetConfiguration.Development)
            //{
            //    Log.TraceInformation("...copying AutoLogin...");
            //    string AutoLoginPath    = EngineSourceRelativeBinaryPath + "../../../Engine/Source/Tools/AutoLogin/";
            //    string AutoLoginDLL     = "AutoLogin.dll";
            //    string AutoLoginBat     = "AutoLogin.bat";
            //    CopyFile(AutoLoginPath + "bin/Debug/" + AutoLoginDLL, EngineSourceRelativeBinaryPath + AutoLoginDLL, true);
            //    CopyFile(AutoLoginPath + AutoLoginBat, EngineSourceRelativeBinaryPath + AutoLoginBat, true);
            //}



            // Log out the time taken to deploy...
            double PrepDeployDuration = (DateTime.UtcNow - PrepDeployStartTime).TotalSeconds;

            Log.TraceInformation("UWP deployment preparation took {0:0.00} seconds", PrepDeployDuration);

            return(true);
        }
Example #3
0
        public static void GetTargetUWPPaths(string InTargetName, TargetRules InTargetRules,
                                             out string OutEngineSourceRelativeBinaryPath, out string OutRelativeTargetPath)
        {
            OutEngineSourceRelativeBinaryPath = "";
            OutRelativeTargetPath             = "";

            string TargetFilename = RulesCompiler.GetTargetFilename(InTargetName);

            string ProjectSourceFolder = new FileInfo(TargetFilename).DirectoryName;

            string EnginePath             = Path.Combine(ProjectFileGenerator.EngineRelativePath);
            string EngineSourcePath       = Path.Combine(EnginePath, "Source");
            string RelativeTargetFilename = Utils.MakePathRelativeTo(TargetFilename, EngineSourcePath);

            if ((RelativeTargetFilename.StartsWith("..") == false) && (RelativeTargetFilename.Contains(":") == false))
            {
                // This target must be UNDER Engine/Source...
                RelativeTargetFilename = Path.Combine(EngineSourcePath, RelativeTargetFilename);
            }
            RelativeTargetFilename = RelativeTargetFilename.Replace("\\", "/");
            EnginePath             = EnginePath.Replace("\\", "/");

            Int32 LastSourceIdx = RelativeTargetFilename.LastIndexOf("Source");

            if (LastSourceIdx != -1)
            {
                RelativeTargetFilename = RelativeTargetFilename.Substring(0, LastSourceIdx);
            }
            else
            {
                RelativeTargetFilename = "";
            }

            OutRelativeTargetPath = RelativeTargetFilename;

            if (InTargetRules.bOutputToEngineBinaries)
            {
                RelativeTargetFilename = EnginePath;
            }
            OutEngineSourceRelativeBinaryPath = Path.Combine(RelativeTargetFilename, "Binaries/UWP/");
            OutEngineSourceRelativeBinaryPath = OutEngineSourceRelativeBinaryPath.Replace("\\", "/");
        }
Example #4
0
        /// <summary>
        /// Main entry point
        /// </summary>
        /// <param name="Arguments">Command-line arguments</param>
        /// <returns>One of the values of ECompilationResult</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);

            // Create the build configuration object, and read the settings
            BuildConfiguration BuildConfiguration = new BuildConfiguration();

            XmlConfig.ApplyTo(BuildConfiguration);
            Arguments.ApplyTo(BuildConfiguration);

            // Parse all the targets being built
            List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, bSkipRulesCompile);

            if (TargetDescriptors.Count == 0)
            {
                throw new BuildException("No targets specified to clean");
            }

            // Also add implicit descriptors for cleaning UnrealBuildTool
            if (!BuildConfiguration.bDoNotBuildUHT)
            {
                const string UnrealHeaderToolTarget = "UnrealHeaderTool";

                // Get a list of project files to clean UHT for
                List <FileReference> ProjectFiles = new List <FileReference>();
                foreach (TargetDescriptor TargetDesc in TargetDescriptors)
                {
                    if (TargetDesc.Name != UnrealHeaderToolTarget && !RemoteMac.HandlesTargetPlatform(TargetDesc.Platform))
                    {
                        if (ProjectFiles.Count == 0)
                        {
                            ProjectFiles.Add(null);
                        }
                        if (TargetDesc.ProjectFile != null && !ProjectFiles.Contains(TargetDesc.ProjectFile))
                        {
                            ProjectFiles.Add(TargetDesc.ProjectFile);
                        }
                    }
                }

                // Add descriptors for cleaning UHT with all these projects
                if (ProjectFiles.Count > 0)
                {
                    UnrealTargetConfiguration Configuration = BuildConfiguration.bForceDebugUnrealHeaderTool ? UnrealTargetConfiguration.Debug : UnrealTargetConfiguration.Development;
                    string Architecture = UEBuildPlatform.GetBuildPlatform(BuildHostPlatform.Current.Platform).GetDefaultArchitecture(null);
                    foreach (FileReference ProjectFile in ProjectFiles)
                    {
                        TargetDescriptors.Add(new TargetDescriptor(ProjectFile, UnrealHeaderToolTarget, BuildHostPlatform.Current.Platform, Configuration, Architecture, null));
                    }
                }
            }

            // Output the list of targets that we're cleaning
            Log.TraceInformation("Cleaning {0} binaries...", StringUtils.FormatList(TargetDescriptors.Select(x => x.Name).Distinct()));

            // Loop through all the targets, and clean them all
            HashSet <FileReference>      FilesToDelete       = new HashSet <FileReference>();
            HashSet <DirectoryReference> DirectoriesToDelete = new HashSet <DirectoryReference>();

            foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
            {
                // Create the rules assembly
                RulesAssembly RulesAssembly = RulesCompiler.CreateTargetRulesAssembly(TargetDescriptor.ProjectFile, TargetDescriptor.Name, bSkipRulesCompile, BuildConfiguration.bUsePrecompiled, TargetDescriptor.ForeignPlugin);

                // Create the rules object
                ReadOnlyTargetRules Target = new ReadOnlyTargetRules(RulesAssembly.CreateTargetRules(TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Configuration, TargetDescriptor.Architecture, TargetDescriptor.ProjectFile, TargetDescriptor.AdditionalArguments));

                // Find the base folders that can contain binaries
                List <DirectoryReference> BaseDirs = new List <DirectoryReference>();
                BaseDirs.Add(UnrealBuildTool.EngineDirectory);
                BaseDirs.Add(UnrealBuildTool.EnterpriseDirectory);
                foreach (FileReference Plugin in Plugins.EnumeratePlugins(Target.ProjectFile))
                {
                    BaseDirs.Add(Plugin.Directory);
                }
                if (Target.ProjectFile != null)
                {
                    BaseDirs.Add(Target.ProjectFile.Directory);
                }

                // If we're running a precompiled build, remove anything under the engine folder
                BaseDirs.RemoveAll(x => RulesAssembly.IsReadOnly(x));

                // Get all the names which can prefix build products
                List <string> NamePrefixes = new List <string>();
                if (Target.Type != TargetType.Program)
                {
                    NamePrefixes.Add(UEBuildTarget.GetAppNameForTargetType(Target.Type));
                }
                NamePrefixes.Add(Target.Name);

                // Get the suffixes for this configuration
                List <string> NameSuffixes = new List <string>();
                if (Target.Configuration == Target.UndecoratedConfiguration)
                {
                    NameSuffixes.Add("");
                }
                NameSuffixes.Add(String.Format("-{0}-{1}", Target.Platform.ToString(), Target.Configuration.ToString()));
                if (!String.IsNullOrEmpty(Target.Architecture))
                {
                    NameSuffixes.AddRange(NameSuffixes.ToArray().Select(x => x + Target.Architecture));
                }

                // Add all the makefiles and caches to be deleted
                FilesToDelete.Add(TargetMakefile.GetLocation(Target.ProjectFile, Target.Name, Target.Platform, Target.Configuration));
                FilesToDelete.UnionWith(SourceFileMetadataCache.GetFilesToClean(Target.ProjectFile));
                FilesToDelete.UnionWith(ActionHistory.GetFilesToClean(Target.ProjectFile, Target.Name, Target.Platform, Target.Type));

                // Add all the intermediate folders to be deleted
                foreach (DirectoryReference BaseDir in BaseDirs)
                {
                    foreach (string NamePrefix in NamePrefixes)
                    {
                        DirectoryReference GeneratedCodeDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, "Inc");
                        if (DirectoryReference.Exists(GeneratedCodeDir))
                        {
                            DirectoriesToDelete.Add(GeneratedCodeDir);
                        }

                        DirectoryReference IntermediateDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, Target.Configuration.ToString());
                        if (DirectoryReference.Exists(IntermediateDir))
                        {
                            DirectoriesToDelete.Add(IntermediateDir);
                        }
                    }
                }

                // List of additional files and directories to clean, specified by the target platform
                List <FileReference>      AdditionalFilesToDelete       = new List <FileReference>();
                List <DirectoryReference> AdditionalDirectoriesToDelete = new List <DirectoryReference>();

                // Add all the build products from this target
                string[] NamePrefixesArray = NamePrefixes.Distinct().ToArray();
                string[] NameSuffixesArray = NameSuffixes.Distinct().ToArray();
                foreach (DirectoryReference BaseDir in BaseDirs)
                {
                    DirectoryReference BinariesDir = DirectoryReference.Combine(BaseDir, "Binaries", Target.Platform.ToString());
                    if (DirectoryReference.Exists(BinariesDir))
                    {
                        UEBuildPlatform.GetBuildPlatform(Target.Platform).FindBuildProductsToClean(BinariesDir, NamePrefixesArray, NameSuffixesArray, AdditionalFilesToDelete, AdditionalDirectoriesToDelete);
                    }
                }

                // Get all the additional intermediate folders created by this platform
                UEBuildPlatform.GetBuildPlatform(Target.Platform).FindAdditionalBuildProductsToClean(Target, AdditionalFilesToDelete, AdditionalDirectoriesToDelete);

                // Add the platform's files and directories to the main list
                FilesToDelete.UnionWith(AdditionalFilesToDelete);
                DirectoriesToDelete.UnionWith(AdditionalDirectoriesToDelete);
            }

            // Delete all the directories, then all the files. By sorting the list of directories before we delete them, we avoid spamming the log if a parent directory is deleted first.
            foreach (DirectoryReference DirectoryToDelete in DirectoriesToDelete.OrderBy(x => x.FullName))
            {
                if (DirectoryReference.Exists(DirectoryToDelete))
                {
                    Log.TraceVerbose("    Deleting {0}{1}...", DirectoryToDelete, Path.DirectorySeparatorChar);
                    try
                    {
                        DirectoryReference.Delete(DirectoryToDelete, true);
                    }
                    catch (Exception Ex)
                    {
                        throw new BuildException(Ex, "Unable to delete {0} ({1})", DirectoryToDelete, Ex.Message.TrimEnd());
                    }
                }
            }

            foreach (FileReference FileToDelete in FilesToDelete.OrderBy(x => x.FullName))
            {
                if (FileReference.Exists(FileToDelete))
                {
                    Log.TraceVerbose("    Deleting " + FileToDelete);
                    try
                    {
                        FileReference.Delete(FileToDelete);
                    }
                    catch (Exception Ex)
                    {
                        throw new BuildException(Ex, "Unable to delete {0} ({1})", FileToDelete, Ex.Message.TrimEnd());
                    }
                }
            }

            // Also clean all the remote targets
            for (int Idx = 0; Idx < TargetDescriptors.Count; Idx++)
            {
                TargetDescriptor TargetDescriptor = TargetDescriptors[Idx];
                if (RemoteMac.HandlesTargetPlatform(TargetDescriptor.Platform))
                {
                    RemoteMac RemoteMac = new RemoteMac(TargetDescriptor.ProjectFile);
                    RemoteMac.Clean(TargetDescriptor);
                }
            }

            return(0);
        }
Example #5
0
        /// <summary>
        /// Build a target remotely
        /// </summary>
        /// <param name="TargetDesc">Descriptor for the target to build</param>
        /// <param name="RemoteLogFile">Path to store the remote log file</param>
        /// <returns>True if the build succeeded, false otherwise</returns>
        public bool Build(TargetDescriptor TargetDesc, FileReference RemoteLogFile)
        {
            // Get the directory for working files
            DirectoryReference BaseDir = DirectoryReference.FromFile(TargetDesc.ProjectFile) ?? UnrealBuildTool.EngineDirectory;
            DirectoryReference TempDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Remote", TargetDesc.Name, TargetDesc.Platform.ToString(), TargetDesc.Configuration.ToString());

            DirectoryReference.CreateDirectory(TempDir);

            // Compile the rules assembly
            RulesCompiler.CreateTargetRulesAssembly(TargetDesc.ProjectFile, TargetDesc.Name, false, false, TargetDesc.ForeignPlugin);

            // Path to the local manifest file. This has to be translated from the remote format after the build is complete.
            List <FileReference> LocalManifestFiles = new List <FileReference>();

            // Path to the remote manifest file
            FileReference RemoteManifestFile = FileReference.Combine(TempDir, "Manifest.xml");

            // Prepare the arguments we will pass to the remote build
            List <string> RemoteArguments = new List <string>();

            RemoteArguments.Add(TargetDesc.Name);
            RemoteArguments.Add(TargetDesc.Platform.ToString());
            RemoteArguments.Add(TargetDesc.Configuration.ToString());
            RemoteArguments.Add("-SkipRulesCompile");             // Use the rules assembly built locally
            RemoteArguments.Add("-ForceXmlConfigCache");          // Use the XML config cache built locally, since the remote won't have it
            RemoteArguments.Add(String.Format("-Log={0}", GetRemotePath(RemoteLogFile)));
            RemoteArguments.Add(String.Format("-Manifest={0}", GetRemotePath(RemoteManifestFile)));

            if (TargetDesc.ProjectFile != null)
            {
                RemoteArguments.Add(String.Format("-Project={0}", GetRemotePath(TargetDesc.ProjectFile)));
            }

            foreach (string LocalArgument in TargetDesc.AdditionalArguments)
            {
                int EqualsIdx = LocalArgument.IndexOf('=');
                if (EqualsIdx == -1)
                {
                    RemoteArguments.Add(LocalArgument);
                    continue;
                }

                string Key   = LocalArgument.Substring(0, EqualsIdx);
                string Value = LocalArgument.Substring(EqualsIdx + 1);

                if (Key.Equals("-Log", StringComparison.InvariantCultureIgnoreCase))
                {
                    // We are already writing to the local log file. The remote will produce a different log (RemoteLogFile)
                    continue;
                }
                if (Key.Equals("-Manifest", StringComparison.InvariantCultureIgnoreCase))
                {
                    LocalManifestFiles.Add(new FileReference(Value));
                    continue;
                }

                string RemoteArgument = LocalArgument;
                foreach (RemoteMapping Mapping in Mappings)
                {
                    if (Value.StartsWith(Mapping.LocalDirectory.FullName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        RemoteArgument = String.Format("{0}={1}", Key, GetRemotePath(Value));
                        break;
                    }
                }
                RemoteArguments.Add(RemoteArgument);
            }

            // Handle any per-platform setup that is required
            if (TargetDesc.Platform == UnrealTargetPlatform.IOS || TargetDesc.Platform == UnrealTargetPlatform.TVOS)
            {
                // Always generate a .stub
                RemoteArguments.Add("-CreateStub");

                // Get the provisioning data for this project
                IOSProvisioningData ProvisioningData = ((IOSPlatform)UEBuildPlatform.GetBuildPlatform(TargetDesc.Platform)).ReadProvisioningData(TargetDesc.ProjectFile);
                if (ProvisioningData == null || ProvisioningData.MobileProvisionFile == null)
                {
                    throw new BuildException("Unable to find mobile provision for {0}. See log for more information.", TargetDesc.Name);
                }

                // Create a local copy of the provision
                FileReference MobileProvisionFile = FileReference.Combine(TempDir, ProvisioningData.MobileProvisionFile.GetFileName());
                if (FileReference.Exists(MobileProvisionFile))
                {
                    FileReference.SetAttributes(MobileProvisionFile, FileAttributes.Normal);
                }
                FileReference.Copy(ProvisioningData.MobileProvisionFile, MobileProvisionFile, true);
                Log.TraceInformation("[Remote] Uploading {0}", MobileProvisionFile);
                UploadFile(MobileProvisionFile);

                // Extract the certificate for the project
                FileReference CertificateFile = FileReference.Combine(TempDir, "Certificate.p12");
                if (!FileReference.Exists(CertificateFile))
                {
                    StringBuilder Arguments = new StringBuilder("ExportCertificate");
                    if (TargetDesc.ProjectFile == null)
                    {
                        Arguments.AppendFormat(" \"{0}\"", UnrealBuildTool.EngineSourceDirectory);
                    }
                    else
                    {
                        Arguments.AppendFormat(" \"{0}\"", TargetDesc.ProjectFile.Directory);
                    }
                    Arguments.AppendFormat(" -certificate \"{0}\"", CertificateFile);

                    ProcessStartInfo StartInfo = new ProcessStartInfo();
                    StartInfo.FileName  = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "DotNET", "IOS", "IPhonePackager.exe").FullName;
                    StartInfo.Arguments = Arguments.ToString();
                    if (Utils.RunLocalProcessAndLogOutput(StartInfo) != 0)
                    {
                        throw new BuildException("IphonePackager failed.");
                    }
                }

                // Upload the certificate to the remote
                Log.TraceInformation("[Remote] Uploading {0}", CertificateFile);
                UploadFile(CertificateFile);

                // Tell the remote UBT instance to use them
                RemoteArguments.Add(String.Format("-ImportProvision={0}", GetRemotePath(MobileProvisionFile)));
                RemoteArguments.Add(String.Format("-ImportCertificate={0}", GetRemotePath(CertificateFile)));
                RemoteArguments.Add(String.Format("-ImportCertificatePassword=A"));
            }

            // Upload the workspace files
            Log.TraceInformation("[Remote] Uploading workspace files");
            UploadWorkspace(TempDir);

            // Fixup permissions on any shell scripts
            Execute(RemoteBaseDir, String.Format("chmod +x {0}/Build/BatchFiles/Mac/*.sh", EscapeShellArgument(GetRemotePath(UnrealBuildTool.EngineDirectory))));

            // Execute the compile
            Log.TraceInformation("[Remote] Executing build");

            StringBuilder BuildCommandLine = new StringBuilder("Engine/Build/BatchFiles/Mac/Build.sh");

            foreach (string RemoteArgument in RemoteArguments)
            {
                BuildCommandLine.AppendFormat(" {0}", EscapeShellArgument(RemoteArgument));
            }

            int Result = Execute(GetRemotePath(UnrealBuildTool.RootDirectory), BuildCommandLine.ToString());

            if (Result != 0)
            {
                if (RemoteLogFile != null)
                {
                    Log.TraceInformation("[Remote] Downloading {0}", RemoteLogFile);
                    DownloadFile(RemoteLogFile);
                }
                return(false);
            }

            // Download the manifest
            Log.TraceInformation("[Remote] Downloading {0}", RemoteManifestFile);
            DownloadFile(RemoteManifestFile);

            // Convert the manifest to local form
            BuildManifest Manifest = Utils.ReadClass <BuildManifest>(RemoteManifestFile.FullName);

            for (int Idx = 0; Idx < Manifest.BuildProducts.Count; Idx++)
            {
                Manifest.BuildProducts[Idx] = GetLocalPath(Manifest.BuildProducts[Idx]).FullName;
            }

            // Download the files from the remote
            if (TargetDesc.AdditionalArguments.Any(x => x.Equals("-GenerateManifest", StringComparison.InvariantCultureIgnoreCase)))
            {
                LocalManifestFiles.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "Manifest.xml"));
            }
            else
            {
                Log.TraceInformation("[Remote] Downloading build products");

                List <FileReference> FilesToDownload = new List <FileReference>();
                FilesToDownload.Add(RemoteLogFile);
                FilesToDownload.AddRange(Manifest.BuildProducts.Select(x => new FileReference(x)));
                DownloadFiles(FilesToDownload);
            }

            // Write out all the local manifests
            foreach (FileReference LocalManifestFile in LocalManifestFiles)
            {
                Log.TraceInformation("[Remote] Writing {0}", LocalManifestFile);
                Utils.WriteClass <BuildManifest>(Manifest, LocalManifestFile.FullName, "");
            }
            return(true);
        }
Example #6
0
        /// <summary>
        /// Parse a list of target descriptors from the command line
        /// </summary>
        /// <param name="Arguments">Command-line arguments</param>
        /// <param name="ProjectFile">The project file, if already set. May be updated if not.</param>
        /// <returns>List of target descriptors</returns>
        public static List <TargetDescriptor> ParseCommandLine(string[] Arguments, ref FileReference ProjectFile)
        {
            UnrealTargetPlatform      Platform      = UnrealTargetPlatform.Unknown;
            UnrealTargetConfiguration Configuration = UnrealTargetConfiguration.Unknown;
            List <string>             TargetNames   = new List <string>();
            List <TargetType>         TargetTypes   = new List <TargetType>();
            string            Architecture          = null;
            List <OnlyModule> OnlyModules           = new List <OnlyModule>();
            FileReference     ForeignPlugin         = null;
            string            ForceReceiptFileName  = null;

            // Settings for creating/using static libraries for the engine
            for (int ArgumentIndex = 0; ArgumentIndex < Arguments.Length; ArgumentIndex++)
            {
                string Argument = Arguments[ArgumentIndex];
                if (!Argument.StartsWith("-"))
                {
                    UnrealTargetPlatform ParsedPlatform;
                    if (Enum.TryParse(Argument, true, out ParsedPlatform) && ParsedPlatform != UnrealTargetPlatform.Unknown)
                    {
                        if (Platform != UnrealTargetPlatform.Unknown)
                        {
                            throw new BuildException("Multiple platforms specified on command line (first {0}, then {1})", Platform, ParsedPlatform);
                        }
                        Platform = ParsedPlatform;
                        continue;
                    }

                    UnrealTargetConfiguration ParsedConfiguration;
                    if (Enum.TryParse(Argument, true, out ParsedConfiguration) && ParsedConfiguration != UnrealTargetConfiguration.Unknown)
                    {
                        if (Configuration != UnrealTargetConfiguration.Unknown)
                        {
                            throw new BuildException("Multiple configurations specified on command line (first {0}, then {1})", Configuration, ParsedConfiguration);
                        }
                        Configuration = ParsedConfiguration;
                        continue;
                    }

                    // Make sure the target name is valid. It may be the path to a project file.
                    if (Argument.IndexOfAny(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar, '.' }) == -1)
                    {
                        TargetNames.Add(Argument);
                    }
                }
                else
                {
                    string Value;
                    if (ParseArgumentValue(Argument, "-TargetType=", out Value))
                    {
                        TargetType Type;
                        if (!Enum.TryParse(Value, true, out Type))
                        {
                            throw new BuildException("Invalid target type: '{0}'", Value);
                        }
                        TargetTypes.Add(Type);
                    }
                    else if (ParseArgumentValue(Argument, "-Module=", out Value))
                    {
                        OnlyModules.Add(new OnlyModule(Value));
                    }
                    else if (ParseArgumentValue(Argument, "-ModuleWithSuffix=", out Value))
                    {
                        int SuffixIdx = Value.LastIndexOf(',');
                        if (SuffixIdx == -1)
                        {
                            throw new BuildException("Missing suffix argument from -ModuleWithSuffix=Name,Suffix");
                        }
                        OnlyModules.Add(new OnlyModule(Value.Substring(0, SuffixIdx), Value.Substring(SuffixIdx + 1)));
                    }
                    else if (ParseArgumentValue(Argument, "-Plugin=", out Value))
                    {
                        if (ForeignPlugin != null)
                        {
                            throw new BuildException("Only one foreign plugin to compile may be specified per invocation");
                        }
                        ForeignPlugin = new FileReference(Value);
                    }
                    else if (ParseArgumentValue(Argument, "-Receipt=", out Value))
                    {
                        ForceReceiptFileName = Value;
                    }
                    else
                    {
                        switch (Arguments[ArgumentIndex].ToUpperInvariant())
                        {
                        case "-MODULE":
                            throw new BuildException("'-Module <Name>' syntax is no longer supported on the command line. Use '-Module=<Name>' instead.");

                        case "-MODULEWITHSUFFIX":
                            throw new BuildException("'-ModuleWithSuffix <Name> <Suffix>' syntax is no longer supported on the command line. Use '-Module=<Name>,<Suffix>' instead.");

                        case "-PLUGIN":
                            throw new BuildException("'-Plugin <Path>' syntax is no longer supported on the command line. Use '-Plugin=<Path>' instead.");

                        case "-RECEIPT":
                            throw new BuildException("'-Receipt <Path>' syntax is no longer supported on the command line. Use '-Receipt=<Path>' instead.");
                        }
                    }
                }
            }

            if (Platform == UnrealTargetPlatform.Unknown)
            {
                throw new BuildException("Couldn't find platform name.");
            }
            if (Configuration == UnrealTargetConfiguration.Unknown)
            {
                throw new BuildException("Couldn't determine configuration name.");
            }

            if (Architecture == null)
            {
                Architecture = UEBuildPlatform.GetBuildPlatform(Platform).GetDefaultArchitecture(ProjectFile);
            }

            // Create all the target descriptors for targets specified by type
            foreach (TargetType Type in TargetTypes)
            {
                if (ProjectFile == null)
                {
                    throw new BuildException("-TargetType=... requires a project file to be specified");
                }
                else
                {
                    TargetNames.Add(RulesCompiler.CreateProjectRulesAssembly(ProjectFile).GetTargetNameByType(Type, Platform, Configuration, Architecture, ProjectFile, new ReadOnlyBuildVersion(BuildVersion.ReadDefault())));
                }
            }

            // Create all the target descriptor
            List <TargetDescriptor> Targets = new List <TargetDescriptor>();

            foreach (string TargetName in TargetNames)
            {
                // If a project file was not specified see if we can find one
                if (ProjectFile == null && UProjectInfo.TryGetProjectForTarget(TargetName, out ProjectFile))
                {
                    Log.TraceVerbose("Found project file for {0} - {1}", TargetName, ProjectFile);
                }

                TargetDescriptor Target = new TargetDescriptor(ProjectFile, TargetName, Platform, Configuration, Architecture);
                Target.OnlyModules          = OnlyModules;
                Target.ForeignPlugin        = ForeignPlugin;
                Target.ForceReceiptFileName = ForceReceiptFileName;
                Targets.Add(Target);
            }

            // Make sure we could parse something
            if (Targets.Count == 0)
            {
                throw new BuildException("No target name was specified on the command-line.");
            }
            return(Targets);
        }
        /// <summary>
        /// Parse a list of target descriptors from the command line
        /// </summary>
        /// <param name="Arguments">Command-line arguments</param>
        /// <param name="bUsePrecompiled">Whether to use a precompiled engine distribution</param>
        /// <param name="bSkipRulesCompile">Whether to skip compiling rules assemblies</param>
        /// <param name="TargetDescriptors">List of target descriptors</param>
        public static void ParseSingleCommandLine(CommandLineArguments Arguments, bool bUsePrecompiled, bool bSkipRulesCompile, List <TargetDescriptor> TargetDescriptors)
        {
            List <UnrealTargetPlatform>      Platforms      = new List <UnrealTargetPlatform>();
            List <UnrealTargetConfiguration> Configurations = new List <UnrealTargetConfiguration>();
            List <string> TargetNames = new List <string>();
            FileReference ProjectFile = Arguments.GetFileReferenceOrDefault("-Project=", null);

            // Settings for creating/using static libraries for the engine
            for (int ArgumentIndex = 0; ArgumentIndex < Arguments.Count; ArgumentIndex++)
            {
                string Argument = Arguments[ArgumentIndex];
                if (Argument.Length > 0 && Argument[0] != '-')
                {
                    // Mark this argument as used. We'll interpret it as one thing or another.
                    Arguments.MarkAsUsed(ArgumentIndex);

                    // Check if it's a project file argument
                    if (Argument.EndsWith(".uproject", StringComparison.OrdinalIgnoreCase))
                    {
                        FileReference NewProjectFile = new FileReference(Argument);
                        if (ProjectFile != null && ProjectFile != NewProjectFile)
                        {
                            throw new BuildException("Multiple project files specified on command line (first {0}, then {1})", ProjectFile, NewProjectFile);
                        }
                        ProjectFile = new FileReference(Argument);
                        continue;
                    }

                    // Split it into separate arguments
                    string[] InlineArguments = Argument.Split('+');

                    // Try to parse them as platforms
                    UnrealTargetPlatform ParsedPlatform;
                    if (UnrealTargetPlatform.TryParse(InlineArguments[0], out ParsedPlatform))
                    {
                        Platforms.Add(ParsedPlatform);
                        for (int InlineArgumentIdx = 1; InlineArgumentIdx < InlineArguments.Length; InlineArgumentIdx++)
                        {
                            Platforms.Add(UnrealTargetPlatform.Parse(InlineArguments[InlineArgumentIdx]));
                        }
                        continue;
                    }

                    // Try to parse them as configurations
                    UnrealTargetConfiguration ParsedConfiguration;
                    if (Enum.TryParse(InlineArguments[0], true, out ParsedConfiguration))
                    {
                        Configurations.Add(ParsedConfiguration);
                        for (int InlineArgumentIdx = 1; InlineArgumentIdx < InlineArguments.Length; InlineArgumentIdx++)
                        {
                            string InlineArgument = InlineArguments[InlineArgumentIdx];
                            if (!Enum.TryParse(InlineArgument, true, out ParsedConfiguration))
                            {
                                throw new BuildException("Invalid configuration '{0}'", InlineArgument);
                            }
                            Configurations.Add(ParsedConfiguration);
                        }
                        continue;
                    }

                    // Otherwise assume they are target names
                    TargetNames.AddRange(InlineArguments);
                }
            }

            if (Platforms.Count == 0)
            {
                throw new BuildException("No platforms specified for target");
            }
            if (Configurations.Count == 0)
            {
                throw new BuildException("No configurations specified for target");
            }

            // Make sure the project file exists, and make sure we're using the correct case.
            if (ProjectFile != null)
            {
                FileInfo ProjectFileInfo = FileUtils.FindCorrectCase(ProjectFile.ToFileInfo());
                if (!ProjectFileInfo.Exists)
                {
                    throw new BuildException("Unable to find project '{0}'.", ProjectFile);
                }
                ProjectFile = new FileReference(ProjectFileInfo);
            }

            // Expand all the platforms, architectures and configurations
            foreach (UnrealTargetPlatform Platform in Platforms)
            {
                // Make sure the platform is valid
                if (!InstalledPlatformInfo.IsValid(null, Platform, null, EProjectType.Code, InstalledPlatformState.Downloaded))
                {
                    if (!InstalledPlatformInfo.IsValid(null, Platform, null, EProjectType.Code, InstalledPlatformState.Supported))
                    {
                        throw new BuildException("The {0} platform is not supported from this engine distribution.", Platform);
                    }
                    else
                    {
                        throw new BuildException("Missing files required to build {0} targets. Enable {0} as an optional download component in the Epic Games Launcher.", Platform);
                    }
                }

                // Parse the architecture parameter, or get the default for the platform
                List <string> Architectures = new List <string>(Arguments.GetValues("-Architecture=", '+'));
                if (Architectures.Count == 0)
                {
                    Architectures.Add(UEBuildPlatform.GetBuildPlatform(Platform).GetDefaultArchitecture(ProjectFile));
                }

                foreach (string Architecture in Architectures)
                {
                    foreach (UnrealTargetConfiguration Configuration in Configurations)
                    {
                        // Create all the target descriptors for targets specified by type
                        foreach (string TargetTypeString in Arguments.GetValues("-TargetType="))
                        {
                            TargetType TargetType;
                            if (!Enum.TryParse(TargetTypeString, out TargetType))
                            {
                                throw new BuildException("Invalid target type '{0}'", TargetTypeString);
                            }

                            if (ProjectFile == null)
                            {
                                throw new BuildException("-TargetType=... requires a project file to be specified");
                            }
                            else
                            {
                                TargetNames.Add(RulesCompiler.CreateProjectRulesAssembly(ProjectFile, bUsePrecompiled, bSkipRulesCompile).GetTargetNameByType(TargetType, Platform, Configuration, Architecture, ProjectFile));
                            }
                        }

                        // Make sure we could parse something
                        if (TargetNames.Count == 0)
                        {
                            throw new BuildException("No target name was specified on the command-line.");
                        }

                        // Create all the target descriptors
                        foreach (string TargetName in TargetNames)
                        {
                            // If a project file was not specified see if we can find one
                            if (ProjectFile == null && NativeProjects.TryGetProjectForTarget(TargetName, out ProjectFile))
                            {
                                Log.TraceVerbose("Found project file for {0} - {1}", TargetName, ProjectFile);
                            }

                            // Create the target descriptor
                            TargetDescriptors.Add(new TargetDescriptor(ProjectFile, TargetName, Platform, Configuration, Architecture, Arguments));
                        }
                    }
                }
            }
        }
Example #8
0
        /**
         * Find all third party and private header includes in public engine headers.
         **/
        public static void FindThirdPartyIncludes(UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration)
        {
            Log.TraceInformation("Looking for third party header includes in public engine header files (this may take a few minutes)...");

            TargetInfo    Target           = new TargetInfo(Platform, Configuration);
            List <string> UncheckedModules = new List <string>();

            EngineHeaders     = new List <Header>();
            ThirdPartyHeaders = new List <Header>();

            // Find all modules referenced by the current target
            List <string> ModuleFileNames = RulesCompiler.FindAllRulesSourceFiles(RulesCompiler.RulesFileType.Module, AdditionalSearchPaths: null);

            foreach (string ModuleFileName in ModuleFileNames)
            {
                string ModuleName = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(ModuleFileName));
                try
                {
                    string      UnusedModuleFilename;
                    ModuleRules RulesObject    = RulesCompiler.CreateModuleRules(ModuleName, Target, out UnusedModuleFilename);
                    bool        bEngineHeaders = RulesObject.Type != ModuleRules.ModuleType.External;
                    foreach (string SystemIncludePath in RulesObject.PublicSystemIncludePaths)
                    {
                        FindHeaders(SystemIncludePath, bEngineHeaders ? EngineHeaders : ThirdPartyHeaders, bEngineHeaders);
                    }
                    foreach (string PublicIncludePath in RulesObject.PublicIncludePaths)
                    {
                        FindHeaders(PublicIncludePath, bEngineHeaders ? EngineHeaders : ThirdPartyHeaders, bEngineHeaders);
                    }
                }
                catch (Exception)
                {
                    // Ignore, some modules may fail here.
                    UncheckedModules.Add(ModuleName);
                }
            }

            // Search for illegal includes.
            List <IncludePath> ThirdPartyIncludes = new List <IncludePath>();
            List <IncludePath> PrivateIncludes    = new List <IncludePath>();

            CheckIfThirdPartyHeadersAreIncluded(ThirdPartyIncludes, PrivateIncludes);

            // List all of the included 3rd party headers unless their name matches with any of the engine header.
            if (ThirdPartyIncludes.Count > 0)
            {
                // Remove ambiguous headers
                for (int IncludeIndex = ThirdPartyIncludes.Count - 1; IncludeIndex >= 0; --IncludeIndex)
                {
                    if (FindHeader(EngineHeaders, ThirdPartyIncludes[IncludeIndex].OtherHeader.Name) != null)
                    {
                        ThirdPartyIncludes.RemoveAt(IncludeIndex);
                    }
                }
                if (ThirdPartyIncludes.Count > 0)
                {
                    Log.TraceInformation("Warning: Found {0} third party header includes in public engine headers. Third party headers should only be included in private engine headers.", ThirdPartyIncludes.Count);
                    foreach (IncludePath HeaderPath in ThirdPartyIncludes)
                    {
                        if (FindHeader(EngineHeaders, HeaderPath.OtherHeader.Name) == null)
                        {
                            Log.TraceInformation("{0} includes {1}.", HeaderPath.PublicHeaderPath, HeaderPath.OtherHeader.Path);
                        }
                    }
                }
            }

            // List all private engine headers included from public engine headers
            if (PrivateIncludes.Count > 0)
            {
                Log.TraceInformation("Warning: Found {0} private engine header includes in public engine headers. Private engine headers should not be included in public engine headers.", PrivateIncludes.Count);
            }
            foreach (IncludePath HeaderPath in PrivateIncludes)
            {
                Log.TraceInformation("{0} includes {1}.", HeaderPath.PublicHeaderPath, HeaderPath.OtherHeader.Path);
            }
            if (PrivateIncludes.Count == 0 && ThirdPartyIncludes.Count == 0)
            {
                Log.TraceInformation("Finished looking for third party includes. Nothing found.");
            }
            if (UncheckedModules.Count > 0)
            {
                Log.TraceInformation("Warning: The following modules could not be checked (exception while trying to create ModuleRules object):");
                for (int ModuleIndex = 0; ModuleIndex < UncheckedModules.Count; ++ModuleIndex)
                {
                    Log.TraceInformation("  {0}", UncheckedModules[ModuleIndex]);
                }
            }
        }
Example #9
0
        private void AddProjectsForAllTargets(
            PlatformProjectGeneratorCollection PlatformProjectGenerators,
            List <FileReference> AllGames,
            out ProjectFile EngineProject,
            out List <ProjectFile> GameProjects,
            out Dictionary <FileReference, ProjectFile> ProgramProjects)
        {
            // As we're creating project files, we'll also keep track of whether we created an "engine" project and return that if we have one
            EngineProject   = null;
            GameProjects    = new List <ProjectFile>();
            ProgramProjects = new Dictionary <FileReference, ProjectFile>();

            // Find all of the target files.  This will filter out any modules or targets that don't
            // belong to platforms we're generating project files for.
            List <FileReference> AllTargetFiles = DiscoverTargets(AllGames);

            // Sort the targets by name. When we have multiple targets of a given type for a project, we'll use the order to determine which goes in the primary project file (so that client names with a suffix will go into their own project).
            AllTargetFiles = AllTargetFiles.OrderBy(x => x.FullName, StringComparer.OrdinalIgnoreCase).ToList();

            foreach (FileReference TargetFilePath in AllTargetFiles)
            {
                string TargetName = TargetFilePath.GetFileNameWithoutAnyExtensions();

                // Check to see if this is an Engine target.  That is, the target is located under the "Engine" folder
                bool IsEngineTarget           = false;
                bool IsEnterpriseTarget       = false;
                bool WantProjectFileForTarget = true;
                if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
                {
                    // This is an engine target
                    IsEngineTarget = true;

                    if (TargetFilePath.IsUnderDirectory(EngineSourceProgramsDirectory))
                    {
                        WantProjectFileForTarget = IncludeEnginePrograms;
                    }
                    else if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EngineSourceDirectory))
                    {
                        WantProjectFileForTarget = bIncludeEngineSource;
                    }
                }
                else if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EnterpriseSourceDirectory))
                {
                    // This is an enterprise target
                    IsEnterpriseTarget = true;

                    if (TargetFilePath.IsUnderDirectory(EnterpriseSourceProgramsDirectory))
                    {
                        WantProjectFileForTarget = bIncludeEnterpriseSource && IncludeEnginePrograms;
                    }
                    else
                    {
                        WantProjectFileForTarget = bIncludeEnterpriseSource;
                    }
                }

                if (WantProjectFileForTarget)
                {
                    RulesAssembly RulesAssembly;

                    FileReference CheckProjectFile =
                        AllGames.FirstOrDefault(x => TargetFilePath.IsUnderDirectory(x.Directory));
                    if (CheckProjectFile == null)
                    {
                        if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EnterpriseDirectory))
                        {
                            RulesAssembly = RulesCompiler.CreateEnterpriseRulesAssembly(false, false);
                        }
                        else
                        {
                            RulesAssembly = RulesCompiler.CreateEngineRulesAssembly(false, false);
                        }
                    }
                    else
                    {
                        RulesAssembly = RulesCompiler.CreateProjectRulesAssembly(CheckProjectFile, false, false);
                    }

                    // Create target rules for all of the platforms and configuration combinations that we want to enable support for.
                    // Just use the current platform as we only need to recover the target type and both should be supported for all targets...
                    TargetRules TargetRulesObject = RulesAssembly.CreateTargetRules(TargetName,
                                                                                    BuildHostPlatform.Current.Platform, UnrealTargetConfiguration.Development, "", CheckProjectFile,
                                                                                    null);

                    bool IsProgramTarget = false;

                    DirectoryReference GameFolder = null;
                    string             ProjectFileNameBase;
                    if (TargetRulesObject.Type == TargetType.Program)
                    {
                        IsProgramTarget     = true;
                        ProjectFileNameBase = TargetName;
                    }
                    else if (IsEngineTarget)
                    {
                        ProjectFileNameBase = EngineProjectFileNameBase;
                    }
                    else if (IsEnterpriseTarget)
                    {
                        ProjectFileNameBase = EnterpriseProjectFileNameBase;
                    }
                    else
                    {
                        // Figure out which game project this target belongs to
                        FileReference ProjectInfo = FindGameContainingFile(AllGames, TargetFilePath);
                        if (ProjectInfo == null)
                        {
                            throw new BuildException("Found a non-engine target file (" + TargetFilePath +
                                                     ") that did not exist within any of the known game folders");
                        }

                        GameFolder          = ProjectInfo.Directory;
                        ProjectFileNameBase = ProjectInfo.GetFileNameWithoutExtension();
                    }

                    // Get the suffix to use for this project file. If we have multiple targets of the same type, we'll have to split them out into separate IDE project files.
                    string GeneratedProjectName = TargetRulesObject.GeneratedProjectName;
                    if (GeneratedProjectName == null)
                    {
                        ProjectFile ExistingProjectFile;
                        if (ProjectFileMap.TryGetValue(GetRiderProjectLocation(ProjectFileNameBase), out ExistingProjectFile) &&
                            ExistingProjectFile.ProjectTargets.Any(x => x.TargetRules.Type == TargetRulesObject.Type))
                        {
                            GeneratedProjectName = TargetRulesObject.Name;
                        }
                        else
                        {
                            GeneratedProjectName = ProjectFileNameBase;
                        }
                    }

                    FileReference ProjectFilePath = GetRiderProjectLocation(GeneratedProjectName);
                    if (TargetRulesObject.Type == TargetType.Game || TargetRulesObject.Type == TargetType.Client ||
                        TargetRulesObject.Type == TargetType.Server)
                    {
                        // Allow platforms to generate stub projects here...
                        PlatformProjectGenerators.GenerateGameProjectStubs(
                            InGenerator: this,
                            InTargetName: TargetName,
                            InTargetFilepath: TargetFilePath.FullName,
                            InTargetRules: TargetRulesObject,
                            InPlatforms: SupportedPlatforms,
                            InConfigurations: SupportedConfigurations);
                    }

                    DirectoryReference BaseFolder;
                    if (IsProgramTarget)
                    {
                        BaseFolder = TargetFilePath.Directory;
                    }
                    else if (IsEngineTarget)
                    {
                        BaseFolder = UnrealBuildTool.EngineDirectory;
                    }
                    else if (IsEnterpriseTarget)
                    {
                        BaseFolder = UnrealBuildTool.EnterpriseDirectory;
                    }
                    else
                    {
                        BaseFolder = GameFolder;
                    }

                    bool        bProjectAlreadyExisted;
                    ProjectFile ProjectFile = FindOrAddProject(ProjectFilePath, BaseFolder,
                                                               true, out bProjectAlreadyExisted);
                    ProjectFile.IsForeignProject =
                        CheckProjectFile != null && !NativeProjects.IsNativeProject(CheckProjectFile);
                    ProjectFile.IsGeneratedProject = true;
                    ProjectFile.IsStubProject      = UnrealBuildTool.IsProjectInstalled();
                    if (TargetRulesObject.bBuildInSolutionByDefault.HasValue)
                    {
                        ProjectFile.ShouldBuildByDefaultForSolutionTargets =
                            TargetRulesObject.bBuildInSolutionByDefault.Value;
                    }

                    // Add the project to the right output list
                    if (IsProgramTarget)
                    {
                        ProgramProjects[TargetFilePath] = ProjectFile;
                    }
                    else if (IsEngineTarget)
                    {
                        EngineProject = ProjectFile;
                        if (UnrealBuildTool.IsEngineInstalled())
                        {
                            // Allow engine projects to be created but not built for Installed Engine builds
                            EngineProject.IsForeignProject   = false;
                            EngineProject.IsGeneratedProject = true;
                            EngineProject.IsStubProject      = true;
                        }
                    }
                    else if (IsEnterpriseTarget)
                    {
                        ProjectFile EnterpriseProject = ProjectFile;
                        if (UnrealBuildTool.IsEnterpriseInstalled())
                        {
                            // Allow enterprise projects to be created but not built for Installed Engine builds
                            EnterpriseProject.IsForeignProject   = false;
                            EnterpriseProject.IsGeneratedProject = true;
                            EnterpriseProject.IsStubProject      = true;
                        }
                    }
                    else
                    {
                        if (!bProjectAlreadyExisted)
                        {
                            GameProjects.Add(ProjectFile);

                            // Add the .uproject file for this game/template
                            FileReference UProjectFilePath =
                                FileReference.Combine(BaseFolder, ProjectFileNameBase + ".uproject");
                            if (FileReference.Exists(UProjectFilePath))
                            {
                                ProjectFile.AddFileToProject(UProjectFilePath, BaseFolder);
                            }
                            else
                            {
                                throw new BuildException(
                                          "Not expecting to find a game with no .uproject file.  File '{0}' doesn't exist",
                                          UProjectFilePath);
                            }
                        }
                    }

                    foreach (ProjectTarget ExistingProjectTarget in ProjectFile.ProjectTargets)
                    {
                        if (ExistingProjectTarget.TargetRules.Type == TargetRulesObject.Type)
                        {
                            throw new BuildException(
                                      "Not expecting project {0} to already have a target rules of with configuration name {1} ({2}) while trying to add: {3}",
                                      ProjectFilePath, TargetRulesObject.Type.ToString(),
                                      ExistingProjectTarget.TargetRules.ToString(), TargetRulesObject.ToString());
                        }

                        // Not expecting to have both a game and a program in the same project.  These would alias because we share the project and solution configuration names (just because it makes sense to)
                        if ((ExistingProjectTarget.TargetRules.Type == TargetType.Game &&
                             TargetRulesObject.Type == TargetType.Program) ||
                            (ExistingProjectTarget.TargetRules.Type == TargetType.Program &&
                             TargetRulesObject.Type == TargetType.Game))
                        {
                            throw new BuildException(
                                      "Not expecting project {0} to already have a Game/Program target ({1}) associated with it while trying to add: {2}",
                                      ProjectFilePath, ExistingProjectTarget.TargetRules.ToString(),
                                      TargetRulesObject.ToString());
                        }
                    }

                    ProjectTarget ProjectTarget = new ProjectTarget()
                    {
                        TargetRules           = TargetRulesObject,
                        TargetFilePath        = TargetFilePath,
                        ProjectFilePath       = ProjectFilePath,
                        UnrealProjectFilePath = CheckProjectFile,
                        SupportedPlatforms    = TargetRulesObject.GetSupportedPlatforms()
                                                .Where(x => UEBuildPlatform.GetBuildPlatform(x, true) != null).ToArray(),
                        CreateRulesDelegate = (Platform, Configuration) =>
                                              RulesAssembly.CreateTargetRules(TargetName, Platform, Configuration, "", CheckProjectFile,
                                                                              null)
                    };

                    ProjectFile.ProjectTargets.Add(ProjectTarget);

                    // Make sure the *.Target.cs file is in the project.
                    ProjectFile.AddFileToProject(TargetFilePath, BaseFolder);

                    Log.TraceVerbose("Generating target {0} for {1}", TargetRulesObject.Type.ToString(),
                                     ProjectFilePath);
                }
            }
        }