@echo off setlocal enabledelayedexpansion REM The %~dp0 specifier resolves to the path to the directory where this .bat is located in. REM We use this so that regardless of where the .bat file was executed from, we can change to REM directory relative to where we know the .bat is stored. pushd "%~dp0\..\..\Source" REM %1 is the game name REM %2 is the platform name REM %3 is the configuration name
IFEXIST ..\..\Engine\Binaries\DotNET\UnrealBuildTool.exe ( ..\..\Engine\Binaries\DotNET\UnrealBuildTool.exe %* -DEPLOY popd REM Ignore exit codes of 2 ("ECompilationResult.UpToDate") from UBT; it's not a failure. if "!ERRORLEVEL!"=="2" ( EXIT /B 0 )
EXIT /B !ERRORLEVEL! ) ELSE ( ECHO UnrealBuildTool.exe not found in ..\..\Engine\Binaries\DotNET\UnrealBuildTool.exe popd EXIT /B 999 )
# Example UnrealBuildTool.exe ThridPerson420 Win64 Development "C:\Users\visionsmile\Documents\Unreal Projects\Examples\ThridPerson420\ThridPerson420.uproject" -WaitMutex -FromMsBuild
// Engine\Source\Programs\UnrealBuildTools\UnrealBuildTool.cs privatestaticintMain(string[] Arguments) { // make sure we catch any exceptions and return an appropriate error code. // Some inner code already does this (to ensure the Mutex is released), // but we need something to cover all outer code as well. try { returnGuardedMain(Arguments); } catch (Exception Exception) { if (Log.IsInitialized()) { Log.TraceError("UnrealBuildTool Exception: " + Exception.ToString()); } if (ExtendedErrorCode != 0) { return ExtendedErrorCode; } return (int)ECompilationResult.OtherCompilationError; } }
if (UBTMakefile != null && !bIsGatheringBuild && bIsAssemblingBuild) { // If we've loaded a makefile, then we can fill target information from this file! Targets = UBTMakefile.Targets; } else { DateTime TargetInitStartTime = DateTime.UtcNow;
ReadOnlyBuildVersion Version = newReadOnlyBuildVersion(BuildVersion.ReadDefault());
///<summary> /// Constructor. Compiles a rules assembly from the given source files. ///</summary> ///<param name="BaseDir">The base directory for this assembly</param> ///<param name="Plugins">All the plugins included in this assembly</param> ///<param name="ModuleFiles">List of module files to compile</param> ///<param name="TargetFiles">List of target files to compile</param> ///<param name="ModuleFileToPluginInfo">Mapping of module file to the plugin that contains it</param> ///<param name="AssemblyFileName">The output path for the compiled assembly</param> ///<param name="bContainsEngineModules">Whether this assembly contains engine modules. Used to initialize the default value for ModuleRules.bTreatAsEngineModule.</param> ///<param name="bUseBackwardsCompatibleDefaults">Whether modules in this assembly should use backwards-compatible defaults.</param> ///<param name="bReadOnly">Whether the modules and targets in this assembly are installed, and should be created with the bUsePrecompiled flag set</param> ///<param name="bSkipCompile">Whether to skip compiling this assembly</param> ///<param name="Parent">The parent rules assembly</param> publicRulesAssembly(DirectoryReference BaseDir, IReadOnlyList<PluginInfo> Plugins, List<FileReference> ModuleFiles, List<FileReference> TargetFiles, Dictionary<FileReference, PluginInfo> ModuleFileToPluginInfo, FileReference AssemblyFileName, bool bContainsEngineModules, bool bUseBackwardsCompatibleDefaults, bool bReadOnly, bool bSkipCompile, RulesAssembly Parent) { this.BaseDir = BaseDir; this.Plugins = Plugins; this.ModuleFileToPluginInfo = ModuleFileToPluginInfo; this.bContainsEngineModules = bContainsEngineModules; this.bUseBackwardsCompatibleDefaults = bUseBackwardsCompatibleDefaults; this.bReadOnly = bReadOnly; this.Parent = Parent;
// Find all the source files List<FileReference> AssemblySourceFiles = new List<FileReference>(); AssemblySourceFiles.AddRange(ModuleFiles); AssemblySourceFiles.AddRange(TargetFiles);
///<summary> /// Creates a target rules object for the specified target name. ///</summary> ///<param name="TargetName">Name of the target</param> ///<param name="Platform">Platform being compiled</param> ///<param name="Configuration">Configuration being compiled</param> ///<param name="Architecture">Architecture being built</param> ///<param name="ProjectFile">Path to the project file for this target</param> ///<param name="Version">The current build version</param> ///<param name="Arguments">Command line arguments for this target</param> ///<param name="TargetFileName">The original source file name of the Target.cs file for this target</param> ///<returns>The build target rules for the specified target</returns> public TargetRules CreateTargetRules(string TargetName, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, string Architecture, FileReference ProjectFile, ReadOnlyBuildVersion Version, string[] Arguments, out FileReference TargetFileName) { // ignore conditional check code... // Return the target file name to the caller TargetFileName = TargetNameToTargetFile[TargetName]; // Currently, we expect the user's rules object type name to be the same as the module name + 'Target' string TargetTypeName = TargetName + "Target"; // The build module must define a type named '<TargetName>Target' that derives from our 'TargetRules' type. // 通过构造 TargetInfo 对象,将基本的编译环境信息传递给 `target.cs` 中定义的构造函数 return CreateTargetRulesInstance(TargetTypeName, new TargetInfo(TargetName, Platform, Configuration, Architecture, ProjectFile, Version), Arguments); }
/// Construct an instance of the given target rules ///<param name="TypeName">Type name of the target rules</param> ///<param name="TargetInfo">Target configuration information to pass to the constructor</param> ///<param name="Arguments">Command line arguments for this target</param> ///<returns>Instance of the corresponding TargetRules</returns> protected TargetRules CreateTargetRulesInstance(string TypeName, TargetInfo TargetInfo, string[] Arguments) { // The build module must define a type named '<TargetName>Target' that derives from our 'TargetRules' type. Type RulesType = CompiledAssembly.GetType(TypeName); if (RulesType == null) { thrownew BuildException("Expecting to find a type to be declared in a target rules named '{0}'. This type must derive from the 'TargetRules' type defined by Unreal Build Tool.", TypeName); }
// Create an instance of the module's rules object, and set some defaults before calling the constructor. TargetRules Rules = (TargetRules)FormatterServices.GetUninitializedObject(RulesType); Rules.bUseBackwardsCompatibleDefaults = bUseBackwardsCompatibleDefaults;
// Find the constructor ConstructorInfo Constructor = RulesType.GetConstructor(new Type[] { typeof(TargetInfo) }); if(Constructor == null) { thrownew BuildException("No constructor found on {0} which takes an argument of type TargetInfo.", RulesType.Name); }
// Invoke the regular constructor try { Constructor.Invoke(Rules, newobject[] { TargetInfo }); } catch (Exception Ex) { thrownew BuildException(Ex, "Unable to instantiate instance of '{0}' object type from compiled assembly '{1}'. Unreal Build Tool creates an instance of your module's 'Rules' object in order to find out about your module's requirements. The CLR exception details may provide more information: {2}", TypeName, Path.GetFileNameWithoutExtension(CompiledAssembly.Location), Ex.ToString()); }
///<summary> /// Setup target before build. This method finds dependencies, sets up global environment etc. ///</summary> publicvoidPreBuildSetup(UEToolChain TargetToolChain) { // Describe what's being built. Log.TraceVerbose("Building {0} - {1} - {2} - {3}", AppName, TargetName, Platform, Configuration);
// Setup the target's binaries. SetupBinaries();
// Setup the target's plugins SetupPlugins();
// Setup the custom build steps for this target SetupCustomBuildSteps();
// Add the plugin binaries to the build foreach (UEBuildPlugin Plugin in BuildPlugins) { foreach(UEBuildModuleCPP Module in Plugin.Modules) { AddModuleToBinary(Module); } }
// Add all of the extra modules, including game modules, that need to be compiled along // with this app. These modules are always statically linked in monolithic targets, but not necessarily linked to anything in modular targets, // and may still be required at runtime in order for the application to load and function properly! AddExtraModules();
// Create all the modules referenced by the existing binaries foreach(UEBuildBinary Binary in Binaries) { Binary.CreateAllDependentModules(FindOrCreateModuleByName); }
// Bind every referenced C++ module to a binary for (int Idx = 0; Idx < Binaries.Count; Idx++) { List<UEBuildModule> DependencyModules = Binaries[Idx].GetAllDependencyModules(true, true); foreach (UEBuildModuleCPP DependencyModule in DependencyModules.OfType<UEBuildModuleCPP>()) { if(DependencyModule.Binary == null) { AddModuleToBinary(DependencyModule); } } }
// Add all the modules to the target if necessary. if(Rules.bBuildAllModules) { AddAllValidModulesToTarget(); }
// Add the external and non-C++ referenced modules to the binaries that reference them. foreach (UEBuildModuleCPP Module in Modules.Values.OfType<UEBuildModuleCPP>()) { if(Module.Binary != null) { foreach (UEBuildModule ReferencedModule in Module.GetUnboundReferences()) { Module.Binary.AddModule(ReferencedModule); } } }
if (!bCompileMonolithic) { if (Platform == UnrealTargetPlatform.Win64 || Platform == UnrealTargetPlatform.Win32) { // On Windows create import libraries for all binaries ahead of time, since linking binaries often causes bottlenecks foreach (UEBuildBinary Binary in Binaries) { Binary.SetCreateImportLibrarySeparately(true); } } else { // On other platforms markup all the binaries containing modules with circular references foreach (UEBuildModule Module in Modules.Values.Where(x => x.Binary != null)) { foreach (string CircularlyReferencedModuleName in Module.Rules.CircularlyReferencedDependentModules) { UEBuildModule CircularlyReferencedModule; if (Modules.TryGetValue(CircularlyReferencedModuleName, out CircularlyReferencedModule) && CircularlyReferencedModule.Binary != null) { CircularlyReferencedModule.Binary.SetCreateImportLibrarySeparately(true); } } } } }
// On Mac AppBinaries paths for non-console targets need to be adjusted to be inside the app bundle if (Platform == UnrealTargetPlatform.Mac && !Rules.bIsBuildingConsoleApplication) { TargetToolChain.FixBundleBinariesPaths(this, Binaries); } }
///<summary> /// Creates an instance of a module rules descriptor object for the specified module name ///</summary> ///<param name="ModuleName">Name of the module</param> ///<param name="Target">Information about the target associated with this module</param> ///<param name="ReferenceChain">Chain of references leading to this module</param> ///<returns>Compiled module rule info</returns> public ModuleRules CreateModuleRules(string ModuleName, ReadOnlyTargetRules Target, string ReferenceChain) { // Currently, we expect the user's rules object type name to be the same as the module name string ModuleTypeName = ModuleName;
// Make sure the module file is known to us FileReference ModuleFileName; if (!ModuleNameToModuleFile.TryGetValue(ModuleName, out ModuleFileName)) { if (Parent == null) { thrownew BuildException("Could not find definition for module '{0}' (referenced via {1})", ModuleName, ReferenceChain); } else { return Parent.CreateModuleRules(ModuleName, Target, ReferenceChain); } }
// The build module must define a type named 'Rules' that derives from our 'ModuleRules' type. Type RulesObjectType = GetModuleRulesTypeInternal(ModuleName); if (RulesObjectType == null) { thrownew BuildException("Expecting to find a type to be declared in a module rules named '{0}' in {1}. This type must derive from the 'ModuleRules' type defined by Unreal Build Tool.", ModuleTypeName, CompiledAssembly.FullName); }
// Create an instance of the module's rules object try { // Create an uninitialized ModuleRules object and set some defaults. ModuleRules RulesObject = (ModuleRules)FormatterServices.GetUninitializedObject(RulesObjectType); RulesObject.Name = ModuleName; RulesObject.File = ModuleFileName; RulesObject.Directory = ModuleFileName.Directory; ModuleFileToPluginInfo.TryGetValue(RulesObject.File, out RulesObject.Plugin); RulesObject.bTreatAsEngineModule = bContainsEngineModules; RulesObject.bUseBackwardsCompatibleDefaults = bUseBackwardsCompatibleDefaults && Target.bUseBackwardsCompatibleDefaults; RulesObject.bPrecompile = (RulesObject.bTreatAsEngineModule || ModuleName.Equals("UE4Game", StringComparison.OrdinalIgnoreCase)) && Target.bPrecompile; RulesObject.bUsePrecompiled = bReadOnly;
// Call the constructor ConstructorInfo Constructor = RulesObjectType.GetConstructor(new Type[] { typeof(ReadOnlyTargetRules) }); if(Constructor == null) { thrownew BuildException("No valid constructor found for {0}.", ModuleName); } Constructor.Invoke(RulesObject, newobject[] { Target });
return RulesObject; } catch (Exception Ex) { Exception MessageEx = (Ex is TargetInvocationException && Ex.InnerException != null)? Ex.InnerException : Ex; thrownew BuildException(Ex, "Unable to instantiate module '{0}': {1}\n(referenced via {2})", ModuleName, MessageEx.ToString(), ReferenceChain); } }
///<summary> /// Sets up the binaries for the target. ///</summary> protectedvoidSetupBinaries() { // If we're using the new method for specifying binaries, fill in the binary configurations now if(Rules.LaunchModuleName == null) { thrownew BuildException("LaunchModuleName must be set for all targets."); }
// Create the launch module UEBuildModuleCPP LaunchModule = FindOrCreateCppModuleByName(Rules.LaunchModuleName, TargetRulesFile.GetFileName());