/// <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); }
public static List <TargetDescriptor> ParseCommandLine(string[] Arguments, ref FileReference ProjectFile) { UnrealTargetPlatform Platform = UnrealTargetPlatform.Unknown; UnrealTargetConfiguration Configuration = UnrealTargetConfiguration.Unknown; List <string> TargetNames = new List <string>(); string Architecture = null; string RemoteRoot = null; List <OnlyModule> OnlyModules = new List <OnlyModule>(); FileReference ForeignPlugin = null; string ForceReceiptFileName = null; // If true, the recompile was launched by the editor. bool bIsEditorRecompile = false; // Settings for creating/using static libraries for the engine List <string> PossibleTargetNames = new List <string>(); 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; } PossibleTargetNames.Add(Argument); } else { switch (Arguments[ArgumentIndex].ToUpperInvariant()) { case "-MODULE": // Specifies a module to recompile. Can be specified more than once on the command-line to compile multiple specific modules. { if (ArgumentIndex + 1 >= Arguments.Length) { throw new BuildException("Expected module name after -Module argument, but found nothing."); } string OnlyModuleName = Arguments[++ArgumentIndex]; OnlyModules.Add(new OnlyModule(OnlyModuleName)); } break; case "-MODULEWITHSUFFIX": { // Specifies a module name to compile along with a suffix to append to the DLL file name. Can be specified more than once on the command-line to compile multiple specific modules. if (ArgumentIndex + 2 >= Arguments.Length) { throw new BuildException("Expected module name and module suffix -ModuleWithSuffix argument"); } string OnlyModuleName = Arguments[++ArgumentIndex]; string OnlyModuleSuffix = Arguments[++ArgumentIndex]; OnlyModules.Add(new OnlyModule(OnlyModuleName, OnlyModuleSuffix)); } break; case "-PLUGIN": { if (ArgumentIndex + 1 >= Arguments.Length) { throw new BuildException("Expected plugin filename after -Plugin argument, but found nothing."); } if (ForeignPlugin != null) { throw new BuildException("Only one foreign plugin to compile may be specified per invocation"); } ForeignPlugin = new FileReference(Arguments[++ArgumentIndex]); } break; case "-RECEIPT": { if (ArgumentIndex + 1 >= Arguments.Length) { throw new BuildException("Expected path to the generated receipt after -Receipt argument, but found nothing."); } ForceReceiptFileName = Arguments[++ArgumentIndex]; } break; // -RemoteRoot <RemoteRoot> sets where the generated binaries are CookerSynced. case "-REMOTEROOT": if (ArgumentIndex + 1 >= Arguments.Length) { throw new BuildException("Expected path after -RemoteRoot argument, but found nothing."); } ArgumentIndex++; if (Arguments[ArgumentIndex].StartsWith("xe:\\") == true) { RemoteRoot = Arguments[ArgumentIndex].Substring("xe:\\".Length); } else if (Arguments[ArgumentIndex].StartsWith("devkit:\\") == true) { RemoteRoot = Arguments[ArgumentIndex].Substring("devkit:\\".Length); } break; case "-DEPLOY": // Does nothing at the moment... break; case "-EDITORRECOMPILE": { bIsEditorRecompile = true; } break; default: break; } } } if (Platform == UnrealTargetPlatform.Unknown) { throw new BuildException("Couldn't find platform name."); } if (Configuration == UnrealTargetConfiguration.Unknown) { throw new BuildException("Couldn't determine configuration name."); } List <TargetDescriptor> Targets = new List <TargetDescriptor>(); if (PossibleTargetNames.Count > 0) { // We have possible targets! string PossibleTargetName = PossibleTargetNames[0]; // If Engine is installed, the PossibleTargetName could contain a path string TargetName = PossibleTargetName; // 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); } UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatform(Platform); if (Architecture == null) { Architecture = BuildPlatform.GetDefaultArchitecture(ProjectFile); } Targets.Add(new TargetDescriptor() { ProjectFile = ProjectFile, TargetName = TargetName, Platform = Platform, Configuration = Configuration, Architecture = Architecture, bIsEditorRecompile = bIsEditorRecompile, RemoteRoot = RemoteRoot, OnlyModules = OnlyModules, ForeignPlugin = ForeignPlugin, ForceReceiptFileName = ForceReceiptFileName }); } if (Targets.Count == 0) { throw new BuildException("No target name was specified on the command-line."); } return(Targets); }
private FileReference GetExecutableFilename(ProjectFile Project, ProjectTarget Target, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration) { TargetRules TargetRulesObject = Target.TargetRules; FileReference TargetFilePath = Target.TargetFilePath; string TargetName = TargetFilePath == null?Project.ProjectFilePath.GetFileNameWithoutExtension() : TargetFilePath.GetFileNameWithoutAnyExtensions(); string UBTPlatformName = Platform.ToString(); string UBTConfigurationName = Configuration.ToString(); string ProjectName = Project.ProjectFilePath.GetFileNameWithoutExtension(); // Setup output path UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatform(Platform); // Figure out if this is a monolithic build bool bShouldCompileMonolithic = BuildPlatform.ShouldCompileMonolithicBinary(Platform); if (TargetRulesObject != null) { bShouldCompileMonolithic |= (Target.CreateRulesDelegate(Platform, Configuration).GetLegacyLinkType(Platform, Configuration) == TargetLinkType.Monolithic); } TargetType TargetRulesType = Target.TargetRules == null ? TargetType.Program : Target.TargetRules.Type; // Get the output directory DirectoryReference RootDirectory = UnrealBuildTool.EngineDirectory; if (TargetRulesType != TargetType.Program && (bShouldCompileMonolithic || TargetRulesObject.BuildEnvironment == TargetBuildEnvironment.Unique) && !TargetRulesObject.bOutputToEngineBinaries) { if (OnlyGameProject != null && TargetFilePath.IsUnderDirectory(OnlyGameProject.Directory)) { RootDirectory = OnlyGameProject.Directory; } else { FileReference ProjectFileName; if (UProjectInfo.TryGetProjectFileName(ProjectName, out ProjectFileName)) { RootDirectory = ProjectFileName.Directory; } } } if (TargetRulesType == TargetType.Program && (TargetRulesObject == null || !TargetRulesObject.bOutputToEngineBinaries)) { FileReference ProjectFileName; if (UProjectInfo.TryGetProjectForTarget(TargetName, out ProjectFileName)) { RootDirectory = ProjectFileName.Directory; } } // Get the output directory DirectoryReference OutputDirectory = DirectoryReference.Combine(RootDirectory, "Binaries", UBTPlatformName); // Get the executable name (minus any platform or config suffixes) string BaseExeName = TargetName; if (!bShouldCompileMonolithic && TargetRulesType != TargetType.Program) { // Figure out what the compiled binary will be called so that we can point the IDE to the correct file string TargetConfigurationName = TargetRulesType.ToString(); if (TargetConfigurationName != TargetType.Game.ToString() && TargetConfigurationName != TargetType.Program.ToString()) { BaseExeName = "UE4" + TargetConfigurationName; } } // Make the output file path string ExecutableFilename = FileReference.Combine(OutputDirectory, BaseExeName).ToString(); if ((Configuration != UnrealTargetConfiguration.DebugGame || bShouldCompileMonolithic)) { ExecutableFilename += "-" + UBTPlatformName + "-" + UBTConfigurationName; } ExecutableFilename += TargetRulesObject.Architecture; ExecutableFilename += BuildPlatform.GetBinaryExtension(UEBuildBinaryType.Executable); return(FileReference.MakeFromNormalizedFullPath(ExecutableFilename)); }