You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb none #lockdown Nick.Penwarden #rnx ============================ MAJOR FEATURES & CHANGES ============================ Change 3804281 by Fred.Kimberley Improve contrast on watches in blueprints. Change 3804322 by Fred.Kimberley First pass at adding a watch window for blueprint debugging. Change 3804737 by mason.seay Added some Descriptions to tests that didn't have any, and fixed some typos Change 3806103 by mason.seay Moved and Renamed Timers test map and content appropriately Change 3806164 by Fred.Kimberley Add missing property types to GetDebugInfoInternal. #jira UE-53355 Change 3806617 by Dan.Oconnor Function Terminator (and derived types) now use FMemberReference instead of a UClass/FName pair. This fixes various bugs when resolving the UFunction referenced by the function terminator #jira UE-31754, UE-42431, UE-53315, UE-53172 Change 3808541 by Fred.Kimberley Add support for redirecting user defined enums. This is in response to the following UDN thread: https://udn.unrealengine.com/questions/404141/is-is-possible-to-create-a-redirector-from-a-bluep.html Change 3808565 by mason.seay Added a few more struct tests Change 3809840 by mason.seay Renamed CharacterMovement.umap to CharacterCollision. Fixed up content to reflect this change. Change 3809847 by mason.seay Added Object Timer tests. Fixed up existing timer test to remove delay dependency Change 3811704 by Ben.Zeigler Fix issue where identical enum redirects registered to different initial names would throw an incorrect error, it's fine if the value change maps are identical Change 3811946 by Ben.Zeigler #jira UE-53511 Fix it so it is possible to set a user defined struct value back to it's default. The UDS hack in PropertyValueToString is no longer needed, but this could affect some other user struct editor operations Change 3812061 by Dan.Oconnor Stepping over or in to nodes that are expanded at compile time (e.g. event nodes, spawn actor nodes) no longer requires multiple 'steps' #jira UE-52854 Change 3812259 by Dan.Oconnor Fix asset broken by removal of an unkown enum #jira UE-51419 Change 3812904 by Ben.Zeigler Make ResolveRedirects on StreamableManager public as it can be used to validate things Change 3812958 by Ben.Zeigler #jira UE-52977 Fix crashes when binding blueprint editor commands to keys and using from invalid contexts Change 3812975 by Mieszko.Zielinski Added contraptions to catch a rare eidtor-time EQS crash #UE4 #jira UE-53468 Change 3818530 by Phillip.Kavan Fix incorrect access to nested instanced subobjects in nativized Blueprint ctor codegen. Change summary: - Modified FEmitDefaultValueHelper::HandleInstancedSubobject() to properly reference the outer and check ptr validity when creating/obtaining nested default subobjects. - Modified FEmitDefaultValueHelper::HandleClassSubobject() to better guard against code generation based on an invalid local variable name. #jira UE-52167 Change 3819733 by Mieszko.Zielinski Marked UAISenseConfig_Blueprint and UAISense_Blueprint as hidedropdown #UE4 #jira UE-15089 Change 3821776 by Marc.Audy Remove redundent code in SpawnActorFromClass that already exists in ConstructObjectFromClass parent class Change 3823851 by mason.seay Moved and renamed blueprints used for Object Reference testing Change 3824165 by Phillip.Kavan Ensure that subobject class types are constructed prior to accessing a subobject CDO in a nativized Blueprint class's generated ctor at runtime. Change summary: - Modified FFakeImportTableHelper to tag subobject class types as a preload dependency of the outer converted Blueprint class type and not of the CDO. #jira UE-53111 Change 3830309 by mason.seay Created Literal Gameplay Tag Container test Change 3830562 by Phillip.Kavan Blueprint nativization bug fixes (reviewed/taken from PR). Change summary: - Modified FSafeContextScopedEmitter::ValidationChain() to ensure that generated code calls the global IsValid() utility function on objects. - Modified FBlueprintCompilerCppBackend::EmitCreateArrayStatement() to generate a proper cast on MakeArray node inputs for enum class types. - Modified FBlueprintCompilerCppBackend::EnimCallStatementInner() to more correctly identify an interface function call site. - Modified FEmitHelper::GenerateAutomaticCast() to properly handle automatic casts of enum arrays. - (Modified from PR source) Added new FComponentDataUtils statics to consolidate custom init code generation for converted special-case component types (e.g. BodyInstance). Ties native component DSOs to the same pre/post as converted non-native component templates around the OuterGenerate() loop. - Modified FExposeOnSpawnValidator::IsSupported() to include CPT_SoftObjectReference property types. - Modified UBlueprintGeneratedClass::CheckAndApplyComponentTemplateOverrides() to no longer break out of the loop before finding additional ICH override record matches. #4202 #jira UE-52188 Change3830579by Fred.Kimberley Add support for turning off multiple watches at once in the watch window. #jira UE-53852 Change 3836047 by Zak.Middleton #ue4 - Dev test maps for overlaps perf tests. Change 3836768 by Phillip.Kavan Fix for a build failure that could occur with Blueprint nativization enabled and EDL disabled. This was a regression introduced in 4.18. Change summary: - Modified FEmitDefaultValueHelper::AddStaticFunctionsForDependencies() to emit the correct signature for constructing FBlueprintDependencyData elements when the EDL boot time optimization is disabled. #jira UE-53908 Change 3838085 by mason.seay Functional tests around basic blueprint functions Change 3840489 by Ben.Zeigler #jira UE-31662 Fix regression with renaming parent inherited function. It was not correctly searching the parent's skeleton class during the child's recompile so it was erroneously detecting the parent function as missing Change 3840648 by mason.seay Updated Descriptions on tests Change 3842914 by Ben.Zeigler Improve comments around stremable handle cancel/release Change 3850413 by Ben.Zeigler Fix asset registry memory reporting, track some newer fields and correctly report the state size instead of static size twice Copy of CL #3849610 Change 3850426 by Ben.Zeigler Reduce asset registry memory in cooked build by stripping out searchable names and empty dependency nodes by default Add option to strip dependency data for asset data with no tags, this was always true before but isn't necessarily safe Copy of CL #3850389 Change 3853449 by Phillip.Kavan Fix a scoping issue for local instanced subobject references in nativized Blueprint C++ code. Also, don't emit redundant assignment statements for instanced subobject reference properties. Change summary: - Consolidated FComponentDataUtils into FDefaultSubobjectData and extended FNonativeComponentData from it in order to handle both native & non-native DSO initialization codegen through a more common interface. - Exposed FEmitDefaultValueHelper::HandleInstancedSubobject() as a public API and added a 'SubobjectData' parameter to allow initialization codegen to be deferred until after all default subobjects have been mapped to local variables within the current scope. - Modified FEmitDefaultValueHelper::GenerateConstructor() to first map all default subobjects to local variables and then emit any delta initialization code for property values. - Modified FEmitDefaultValueHelper::HandleSpecialTypes() to return an empty string for an instanced reference to a default subobject. This allows us to avoid emitting initialization statements to unnecessarily reassign instances back to the same property. - Modified FEmitDefaultValueHelper::InnerGenerate() to better handle instanced references to default subobjects, ensuring that we don't emit unnecessary assignment statements and array initialization code to the converted class constructor in C++. - Fixed a few typos. #jira UE-53960 Change 3853465 by Phillip.Kavan Fix plugin module C++ source template to conform to recent public include path changes. Change 3857599 by Marc.Audy PR #4438: UE-54281: Make None a valid default value to select (Contributed by projectgheist) #jira UE-54281 #jira UE-54399 Change 3863259 by Zak.Middleton #ue4 - Save bandwidth for replicated characters by only replicating 4 byte timestamp value to clients if it's actually needed for Linear smoothing. Added option to always replicate the timestamp ("bNetworkAlwaysReplicateTransformUpdateTimestamp", default off), in case users still want this timestamp for some reason, or if smoothing mode changes dynamically and the server won't know. #jira UE-46293 Change 3863491 by Zak.Middleton #ue4 - Reduce network RPC overhead for players that are not moving. Added ClientNetSendMoveDeltaTimeStationary (default 12Hz) to supplement existing ClientNetSendMoveDeltaTime and ClientNetSendMoveDeltaTimeThrottled. UCharacterMovementComponent::GetClientNetSendDeltaTime() now uses this time if Acceleration and Velocity are zero, and the control rotation matches the last ack'd control rotation from the server. Also fixed up code default for ClientNetSendMoveDeltaTime to match default INI value. #jira UE-21264 Change 3865325 by Zak.Middleton #ue4 - Fix static analysis warning about possible null PC pointer. #jira none Change 3869828 by Ben.Zeigler #jira UE-54786 Fix it so -cookonthefly cooperates with -iterate by writing out a development asset registry Change 3869969 by mason.seay Character Movement Functional Tests Change 3870099 by Mason.Seay Submitted asset deletes Change 3870105 by mason.seay Removed link to anim blueprint to fix errors Change 3870238 by mason.seay Test map for Async Loading in a Loop Change 3870479 by Ben.Zeigler Add code to check CoreRedirects for SoftObjectPaths when saving or resolving in the editor. This is a bit slow so we don't want to do it on load We don't have any good way to know the type of a path so I check both Object and Class redirectors, which will also pickup Module renames Change 3875224 by mason.seay Functional tests for Event BeginPlay execution order Change 3875409 by mason.seay Optimized and fixed up character movement tests (because a potential bug in FunctionalTestActor is always passing a test when it can fail) Change 3878947 by Mieszko.Zielinski CIS fixes #UE4 Change 3879000 by Mieszko.Zielinski More CIS fixes #UE4 Change 3879139 by Mieszko.Zielinski Even moar CIS fixes #UE4 Change 3879742 by mason.seay Added animation to Nativization Widget asset Change3880198by Zak.Middleton #ue4 - CanCrouchInCurrentState() returns false when character capsule is simulating physics. #jira UE-54875 github #4479 Change 3880266 by Zak.Middleton #ue4 - Optimize UpdateCharacterStateBeforeMovement() to do cheaper tests earlier (avoid CanCrouchInCurrentState() unless necessary, now that it tests IsSimulatingPhysics() which is not trivial). #jira UE-54875 Change 3881546 by Mieszko.Zielinski *.Build.cs files clean up - removed redundant dependencies from NavigationSystem and AIModule #UE4 Change 3881547 by Mieszko.Zielinski Removed a bunch of DEPRECATED functions from the new NavigationSystem module #UE4 Removed all deprecates prior 4.15 (picked this one because I do know some licencees are still using it). Change 3881742 by mason.seay Additional crouch test to cover UE-54875 Change 3881794 by Mieszko.Zielinski Fixed a bug in FVisualLoggerHelpers::GetCategories resulting in losing verbosity information #UE4 Change 3884503 by Mieszko.Zielinski Fixed TopDown code template to make it compile after navsys refactor #UE4 #jira UE-55039 Change 3884507 by Mieszko.Zielinski Switched ensures in UNavigationSystemV1:SimpleMoveToX to error-level logs #UE4 It's an error rather than a warning because the functions no longer do anything. Making it work would require a cyclic dependency between NavigationSystem and AIModule. #jira UE-55033 Change 3884594 by Mieszko.Zielinski Added a const FNavigationSystem::GetCurrent version #UE4 lack of it was causing KiteDemo to not compile. Change 3884602 by Mieszko.Zielinski Mac editor compilation fix #UE4 Change 3884615 by Mieszko.Zielinski Fixed FAIDataProviderValue::GetRawValuePtr not being accessible from outside of AIModule #UE4 Change3885254by Mieszko.Zielinski Guessfix for UE-55030 #UE4 The name of NavigationSystem module was put in wrong in the IMPLEMENT_MODULE macro #jira 55030 Change 3885286 by Mieszko.Zielinski Changed how NavigationSystem module includes DerivedDataCache module #UE4 #jira UE-55035 Change 3885492 by mason.seay Minor tweaks to animation Change 3885773 by mason.seay Resaving assets to clear out warning Change 3886433 by Mieszko.Zielinski Fixed TP_TopDownBP's player controller BP to not use deprecated nav functions #UE4 #jira UE-55108 Change 3886783 by Mieszko.Zielinski Removed silly inclusion of NavigationSystemTypes.h from NavigationSystemTypes.h #UE4 Change 3887019 by Mieszko.Zielinski Fixed accessing unchecked pointer in ANavigationData::OnNavAreaAdded #UE4 Change 3891031 by Mieszko.Zielinski Fixed missing includes in NavigationSystem.cpp #UE4 Change 3891037 by Mieszko.Zielinski ContentEample's navigation fix #UE4 #jira UE-55109 Change 3891044 by Mieszko.Zielinski PR #4456: Fix bug in UAISense_Sight::OnListenerForgetsActor (Contributed by maxtunel) #UE4 Change 3891598 by mason.seay Resaving assets to clear out "empty engine version" spam Change 3891612 by mason.seay Fixed deprecated Set Text warnings Change 3893334 by Mieszko.Zielinski Fixed a bug in navmesh generation resulting in not removing layers that ended up empty after rebuilding #UE4 #jira UE-55041 Change 3893394 by Mieszko.Zielinski Fixed navmesh debug drawing to properly display octree elements with "per instance transforms" (like instanced SMs) #UE4 Also, added a more detailed debug drawing of navoctree contents (optional, but on by default). Change 3893395 by Mieszko.Zielinski Added a bit of code to navigation system's initialization that checks the enegine ini for sections refering to the moved navigation classes, and complain about it #UE4 The message is printed as an error-level log line and it says what should the offending section be renamed to. Change 3895563 by Dan.Oconnor Mirror 3895535 Append history from previous branches in source control history view #jira none Change 3896930 by Mieszko.Zielinski Added an option to tick navigation system while the game is paused #UE4 Controlled via NavigationSystemV1.bTickWhilePaused, ini- and ProjectSettings-configurable. #jira UE-39275 Change 3897554 by Mieszko.Zielinski Unified how NavMeshRenderingComponent draws navmesh and octree collision's polys #UE4 Change 3897556 by Mieszko.Zielinski Fixed what kind of nav tile bounds we're sending to nav-colliding elements when calling 'per-instance transform' delegate #UE4 #jira UE-45261 Change 3898064 by Mieszko.Zielinski Made SM Editor display AI-navigation-related whenever bHasNavigationData is set to true #UE4 #jira UE-50436 Change 3899004 by Mieszko.Zielinski Fixed UEnvQueryItemType_Actor::GetItemLocation and UEnvQueryItemType_Actor::GetItemRotation to return FAISystem::InvalidLocation and FAISystem::InvalidRotation respectively instead of '0' when hosted Actor ptr is null #UE4 Note for programmers: this changes the default behavior of this edge case. You might want to go through your code and check if you're comparing UEnvQueryItemType_Actor::GetItem*'s results to 0. Change 3901733 by Mieszko.Zielinski Made FEnvQueryInstance::PrepareContext implementations returning vectors and rotators ignore InvalidLocation and InvalidRotation (respectively) #UE4 Change 3901925 by Ben.Zeigler #jira UE-55395 Fix issue where the cooker could load asset registry caches made in -game that do not have dependency data, leading to broken cooks Change 3902166 by Marc.Audy Make ULevel::GetWorld final Change 3902749 by Ben.Zeigler Fix it so pressing refresh button in asset audit window actually refreshes the asset management database Change 3902763 by Ben.Zeigler #jira UE-55407 Fix it so editor tutorials are not cooked unless referenced, by correctly marking soft object paths imported from editor project settings as editor-only Change 3905578 by Phillip.Kavan The UX to add a new parameter on a Blueprint delegate is now at parity with Blueprint functions. #4392 #jira UE-53779 Change 3905848 by Phillip.Kavan First pass of the experimental Blueprint graph bookmarks feature. #jira UE-10052 Change 3906025 by Phillip.Kavan CIS fix. Change 3906195 by Phillip.Kavan Add missing icon file. Change 3906356 by Phillip.Kavan Moved Blueprint bookmarks enable flag into EditorExperimentalSettings for consistency with other options. Change 3910628 by Ben.Zeigler Partial fix for UE-55363, this allows references to ObjectRedirectors to be switched from parent class to a child class on load as this should always be safe This does not actually fix UE-55363 because that case is changing from UMaterial to UMaterialInstanceConstant, and those are siblings instead of parent/child Change 3912470 by Ben.Zeigler #jira UE-55586 Fix issue with saving redirected soft object paths where the export sort could accidentally cause the parent CDO to get modified between name tagging and writing exports, which is unsafe because due to delta serialization it would try to write names that were not previously tagged Change 3913045 by Marc.Audy Fix issues where recursion in to child actors wasn't being handled correctly Change 3913398 by Fred.Kimberley Fixes a misspelled name for one of the classes in the ability system. PR #4430: Fixed spelling of FGameplayAbilityInputBinds. (Contributed by IntegralLee) #github #jira UE-54327 Change 3918016 by Fred.Kimberley Ensure AllocGameplayEffectContext is being used in all cases where FGameplayeEffectContext is being created. #jira UE-52668 PR #4250: Only create FGameplayEffectContext via AbilitySystemGlobals::.AllocGameplayEffectContext (Contributed by slonopotamus) #github Change 3924653 by Mieszko.Zielinski Fixed LoadEngineClass local to UnrealEngine.cpp to check class redirects before falling back to default class instance #UE4 #jira UE-55378 Change 3925614 by Phillip.Kavan Fix ForEachEnum node to skip over hidden enum values in new placements by default. Change summary: - Added FKismetNodeHelperLibrary::ShouldHideEnumeratorIndex() as an internal-only Blueprint node support API. - Modified FForExpandNodeHelper::AllocateDefaultPins() to add a "Skip Hidden" input pin (advanced). Pin default value is false. - Added a UK2Node_ForEachElementInEnum::PostPlacedNewNode() override to set the default value of the "Skip Hidden" input pin to 'true' for all new node placements. - Modified UK2Node_ForEachElementInEnum::ExpandNode() to include additional expansion logic based on the "Skip Hidden" input pin. For new placements (i.e. when the pin defaults to 'true'), an intermediate branch node will now be inserted into the compiled execution sequence to test for "hidden" metadata on the value before executing the loop body. If the input pin is linked, another intermediate branch will be inserted into the execution sequence prior to the "hidden" metadata test. All existing placements of the node will remain as-is after compilation (i.e. no additional intermediate branch nodes will be included in the expansion). #jira UE-34563 Change 3925649 by Marc.Audy Fix up issue post merge from Main with navigation system refactor Change 3926293 by Phillip.Kavan Temp fix to unblock CIS. #jira UE-34563 Change 3926523 by Marc.Audy Ensure that a renamed Actor is in the correct Actors array #jira UE-46718 Change 3928732 by Fred.Kimberley Unshelved from pending changelist '3793298': #jira UE-53136 PR #4287: virtual additions for AttributeSet extendability (Contributed by TWIDan) #github Change 3928780 by Marc.Audy PR #4309: The display names of the functions. (Contributed by SertacOgan) #jira UE-53334 Change 3929730 by Joseph.Wysosky Submitting test assets for the new Blueprint Structure test cases Change 3931919 by Joseph.Wysosky Deleting BasicStructure asset to rest MemberVariables back to default settings Change 3931922 by Joseph.Wysosky Adding BasicStructure test asset back with default members Change 3932083 by Phillip.Kavan Fix Compositing plugin source files to conform to updated relative include path specifications. - Encountered while testing Blueprint nativization of assets with dependencies on Composure/LensDistortion APIs. Change 3932196 by Dan.Oconnor Resetting a property to default now uses the same codepath as assigning the value from the slate control #jira UE-55909 Change 3932408 by Lukasz.Furman fixed behavior tree services attached to task nodes being sometimes recognized as root level #jira nope Change 3932808 by Marc.Audy PR #4083: Change to UK2Node_BaseAsyncTask to have pin tooltips on latent nodes (Contributed by dwrpayne) #jira UE-50871 Change 3934101 by Phillip.Kavan Revise ForEachEnum node expansion logic to exclude hidden values at compile time. Change summary: - Removed UKismetNodeHelperLibrary::ShouldHideEnumeratorIndex() (no longer in use). - Modified UK2Node_ForEachElementInEnum::ExpandNode() to include an enum switch node in the expansion, which will exclude hidden values when constructed. The additional expansion will occur if the enum type contains at least one hidden value. #jira UE-34563 Change 3934106 by Phillip.Kavan Mirrored 4.19 fixes to allow for EngineTest iteration w/ nativization enabled. Change summary: - Mirrored CLs 3876918, 3878968, 3883257, 3885566, 3912161 and 3920519. Change 3934116 by Phillip.Kavan UBT: Explicitly define the DEPRECATED_FORGAME macro only for non-engine modules. Change summary: - Modified UEBuildModule.SetupPrivateCompileEnvironment() to check the 'bTreatAsEngineModule' flag from the rules assembly rather than testing the module's build type. Change 3934382 by Phillip.Kavan Avoid inclusion of monolothic engine header files in nativized Blueprint codegen. Change 3936387 by Mieszko.Zielinski Added a flag to NavModifierComponent to control whether agent's height is being used while expadning modifier's bounds during navmesh generation #UE4 Change 3936905 by Ben.Marsh Disable IncludeTool warning for DEPRECATED_FORGAME macro; we expect this to be different for game modules. Change 3940537 by Marc.Audy Don't allow maps, sets, or arrays with an actor inner type in user defined structs to select an actor from the currently open level as default value. #jira UE-55938 Change 3940901 by Marc.Audy Properly name CVar global to reflect what it is for Change 3943043 by Marc.Audy Fix world context functions not being able to be used in CheatManager derived blueprints #jira UE-55787 Change 3943075 by Mieszko.Zielinski Moved path-following related delegats' interface from NavigationSystemBase over to a new IPathFollowingManagerInterface #UE4 Change 3943089 by Mieszko.Zielinski Fixed how WorldSettings.NavigationSystemConfig gets created #UE4 Made it so that there's always a NavigationSystemConfig instance present, but added a 'Null' config - this was required due to issues with creation/serialization of instanced subobjects. The change required adding copying constructors to FNavAgentProperties and FNavDataConfig. Also, fixed FNavAgentProperties.IsEquivalent to be symetrical. Change 3943225 by Marc.Audy Fix spelling of Implements Change 3950813 by Marc.Audy Include owner in attachment mismatch ensure #jira UE-56148 Change 3950996 by Marc.Audy Fix cases where bit packed properties used the entire byte not just the bit when interacting with boolean arrays #jira UE-55482 Change 3952086 by Marc.Audy PR #4483: Add Missing Radial Damage Multicast Delegate (Contributed by error454) #jira UE-54974 Change 3952720 by Marc.Audy PR #4575: Check if *Pawn* is a null Pointer (Contributed by dani9bma) #jira UE-56248 Change 3952804 by Richard.Hinckley Changes to BP API export commandlet to support better plugin exporting. Contributed by Harry Wang of Google. Change 3952962 by Marc.Audy UHT now validates that ExpandEnumAsExecs references a valid parameter to the function. #jira UE-49610 Change 3952977 by Phillip.Kavan Fix EDL cycle at load time in nativized cooked builds when a circular dependency exists between converted and unconverted assets. Change summary: - Added FGatherConvertedClassDependencies::MarkUnconvertedClassAsNecessary(). - Modified FFindAssetsToInclude::MaybeIncludeObjectAsDependency() to mark unconverted BPGCs (e.g. DOBPs) as necessary for conversion when the potential for a circular dependency exists so that we generate stub wrappers rather than depend on them directly. - Fixed a few typos in existing API names. #jira UE-48233 Change 3953658 by Marc.Audy (4.19.1) Fix inserting a reroute node causing connections to break on a GetClassDefaults node #jira UE-56270 Change 3954727 by Marc.Audy Add friendly name to custom version mismatch message Change 3954906 by Marc.Audy (4.19.1) Fix crash when undoing changes related to reroute nodes connected to a GetClassDefaults node #jira UE-56313 Change 3954997 by Marc.Audy Ensure and return null if GetOuter<WithinClass> is called on a CDO for uclasses declared as within another so we don't get a UPackage c-style cast to the expected outer type Change 3955091 by Marc.Audy Do not register subcomponents that are not auto register #jira UE-52878 Change 3955943 by Marc.Audy Make AbilitySystemComponent pass parameters by const& instead of ref as no state is being changed Change 3956185 by Zak.Middleton #ue4 - Fix Characters using scoped movement updates (the default) not visually rotating when rotated at small rates at high framerate. This was caused by FScopedMovementUpdate::IsTransformDirty() using a larger FTransform comparison tolerance than USceneComponent::UpdateComponentToWorldWithParent(). #jira none Change 3958102 by Marc.Audy Clean out dead code path from k2node_select Select node now resets pins to wildcard if none of the pins are in use Change 3958113 by Lukasz.Furman added OnSearchStart call to root level behavior tree services #jira UE-56257 Change 3958361 by Marc.Audy Fix literal input pins on select being set to wildcard during compilation Change 3961148 by Dan.Oconnor Mirror 3961139 from Release 4.19 Fix for placeholder objects being left behind when loading certain UMG assets - this could causea crash when loading UMG assets #jira UE-55742 Change 3961640 by Marc.Audy Select node now displays Add Pin button Undo of changing select node index type now works correctly. Connections to option pins now maintained across change of index pin type #jira UE-20742 Change 3962262 by Marc.Audy Display "Object Reference" instead of "Object Object Reference" and "Soft Object Reference" instead of "Object Soft Object Reference" Change 3962795 by Phillip.Kavan Fix for a crash when cooking with Blueprint nativization enabled after encountering a nested instanced editor-only default subobject inherited from a native C++ base class. - Mirrored from //UE4/Release-4.19 (3962782) #jira UE-56316 Change 3962991 by Marc.Audy Modify Negate/Increment/Decrement Int/Float so that the output is always the desired result even if a non-mutable pin is passed in. Note that this can mean the result being returned and the value of the pin passed in if queried again will not be the same (in the case of pure nodes). #jira UE-54807 Change 3963114 by Marc.Audy Fix ensures/crash as a result of UClass expecting to be able to access the UPackage of CDOs via the GetOuterUPackage call. Change 3963427 by Marc.Audy Fix initialization order Initialize bUseBackwardsCompatForEmptyAutogeneratedValue Change 3963781 by Marc.Audy Fix without editor compiles Change 3964576 by Marc.Audy PR #4599: : Working category for timelines (Contributed by projectgheist) #jira UE-56460 #jira UE-26053 Change 3964782 by Dan.Oconnor Mirror 3964772 from Release 4.19 Fix crash when force deleting certain blueprints, we can only check for authoritativeness while reinstancing #jira UE-56447 Change 3965156 by Mieszko.Zielinski PR #4592: Visual Logger optimization to fix rapid FPS drop when many items are hidden (Contributed by tstaples) #jira UE-56435 Change 3965173 by Marc.Audy (4.19.1) Fix incorrectly switching a cooling down tick to be an enabled tick when marking it enabled. #jira UE-56431 Change 3966117 by Marc.Audy Fix select nodes inside macros using wildcard array inputs having issues resolving type. #jira UE-56484 Change 3878901 by Mieszko.Zielinski NavigationSystem's code refactored out of the engine and into a new separate module #UE4 The CL contains required changes to all of our internal projects. Fortnite and Paragon have been tested, while the rest have been only compiled. Change 3879409 by Mieszko.Zielinski Further fallout fixes after ripping out NavigationSystem out of the engine #UE4 - Fixed bad ini redirects (had NavigationSystem.NavigationSystem instead of NavigationSystem.NavigationSystemV1) - Added missing FNavigationSystem::GetDefaultNavDataClass binding (resulting in QAGame's func tests failing) Change3897655by Ben.Zeigler #jira UE-55211 Fix it so literal soft object pins on blueprint nodes get correctly cooked/referenced It now sets the thread context to skip internal serialize and calls the archive's serialize function instead of bypassing it, which allows it to pick up references Change 3962780 by Marc.Audy When preventing a split pin from being orphaned, all sub pins must also be prevented. #jira UE-56328 Repack members of UEdGraphPin to avoid wasted space (saves 16bytes) [CL 3967553 by Marc Audy in Main branch]
1427 lines
60 KiB
C#
1427 lines
60 KiB
C#
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Tools.DotNETCommon;
|
|
|
|
namespace UnrealBuildTool
|
|
{
|
|
/// <summary>
|
|
/// A module that is compiled from C++ code.
|
|
/// </summary>
|
|
class UEBuildModuleCPP : UEBuildModule
|
|
{
|
|
public class AutoGenerateCppInfoClass
|
|
{
|
|
public class BuildInfoClass
|
|
{
|
|
/// <summary>
|
|
/// The wildcard of the *.gen.cpp file which was generated for the module
|
|
/// </summary>
|
|
public readonly string FileWildcard;
|
|
|
|
public BuildInfoClass(string InWildcard)
|
|
{
|
|
Debug.Assert(InWildcard != null);
|
|
|
|
FileWildcard = InWildcard;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Information about how to build the .gen.cpp files. If this is null, then we're not building .gen.cpp files for this module.
|
|
/// </summary>
|
|
public BuildInfoClass BuildInfo;
|
|
|
|
public AutoGenerateCppInfoClass(BuildInfoClass InBuildInfo)
|
|
{
|
|
BuildInfo = InBuildInfo;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Information about the .gen.cpp file. If this is null then this module doesn't have any UHT-produced code.
|
|
/// </summary>
|
|
public AutoGenerateCppInfoClass AutoGenerateCppInfo = null;
|
|
|
|
public class SourceFilesClass
|
|
{
|
|
public readonly List<FileItem> MissingFiles = new List<FileItem>();
|
|
public readonly List<FileItem> CPPFiles = new List<FileItem>();
|
|
public readonly List<FileItem> CFiles = new List<FileItem>();
|
|
public readonly List<FileItem> CCFiles = new List<FileItem>();
|
|
public readonly List<FileItem> MMFiles = new List<FileItem>();
|
|
public readonly List<FileItem> RCFiles = new List<FileItem>();
|
|
public readonly List<FileItem> OtherFiles = new List<FileItem>();
|
|
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
return MissingFiles.Count +
|
|
CPPFiles.Count +
|
|
CFiles.Count +
|
|
CCFiles.Count +
|
|
MMFiles.Count +
|
|
RCFiles.Count +
|
|
OtherFiles.Count;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy from list to list helper.
|
|
/// </summary>
|
|
/// <param name="From">Source list.</param>
|
|
/// <param name="To">Destination list.</param>
|
|
private static void CopyFromListToList(List<FileItem> From, List<FileItem> To)
|
|
{
|
|
To.Clear();
|
|
To.AddRange(From);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies file lists from other SourceFilesClass to this.
|
|
/// </summary>
|
|
/// <param name="Other">Source object.</param>
|
|
public void CopyFrom(SourceFilesClass Other)
|
|
{
|
|
CopyFromListToList(Other.MissingFiles, MissingFiles);
|
|
CopyFromListToList(Other.CPPFiles, CPPFiles);
|
|
CopyFromListToList(Other.CFiles, CFiles);
|
|
CopyFromListToList(Other.CCFiles, CCFiles);
|
|
CopyFromListToList(Other.MMFiles, MMFiles);
|
|
CopyFromListToList(Other.RCFiles, RCFiles);
|
|
CopyFromListToList(Other.OtherFiles, OtherFiles);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds additional source cpp files for this module.
|
|
/// </summary>
|
|
/// <param name="Files">Files to add.</param>
|
|
public void AddAdditionalCPPFiles(IEnumerable<FileItem> Files)
|
|
{
|
|
SourceFiles.AddRange(Files);
|
|
SourceFilesToBuild.CPPFiles.AddRange(Files);
|
|
}
|
|
|
|
/// <summary>
|
|
/// All the source files for this module
|
|
/// </summary>
|
|
public readonly List<FileItem> SourceFiles = new List<FileItem>();
|
|
|
|
/// <summary>
|
|
/// A list of the absolute paths of source files to be built in this module.
|
|
/// </summary>
|
|
public readonly SourceFilesClass SourceFilesToBuild = new SourceFilesClass();
|
|
|
|
/// <summary>
|
|
/// A list of the source files that were found for the module.
|
|
/// </summary>
|
|
public readonly SourceFilesClass SourceFilesFound = new SourceFilesClass();
|
|
|
|
/// <summary>
|
|
/// The directory for this module's object files
|
|
/// </summary>
|
|
public readonly DirectoryReference IntermediateDirectory;
|
|
|
|
/// <summary>
|
|
/// The directory for this module's generated code
|
|
/// </summary>
|
|
public readonly DirectoryReference GeneratedCodeDirectory;
|
|
|
|
public List<DirectoryReference> IncludeSearchPaths = new List<DirectoryReference>();
|
|
|
|
public class ProcessedDependenciesClass
|
|
{
|
|
/// <summary>
|
|
/// The file, if any, which is used as the unique PCH for this module
|
|
/// </summary>
|
|
public FileItem UniquePCHHeaderFile = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The processed dependencies for the class
|
|
/// </summary>
|
|
public ProcessedDependenciesClass ProcessedDependencies = null;
|
|
|
|
/// <summary>
|
|
/// List of invalid include directives. These are buffered up and output before we start compiling.
|
|
/// </summary>
|
|
public List<string> InvalidIncludeDirectiveMessages;
|
|
|
|
/// <summary>
|
|
/// Hack to skip adding definitions to compile environment. They will be baked into source code by external code.
|
|
/// </summary>
|
|
public bool bSkipDefinitionsForCompileEnvironment = false;
|
|
|
|
public IEnumerable<string> FindGeneratedCppFiles()
|
|
{
|
|
return ((null == GeneratedCodeDirectory) || !DirectoryReference.Exists(GeneratedCodeDirectory))
|
|
? Enumerable.Empty<string>()
|
|
: DirectoryReference.EnumerateFiles(GeneratedCodeDirectory, "*.gen.cpp", SearchOption.TopDirectoryOnly).Select((Dir) => Dir.FullName);
|
|
}
|
|
|
|
protected override void GetReferencedDirectories(HashSet<DirectoryReference> Directories)
|
|
{
|
|
base.GetReferencedDirectories(Directories);
|
|
|
|
foreach(FileItem SourceFile in SourceFiles)
|
|
{
|
|
Directories.Add(SourceFile.Location.Directory);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Categorizes source files into per-extension buckets
|
|
/// </summary>
|
|
private static void CategorizeSourceFiles(IEnumerable<FileItem> InSourceFiles, SourceFilesClass OutSourceFiles)
|
|
{
|
|
foreach (FileItem SourceFile in InSourceFiles)
|
|
{
|
|
string Extension = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();
|
|
if (!SourceFile.bExists)
|
|
{
|
|
OutSourceFiles.MissingFiles.Add(SourceFile);
|
|
}
|
|
else if (Extension == ".CPP")
|
|
{
|
|
OutSourceFiles.CPPFiles.Add(SourceFile);
|
|
}
|
|
else if (Extension == ".C")
|
|
{
|
|
OutSourceFiles.CFiles.Add(SourceFile);
|
|
}
|
|
else if (Extension == ".CC")
|
|
{
|
|
OutSourceFiles.CCFiles.Add(SourceFile);
|
|
}
|
|
else if (Extension == ".MM" || Extension == ".M")
|
|
{
|
|
OutSourceFiles.MMFiles.Add(SourceFile);
|
|
}
|
|
else if (Extension == ".RC")
|
|
{
|
|
OutSourceFiles.RCFiles.Add(SourceFile);
|
|
}
|
|
else
|
|
{
|
|
OutSourceFiles.OtherFiles.Add(SourceFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// List of whitelisted circular dependencies. Please do NOT add new modules here; refactor to allow the modules to be decoupled instead.
|
|
/// </summary>
|
|
static readonly KeyValuePair<string, string>[] WhitelistedCircularDependencies =
|
|
{
|
|
new KeyValuePair<string, string>("Engine", "Landscape"),
|
|
new KeyValuePair<string, string>("Engine", "UMG"),
|
|
new KeyValuePair<string, string>("Engine", "GameplayTags"),
|
|
new KeyValuePair<string, string>("Engine", "MaterialShaderQualitySettings"),
|
|
new KeyValuePair<string, string>("Engine", "UnrealEd"),
|
|
new KeyValuePair<string, string>("PacketHandler", "ReliabilityHandlerComponent"),
|
|
new KeyValuePair<string, string>("GameplayDebugger", "AIModule"),
|
|
new KeyValuePair<string, string>("GameplayDebugger", "GameplayTasks"),
|
|
new KeyValuePair<string, string>("Engine", "CinematicCamera"),
|
|
new KeyValuePair<string, string>("Engine", "CollisionAnalyzer"),
|
|
new KeyValuePair<string, string>("Engine", "LogVisualizer"),
|
|
new KeyValuePair<string, string>("Engine", "Kismet"),
|
|
new KeyValuePair<string, string>("Landscape", "UnrealEd"),
|
|
new KeyValuePair<string, string>("Landscape", "MaterialUtilities"),
|
|
new KeyValuePair<string, string>("LocalizationDashboard", "LocalizationService"),
|
|
new KeyValuePair<string, string>("LocalizationDashboard", "MainFrame"),
|
|
new KeyValuePair<string, string>("LocalizationDashboard", "TranslationEditor"),
|
|
new KeyValuePair<string, string>("Documentation", "SourceControl"),
|
|
new KeyValuePair<string, string>("UnrealEd", "GraphEditor"),
|
|
new KeyValuePair<string, string>("UnrealEd", "Kismet"),
|
|
new KeyValuePair<string, string>("UnrealEd", "AudioEditor"),
|
|
new KeyValuePair<string, string>("BlueprintGraph", "KismetCompiler"),
|
|
new KeyValuePair<string, string>("BlueprintGraph", "UnrealEd"),
|
|
new KeyValuePair<string, string>("BlueprintGraph", "GraphEditor"),
|
|
new KeyValuePair<string, string>("BlueprintGraph", "Kismet"),
|
|
new KeyValuePair<string, string>("BlueprintGraph", "CinematicCamera"),
|
|
new KeyValuePair<string, string>("ConfigEditor", "PropertyEditor"),
|
|
new KeyValuePair<string, string>("SourceControl", "UnrealEd"),
|
|
new KeyValuePair<string, string>("Kismet", "BlueprintGraph"),
|
|
new KeyValuePair<string, string>("Kismet", "UMGEditor"),
|
|
new KeyValuePair<string, string>("MovieSceneTools", "Sequencer"),
|
|
new KeyValuePair<string, string>("Sequencer", "MovieSceneTools"),
|
|
new KeyValuePair<string, string>("AIModule", "AITestSuite"),
|
|
new KeyValuePair<string, string>("GameplayTasks", "UnrealEd"),
|
|
new KeyValuePair<string, string>("AnimGraph", "UnrealEd"),
|
|
new KeyValuePair<string, string>("AnimGraph", "GraphEditor"),
|
|
new KeyValuePair<string, string>("MaterialUtilities", "Landscape"),
|
|
new KeyValuePair<string, string>("HierarchicalLODOutliner", "UnrealEd"),
|
|
new KeyValuePair<string, string>("PixelInspectorModule", "UnrealEd"),
|
|
new KeyValuePair<string, string>("GameplayAbilitiesEditor", "BlueprintGraph"),
|
|
new KeyValuePair<string, string>("UnrealEd", "ViewportInteraction"),
|
|
new KeyValuePair<string, string>("UnrealEd", "VREditor"),
|
|
new KeyValuePair<string, string>("LandscapeEditor", "ViewportInteraction"),
|
|
new KeyValuePair<string, string>("LandscapeEditor", "VREditor"),
|
|
new KeyValuePair<string, string>("FoliageEdit", "ViewportInteraction"),
|
|
new KeyValuePair<string, string>("FoliageEdit", "VREditor"),
|
|
new KeyValuePair<string, string>("MeshPaint", "ViewportInteraction"),
|
|
new KeyValuePair<string, string>("MeshPaint", "VREditor"),
|
|
new KeyValuePair<string, string>("MeshPaintMode", "ViewportInteraction"),
|
|
new KeyValuePair<string, string>("MeshPaintMode", "VREditor"),
|
|
new KeyValuePair<string, string>("Sequencer", "ViewportInteraction"),
|
|
new KeyValuePair<string, string>("NavigationSystem", "UnrealEd"),
|
|
};
|
|
|
|
|
|
public UEBuildModuleCPP(
|
|
string InName,
|
|
UHTModuleType InType,
|
|
DirectoryReference InModuleDirectory,
|
|
DirectoryReference InIntermediateDirectory,
|
|
DirectoryReference InGeneratedCodeDirectory,
|
|
IEnumerable<FileItem> InSourceFiles,
|
|
ModuleRules InRules,
|
|
bool bInBuildSourceFiles,
|
|
FileReference InRulesFile,
|
|
List<RuntimeDependency> InRuntimeDependencies
|
|
)
|
|
: base(
|
|
InName,
|
|
InType,
|
|
InModuleDirectory,
|
|
InRules,
|
|
InRulesFile,
|
|
InRuntimeDependencies
|
|
)
|
|
{
|
|
IntermediateDirectory = InIntermediateDirectory;
|
|
GeneratedCodeDirectory = InGeneratedCodeDirectory;
|
|
|
|
SourceFiles = InSourceFiles.ToList();
|
|
|
|
CategorizeSourceFiles(InSourceFiles, SourceFilesFound);
|
|
if (bInBuildSourceFiles)
|
|
{
|
|
SourceFilesToBuild.CopyFrom(SourceFilesFound);
|
|
}
|
|
|
|
foreach (string Def in PublicDefinitions)
|
|
{
|
|
Log.TraceVerbose("Compile Env {0}: {1}", Name, Def);
|
|
}
|
|
|
|
foreach (string Def in Rules.PrivateDefinitions)
|
|
{
|
|
Log.TraceVerbose("Compile Env {0}: {1}", Name, Def);
|
|
}
|
|
|
|
foreach(string CircularlyReferencedModuleName in Rules.CircularlyReferencedDependentModules)
|
|
{
|
|
if(CircularlyReferencedModuleName != "BlueprintContext" && !WhitelistedCircularDependencies.Any(x => x.Key == Name && x.Value == CircularlyReferencedModuleName))
|
|
{
|
|
Log.TraceWarning("Found reference between '{0}' and '{1}'. Support for circular references is being phased out; please do not introduce new ones.", Name, CircularlyReferencedModuleName);
|
|
}
|
|
}
|
|
|
|
AddDefaultIncludePaths();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the default include paths for this module to its settings
|
|
/// </summary>
|
|
private void AddDefaultIncludePaths()
|
|
{
|
|
// Add the path to the generated headers
|
|
if (GeneratedCodeDirectory != null)
|
|
{
|
|
PublicIncludePaths.Add(GeneratedCodeDirectory);
|
|
}
|
|
|
|
// Add the module's parent directory to the public include paths, so other modules may include headers from it explicitly.
|
|
PublicIncludePaths.Add(ModuleDirectory.ParentDirectory);
|
|
|
|
// Add the base directory to the legacy include paths.
|
|
LegacyPublicIncludePaths.Add(ModuleDirectory);
|
|
|
|
// Add the 'classes' directory, if it exists
|
|
DirectoryReference ClassesDirectory = DirectoryReference.Combine(ModuleDirectory, "Classes");
|
|
if (DirectoryLookupCache.DirectoryExists(ClassesDirectory))
|
|
{
|
|
PublicIncludePaths.Add(ClassesDirectory);
|
|
}
|
|
|
|
// Add all the public directories
|
|
DirectoryReference PublicDirectory = DirectoryReference.Combine(ModuleDirectory, "Public");
|
|
if (DirectoryLookupCache.DirectoryExists(PublicDirectory))
|
|
{
|
|
PublicIncludePaths.Add(PublicDirectory);
|
|
|
|
FileSystemName[] ExcludedFolderNames = UEBuildPlatform.GetBuildPlatform(Rules.Target.Platform).GetExcludedFolderNames();
|
|
foreach (DirectoryReference PublicSubDirectory in DirectoryLookupCache.EnumerateDirectoriesRecursively(PublicDirectory))
|
|
{
|
|
if(!PublicSubDirectory.ContainsAnyNames(ExcludedFolderNames, PublicDirectory))
|
|
{
|
|
LegacyPublicIncludePaths.Add(PublicSubDirectory);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add the base private directory for this module
|
|
DirectoryReference PrivateDirectory = DirectoryReference.Combine(ModuleDirectory, "Private");
|
|
if(DirectoryLookupCache.DirectoryExists(PrivateDirectory))
|
|
{
|
|
PrivateIncludePaths.Add(PrivateDirectory);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Path to the precompiled manifest location
|
|
/// </summary>
|
|
public FileReference PrecompiledManifestLocation
|
|
{
|
|
get { return FileReference.Combine(IntermediateDirectory, String.Format("{0}.precompiled", Name)); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gathers intellisense data for the project file containing this module
|
|
/// </summary>
|
|
/// <param name="Target">The target being built</param>
|
|
/// <param name="BinaryCompileEnvironment">The inherited compile environment for this module</param>
|
|
/// <param name="ProjectFile">The project file containing this module</param>
|
|
public void GatherDataForProjectFile(ReadOnlyTargetRules Target, CppCompileEnvironment BinaryCompileEnvironment, ProjectFile ProjectFile)
|
|
{
|
|
CppCompileEnvironment ModuleCompileEnvironment = CreateModuleCompileEnvironment(Target, BinaryCompileEnvironment);
|
|
ProjectFile.AddIntelliSensePreprocessorDefinitions(ModuleCompileEnvironment.Definitions);
|
|
ProjectFile.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.IncludePaths.SystemIncludePaths, true);
|
|
ProjectFile.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.IncludePaths.UserIncludePaths, false);
|
|
}
|
|
|
|
// UEBuildModule interface.
|
|
public override List<FileItem> Compile(ReadOnlyTargetRules Target, UEToolChain ToolChain, CppCompileEnvironment BinaryCompileEnvironment, List<PrecompiledHeaderTemplate> SharedPCHs, ISourceFileWorkingSet WorkingSet, ActionGraph ActionGraph)
|
|
{
|
|
UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(BinaryCompileEnvironment.Platform);
|
|
|
|
List<FileItem> LinkInputFiles = new List<FileItem>();
|
|
|
|
CppCompileEnvironment ModuleCompileEnvironment = CreateModuleCompileEnvironment(Target, BinaryCompileEnvironment);
|
|
IncludeSearchPaths = ModuleCompileEnvironment.IncludePaths.UserIncludePaths.ToList();
|
|
IncludeSearchPaths.AddRange(ModuleCompileEnvironment.IncludePaths.SystemIncludePaths.ToList());
|
|
|
|
// If the module is precompiled, read the object files from the manifest
|
|
if(Rules.bUsePrecompiled)
|
|
{
|
|
PrecompiledManifest Manifest = PrecompiledManifest.Read(PrecompiledManifestLocation);
|
|
foreach(FileReference OutputFile in Manifest.OutputFiles)
|
|
{
|
|
FileItem ObjectFile = FileItem.GetExistingItemByFileReference(OutputFile);
|
|
LinkInputFiles.Add(ObjectFile);
|
|
}
|
|
return LinkInputFiles;
|
|
}
|
|
|
|
// Throw an error if the module's source file list referenced any non-existent files.
|
|
if (SourceFilesToBuild.MissingFiles.Count > 0)
|
|
{
|
|
throw new BuildException(
|
|
"UBT ERROR: Module \"{0}\" references non-existent files:\n{1} (perhaps a file was added to the project but not checked in)",
|
|
Name,
|
|
string.Join("\n", SourceFilesToBuild.MissingFiles.Select(M => M.AbsolutePath))
|
|
);
|
|
}
|
|
|
|
{
|
|
// Process all of the header file dependencies for this module
|
|
this.CachePCHUsageForModuleSourceFiles(Target, ModuleCompileEnvironment);
|
|
|
|
// Make sure our RC files have cached includes.
|
|
foreach (FileItem RCFile in SourceFilesToBuild.RCFiles)
|
|
{
|
|
// The default resource file (PCLaunch.rc) is created in a module-agnostic way, so we want to avoid overriding the include paths for it
|
|
if(RCFile.CachedIncludePaths == null)
|
|
{
|
|
RCFile.CachedIncludePaths = ModuleCompileEnvironment.IncludePaths;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Should we force a precompiled header to be generated for this module? Usually, we only bother with a
|
|
// precompiled header if there are at least several source files in the module (after combining them for unity
|
|
// builds.) But for game modules, it can be convenient to always have a precompiled header to single-file
|
|
// changes to code is really quick to compile.
|
|
int MinFilesUsingPrecompiledHeader = Target.MinFilesUsingPrecompiledHeader;
|
|
if (Rules.MinFilesUsingPrecompiledHeaderOverride != 0)
|
|
{
|
|
MinFilesUsingPrecompiledHeader = Rules.MinFilesUsingPrecompiledHeaderOverride;
|
|
}
|
|
else if (!Rules.bTreatAsEngineModule && Target.bForcePrecompiledHeaderForGameModules)
|
|
{
|
|
// This is a game module with only a small number of source files, so go ahead and force a precompiled header
|
|
// to be generated to make incremental changes to source files as fast as possible for small projects.
|
|
MinFilesUsingPrecompiledHeader = 1;
|
|
}
|
|
|
|
// Engine modules will always use unity build mode unless MinSourceFilesForUnityBuildOverride is specified in
|
|
// the module rules file. By default, game modules only use unity of they have enough source files for that
|
|
// to be worthwhile. If you have a lot of small game modules, consider specifying MinSourceFilesForUnityBuildOverride=0
|
|
// in the modules that you don't typically iterate on source files in very frequently.
|
|
int MinSourceFilesForUnityBuild = 0;
|
|
if (Rules.MinSourceFilesForUnityBuildOverride != 0)
|
|
{
|
|
MinSourceFilesForUnityBuild = Rules.MinSourceFilesForUnityBuildOverride;
|
|
}
|
|
else if (!Rules.bTreatAsEngineModule)
|
|
{
|
|
// Game modules with only a small number of source files are usually better off having faster iteration times
|
|
// on single source file changes, so we forcibly disable unity build for those modules
|
|
MinSourceFilesForUnityBuild = Target.MinGameModuleSourceFilesForUnityBuild;
|
|
}
|
|
|
|
// Should we use unity build mode for this module?
|
|
bool bModuleUsesUnityBuild = false;
|
|
if (Target.bUseUnityBuild || Target.bForceUnityBuild)
|
|
{
|
|
if (Target.bForceUnityBuild)
|
|
{
|
|
Log.TraceVerbose("Module '{0}' using unity build mode (bForceUnityBuild enabled for this module)", this.Name);
|
|
bModuleUsesUnityBuild = true;
|
|
}
|
|
else if (Rules.bFasterWithoutUnity)
|
|
{
|
|
Log.TraceVerbose("Module '{0}' not using unity build mode (bFasterWithoutUnity enabled for this module)", this.Name);
|
|
bModuleUsesUnityBuild = false;
|
|
}
|
|
else if (SourceFilesToBuild.CPPFiles.Count < MinSourceFilesForUnityBuild)
|
|
{
|
|
Log.TraceVerbose("Module '{0}' not using unity build mode (module with fewer than {1} source files)", this.Name, MinSourceFilesForUnityBuild);
|
|
bModuleUsesUnityBuild = false;
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("Module '{0}' using unity build mode", this.Name);
|
|
bModuleUsesUnityBuild = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("Module '{0}' not using unity build mode", this.Name);
|
|
}
|
|
|
|
// Set up the environment with which to compile the CPP files
|
|
CppCompileEnvironment CompileEnvironment = ModuleCompileEnvironment;
|
|
if (Target.bUsePCHFiles)
|
|
{
|
|
// If this module has an explicit PCH, use that
|
|
if(Rules.PrivatePCHHeaderFile != null)
|
|
{
|
|
PrecompiledHeaderInstance Instance = CreatePrivatePCH(ToolChain, FileItem.GetItemByFileReference(FileReference.Combine(ModuleDirectory, Rules.PrivatePCHHeaderFile)), CompileEnvironment, ActionGraph);
|
|
|
|
CompileEnvironment = new CppCompileEnvironment(CompileEnvironment);
|
|
CompileEnvironment.Definitions.Clear();
|
|
CompileEnvironment.PrecompiledHeaderAction = PrecompiledHeaderAction.Include;
|
|
CompileEnvironment.PrecompiledHeaderIncludeFilename = Instance.HeaderFile.Location;
|
|
CompileEnvironment.PrecompiledHeaderFile = Instance.Output.PrecompiledHeaderFile;
|
|
|
|
LinkInputFiles.AddRange(Instance.Output.ObjectFiles);
|
|
}
|
|
|
|
// Try to find a suitable shared PCH for this module
|
|
if (CompileEnvironment.PrecompiledHeaderFile == null && SharedPCHs.Count > 0 && !CompileEnvironment.bIsBuildingLibrary && Rules.PCHUsage != ModuleRules.PCHUsageMode.NoSharedPCHs)
|
|
{
|
|
// Find all the dependencies of this module
|
|
HashSet<UEBuildModule> ReferencedModules = new HashSet<UEBuildModule>();
|
|
GetAllDependencyModules(new List<UEBuildModule>(), ReferencedModules, bIncludeDynamicallyLoaded: false, bForceCircular: false, bOnlyDirectDependencies: true);
|
|
|
|
// Find the first shared PCH module we can use
|
|
PrecompiledHeaderTemplate Template = SharedPCHs.FirstOrDefault(x => ReferencedModules.Contains(x.Module));
|
|
if(Template != null && Template.IsValidFor(CompileEnvironment))
|
|
{
|
|
PrecompiledHeaderInstance Instance = FindOrCreateSharedPCH(ToolChain, Template, ModuleCompileEnvironment.bOptimizeCode, ModuleCompileEnvironment.bUseRTTI, ActionGraph);
|
|
|
|
FileReference PrivateDefinitionsFile = FileReference.Combine(IntermediateDirectory, String.Format("Definitions.{0}.h", Name));
|
|
|
|
FileItem PrivateDefinitionsFileItem;
|
|
using (StringWriter Writer = new StringWriter())
|
|
{
|
|
// Remove the module _API definition for cases where there are circular dependencies between the shared PCH module and modules using it
|
|
Writer.WriteLine("#undef {0}", ModuleApiDefine);
|
|
|
|
// Games may choose to use shared PCHs from the engine, so allow them to change the value of these macros
|
|
if(!Rules.bTreatAsEngineModule)
|
|
{
|
|
Writer.WriteLine("#undef UE_IS_ENGINE_MODULE");
|
|
Writer.WriteLine("#undef DEPRECATED_FORGAME");
|
|
Writer.WriteLine("#define DEPRECATED_FORGAME DEPRECATED");
|
|
}
|
|
|
|
WriteDefinitions(CompileEnvironment.Definitions, Writer);
|
|
PrivateDefinitionsFileItem = FileItem.CreateIntermediateTextFile(PrivateDefinitionsFile, Writer.ToString());
|
|
}
|
|
|
|
CompileEnvironment = new CppCompileEnvironment(CompileEnvironment);
|
|
CompileEnvironment.Definitions.Clear();
|
|
CompileEnvironment.ForceIncludeFiles.Add(PrivateDefinitionsFileItem);
|
|
CompileEnvironment.PrecompiledHeaderAction = PrecompiledHeaderAction.Include;
|
|
CompileEnvironment.PrecompiledHeaderIncludeFilename = Instance.HeaderFile.Location;
|
|
CompileEnvironment.PrecompiledHeaderFile = Instance.Output.PrecompiledHeaderFile;
|
|
|
|
LinkInputFiles.AddRange(Instance.Output.ObjectFiles);
|
|
}
|
|
}
|
|
|
|
// If there was one header that was included first by enough C++ files, use it as the precompiled header. Only use precompiled headers for projects with enough files to make the PCH creation worthwhile.
|
|
if (CompileEnvironment.PrecompiledHeaderFile == null && SourceFilesToBuild.CPPFiles.Count >= MinFilesUsingPrecompiledHeader && ProcessedDependencies != null)
|
|
{
|
|
PrecompiledHeaderInstance Instance = CreatePrivatePCH(ToolChain, ProcessedDependencies.UniquePCHHeaderFile, CompileEnvironment, ActionGraph);
|
|
|
|
CompileEnvironment = new CppCompileEnvironment(CompileEnvironment);
|
|
CompileEnvironment.Definitions.Clear();
|
|
CompileEnvironment.PrecompiledHeaderAction = PrecompiledHeaderAction.Include;
|
|
CompileEnvironment.PrecompiledHeaderIncludeFilename = Instance.HeaderFile.Location;
|
|
CompileEnvironment.PrecompiledHeaderFile = Instance.Output.PrecompiledHeaderFile;
|
|
|
|
LinkInputFiles.AddRange(Instance.Output.ObjectFiles);
|
|
}
|
|
}
|
|
|
|
// Write all the definitions to a separate file
|
|
CreateHeaderForDefinitions(CompileEnvironment, IntermediateDirectory, null);
|
|
|
|
// Compile CPP files
|
|
List<FileItem> CPPFilesToCompile = SourceFilesToBuild.CPPFiles;
|
|
if (bModuleUsesUnityBuild)
|
|
{
|
|
CPPFilesToCompile = Unity.GenerateUnityCPPs(Target, CPPFilesToCompile, CompileEnvironment, WorkingSet, Rules.ShortName ?? Name, IntermediateDirectory);
|
|
LinkInputFiles.AddRange(CompileUnityFilesWithToolChain(Target, ToolChain, CompileEnvironment, ModuleCompileEnvironment, CPPFilesToCompile, ActionGraph).ObjectFiles);
|
|
}
|
|
else
|
|
{
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(CompileEnvironment, CPPFilesToCompile, IntermediateDirectory, Name, ActionGraph).ObjectFiles);
|
|
}
|
|
|
|
// Compile all the generated CPP files
|
|
if (AutoGenerateCppInfo != null && AutoGenerateCppInfo.BuildInfo != null && !CompileEnvironment.bHackHeaderGenerator)
|
|
{
|
|
string[] GeneratedFiles = Directory.GetFiles(Path.GetDirectoryName(AutoGenerateCppInfo.BuildInfo.FileWildcard), Path.GetFileName(AutoGenerateCppInfo.BuildInfo.FileWildcard));
|
|
if(GeneratedFiles.Length > 0)
|
|
{
|
|
// Create a compile environment for the generated files. We can disable creating debug info here to improve link times.
|
|
CppCompileEnvironment GeneratedCPPCompileEnvironment = CompileEnvironment;
|
|
if(GeneratedCPPCompileEnvironment.bCreateDebugInfo && Target.bDisableDebugInfoForGeneratedCode)
|
|
{
|
|
GeneratedCPPCompileEnvironment = new CppCompileEnvironment(GeneratedCPPCompileEnvironment);
|
|
GeneratedCPPCompileEnvironment.bCreateDebugInfo = false;
|
|
}
|
|
|
|
// Compile all the generated files
|
|
List<FileItem> GeneratedFileItems = new List<FileItem>();
|
|
foreach (string GeneratedFilename in GeneratedFiles)
|
|
{
|
|
FileItem GeneratedCppFileItem = FileItem.GetItemByPath(GeneratedFilename);
|
|
|
|
CachePCHUsageForModuleSourceFile(CompileEnvironment, GeneratedCppFileItem);
|
|
|
|
// @todo ubtmake: Check for ALL other places where we might be injecting .cpp or .rc files for compiling without caching CachedCPPIncludeInfo first (anything platform specific?)
|
|
GeneratedFileItems.Add(GeneratedCppFileItem);
|
|
}
|
|
|
|
if (bModuleUsesUnityBuild)
|
|
{
|
|
GeneratedFileItems = Unity.GenerateUnityCPPs(Target, GeneratedFileItems, GeneratedCPPCompileEnvironment, WorkingSet, (Rules.ShortName ?? Name) + ".gen", IntermediateDirectory);
|
|
LinkInputFiles.AddRange(CompileUnityFilesWithToolChain(Target, ToolChain, GeneratedCPPCompileEnvironment, ModuleCompileEnvironment, GeneratedFileItems, ActionGraph).ObjectFiles);
|
|
}
|
|
else
|
|
{
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(GeneratedCPPCompileEnvironment, GeneratedFileItems, IntermediateDirectory, Name, ActionGraph).ObjectFiles);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Compile C files directly. Do not use a PCH here, because a C++ PCH is not compatible with C source files.
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(ModuleCompileEnvironment, SourceFilesToBuild.CFiles, IntermediateDirectory, Name, ActionGraph).ObjectFiles);
|
|
|
|
// Compile CC files directly.
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(CompileEnvironment, SourceFilesToBuild.CCFiles, IntermediateDirectory, Name, ActionGraph).ObjectFiles);
|
|
|
|
// Compile MM files directly.
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(CompileEnvironment, SourceFilesToBuild.MMFiles, IntermediateDirectory, Name, ActionGraph).ObjectFiles);
|
|
|
|
// Compile RC files. The resource compiler does not work with response files, and using the regular compile environment can easily result in the
|
|
// command line length exceeding the OS limit. Use the binary compile environment to keep the size down, and require that all include paths
|
|
// must be specified relative to the resource file itself or Engine/Source.
|
|
CppCompileEnvironment ResourceCompileEnvironment = new CppCompileEnvironment(BinaryCompileEnvironment);
|
|
LinkInputFiles.AddRange(ToolChain.CompileRCFiles(ResourceCompileEnvironment, SourceFilesToBuild.RCFiles, IntermediateDirectory, ActionGraph).ObjectFiles);
|
|
|
|
// Write the compiled manifest
|
|
if(Rules.bPrecompile)
|
|
{
|
|
DirectoryReference.CreateDirectory(PrecompiledManifestLocation.Directory);
|
|
|
|
PrecompiledManifest Manifest = new PrecompiledManifest();
|
|
Manifest.OutputFiles.AddRange(LinkInputFiles.Select(x => x.Location));
|
|
Manifest.Write(PrecompiledManifestLocation);
|
|
}
|
|
|
|
return LinkInputFiles;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a shared PCH template for this module, which allows constructing shared PCH instances in the future
|
|
/// </summary>
|
|
/// <param name="Target">The target which owns this module</param>
|
|
/// <param name="BaseCompileEnvironment">Base compile environment for this target</param>
|
|
/// <returns>Template for shared PCHs</returns>
|
|
public PrecompiledHeaderTemplate CreateSharedPCHTemplate(UEBuildTarget Target, CppCompileEnvironment BaseCompileEnvironment)
|
|
{
|
|
CppCompileEnvironment CompileEnvironment = CreateSharedPCHCompileEnvironment(Target, BaseCompileEnvironment);
|
|
FileItem HeaderFile = FileItem.GetItemByFileReference(FileReference.Combine(ModuleDirectory, Rules.SharedPCHHeaderFile));
|
|
HeaderFile.CachedIncludePaths = CompileEnvironment.IncludePaths;
|
|
|
|
DirectoryReference PrecompiledHeaderDir;
|
|
if(Target.Rules.bUsePrecompiled)
|
|
{
|
|
PrecompiledHeaderDir = DirectoryReference.Combine(Target.ProjectIntermediateDirectory, Name);
|
|
}
|
|
else
|
|
{
|
|
PrecompiledHeaderDir = IntermediateDirectory;
|
|
}
|
|
|
|
return new PrecompiledHeaderTemplate(this, CompileEnvironment, HeaderFile, PrecompiledHeaderDir);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a precompiled header action to generate a new pch file
|
|
/// </summary>
|
|
/// <param name="ToolChain">The toolchain to generate the PCH</param>
|
|
/// <param name="HeaderFile"></param>
|
|
/// <param name="ModuleCompileEnvironment"></param>
|
|
/// <param name="ActionGraph">Graph containing build actions</param>
|
|
/// <returns>The created PCH instance.</returns>
|
|
private PrecompiledHeaderInstance CreatePrivatePCH(UEToolChain ToolChain, FileItem HeaderFile, CppCompileEnvironment ModuleCompileEnvironment, ActionGraph ActionGraph)
|
|
{
|
|
// Cache the header file include paths. This file could have been a shared PCH too, so ignore if the include paths are already set.
|
|
if(HeaderFile.CachedIncludePaths == null)
|
|
{
|
|
HeaderFile.CachedIncludePaths = ModuleCompileEnvironment.IncludePaths;
|
|
}
|
|
|
|
// Create the wrapper file, which sets all the definitions needed to compile it
|
|
FileReference WrapperLocation = FileReference.Combine(IntermediateDirectory, String.Format("PCH.{0}.h", Name));
|
|
FileItem WrapperFile = CreatePCHWrapperFile(WrapperLocation, ModuleCompileEnvironment.Definitions, HeaderFile);
|
|
|
|
// Create a new C++ environment that is used to create the PCH.
|
|
CppCompileEnvironment CompileEnvironment = new CppCompileEnvironment(ModuleCompileEnvironment);
|
|
CompileEnvironment.Definitions.Clear();
|
|
CompileEnvironment.PrecompiledHeaderAction = PrecompiledHeaderAction.Create;
|
|
CompileEnvironment.PrecompiledHeaderIncludeFilename = WrapperFile.Location;
|
|
CompileEnvironment.bOptimizeCode = ModuleCompileEnvironment.bOptimizeCode;
|
|
|
|
// Create the action to compile the PCH file.
|
|
CPPOutput Output = ToolChain.CompileCPPFiles(CompileEnvironment, new List<FileItem>() { WrapperFile }, IntermediateDirectory, Name, ActionGraph);
|
|
return new PrecompiledHeaderInstance(WrapperFile, CompileEnvironment.bOptimizeCode, CompileEnvironment.bUseRTTI, Output);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generates a precompiled header instance from the given template, or returns an existing one if it already exists
|
|
/// </summary>
|
|
/// <param name="ToolChain">The toolchain being used to build this module</param>
|
|
/// <param name="Template">The PCH template</param>
|
|
/// <param name="bOptimizeCode">Whether optimization should be enabled for this PCH</param>
|
|
/// <param name="bUseRTTI">Whether to enable RTTI for this PCH</param>
|
|
/// <param name="ActionGraph">Graph containing build actions</param>
|
|
/// <returns>Instance of a PCH</returns>
|
|
public PrecompiledHeaderInstance FindOrCreateSharedPCH(UEToolChain ToolChain, PrecompiledHeaderTemplate Template, bool bOptimizeCode, bool bUseRTTI, ActionGraph ActionGraph)
|
|
{
|
|
PrecompiledHeaderInstance Instance = Template.Instances.Find(x => x.bOptimizeCode == bOptimizeCode && x.bUseRTTI == bUseRTTI);
|
|
if(Instance == null)
|
|
{
|
|
// Create a suffix to distinguish this shared PCH variant from any others. Currently only optimized and non-optimized shared PCHs are supported.
|
|
string Variant = "";
|
|
if(bOptimizeCode != Template.BaseCompileEnvironment.bOptimizeCode)
|
|
{
|
|
if(bOptimizeCode)
|
|
{
|
|
Variant += ".Optimized";
|
|
}
|
|
else
|
|
{
|
|
Variant += ".NonOptimized";
|
|
}
|
|
}
|
|
if(bUseRTTI != Template.BaseCompileEnvironment.bUseRTTI)
|
|
{
|
|
if (bUseRTTI)
|
|
{
|
|
Variant += ".RTTI";
|
|
}
|
|
else
|
|
{
|
|
Variant += ".NonRTTI";
|
|
}
|
|
}
|
|
|
|
// Create the wrapper file, which sets all the definitions needed to compile it
|
|
FileReference WrapperLocation = FileReference.Combine(Template.OutputDir, String.Format("SharedPCH.{0}{1}.h", Template.Module.Name, Variant));
|
|
FileItem WrapperFile = CreatePCHWrapperFile(WrapperLocation, Template.BaseCompileEnvironment.Definitions, Template.HeaderFile);
|
|
|
|
// Create the compile environment for this PCH
|
|
CppCompileEnvironment CompileEnvironment = new CppCompileEnvironment(Template.BaseCompileEnvironment);
|
|
CompileEnvironment.Definitions.Clear();
|
|
CompileEnvironment.PrecompiledHeaderAction = PrecompiledHeaderAction.Create;
|
|
CompileEnvironment.PrecompiledHeaderIncludeFilename = WrapperFile.Location;
|
|
CompileEnvironment.bOptimizeCode = bOptimizeCode;
|
|
CompileEnvironment.bUseRTTI = bUseRTTI;
|
|
|
|
// Create the PCH
|
|
CPPOutput Output = ToolChain.CompileCPPFiles(CompileEnvironment, new List<FileItem>() { WrapperFile }, Template.OutputDir, "Shared", ActionGraph);
|
|
Instance = new PrecompiledHeaderInstance(WrapperFile, bOptimizeCode, bUseRTTI, Output);
|
|
Template.Instances.Add(Instance);
|
|
}
|
|
return Instance;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compiles the provided CPP unity files. Will
|
|
/// </summary>
|
|
private CPPOutput CompileUnityFilesWithToolChain(ReadOnlyTargetRules Target, UEToolChain ToolChain, CppCompileEnvironment CompileEnvironment, CppCompileEnvironment ModuleCompileEnvironment, List<FileItem> SourceFiles, ActionGraph ActionGraph)
|
|
{
|
|
List<FileItem> NormalFiles = new List<FileItem>();
|
|
List<FileItem> AdaptiveFiles = new List<FileItem>();
|
|
|
|
bool bAdaptiveUnityDisablesPCH = (Target.bAdaptiveUnityDisablesPCH && Rules.PCHUsage == ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs);
|
|
|
|
if ((Target.bAdaptiveUnityDisablesOptimizations || bAdaptiveUnityDisablesPCH) && !Target.bStressTestUnity)
|
|
{
|
|
foreach (FileItem File in SourceFiles)
|
|
{
|
|
// Basic check as to whether something in this module is/isn't a unity file...
|
|
if (File.Location.GetFileName().StartsWith(Unity.ModulePrefix))
|
|
{
|
|
NormalFiles.Add(File);
|
|
}
|
|
else
|
|
{
|
|
AdaptiveFiles.Add(File);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NormalFiles.AddRange(SourceFiles);
|
|
}
|
|
|
|
CPPOutput OutputFiles = new CPPOutput();
|
|
|
|
if (NormalFiles.Count > 0)
|
|
{
|
|
OutputFiles = ToolChain.CompileCPPFiles(CompileEnvironment, NormalFiles, IntermediateDirectory, Name, ActionGraph);
|
|
}
|
|
|
|
if (AdaptiveFiles.Count > 0)
|
|
{
|
|
// Create the new compile environment. Always turn off PCH due to different compiler settings.
|
|
CppCompileEnvironment AdaptiveUnityEnvironment = new CppCompileEnvironment(ModuleCompileEnvironment);
|
|
if(Target.bAdaptiveUnityDisablesOptimizations)
|
|
{
|
|
AdaptiveUnityEnvironment.bOptimizeCode = false;
|
|
}
|
|
AdaptiveUnityEnvironment.PrecompiledHeaderAction = PrecompiledHeaderAction.None;
|
|
|
|
// Write all the definitions out to a separate file
|
|
CreateHeaderForDefinitions(AdaptiveUnityEnvironment, IntermediateDirectory, "Adaptive");
|
|
|
|
// Compile the files
|
|
CPPOutput AdaptiveOutput = ToolChain.CompileCPPFiles(AdaptiveUnityEnvironment, AdaptiveFiles, IntermediateDirectory, Name, ActionGraph);
|
|
|
|
// Merge output
|
|
OutputFiles.ObjectFiles.AddRange(AdaptiveOutput.ObjectFiles);
|
|
OutputFiles.DebugDataFiles.AddRange(AdaptiveOutput.DebugDataFiles);
|
|
}
|
|
|
|
return OutputFiles;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a header file containing all the preprocessor definitions for a compile environment, and force-include it. We allow a more flexible syntax for preprocessor definitions than
|
|
/// is typically allowed on the command line (allowing function macros or double-quote characters, for example). Ensuring all definitions are specified in a header files ensures consistent
|
|
/// behavior.
|
|
/// </summary>
|
|
/// <param name="CompileEnvironment">The compile environment</param>
|
|
/// <param name="IntermediateDirectory">Directory to create the intermediate file</param>
|
|
/// <param name="HeaderSuffix">Suffix for the included file</param>
|
|
static void CreateHeaderForDefinitions(CppCompileEnvironment CompileEnvironment, DirectoryReference IntermediateDirectory, string HeaderSuffix)
|
|
{
|
|
if(CompileEnvironment.Definitions.Count > 0)
|
|
{
|
|
StringBuilder PrivateDefinitionsName = new StringBuilder("Definitions");
|
|
if(!String.IsNullOrEmpty(HeaderSuffix))
|
|
{
|
|
PrivateDefinitionsName.Append('.');
|
|
PrivateDefinitionsName.Append(HeaderSuffix);
|
|
}
|
|
PrivateDefinitionsName.Append(".h");
|
|
|
|
FileReference PrivateDefinitionsFile = FileReference.Combine(IntermediateDirectory, PrivateDefinitionsName.ToString());
|
|
using (StringWriter Writer = new StringWriter())
|
|
{
|
|
WriteDefinitions(CompileEnvironment.Definitions, Writer);
|
|
CompileEnvironment.Definitions.Clear();
|
|
|
|
FileItem PrivateDefinitionsFileItem = FileItem.CreateIntermediateTextFile(PrivateDefinitionsFile, Writer.ToString());
|
|
CompileEnvironment.ForceIncludeFiles.Add(PrivateDefinitionsFileItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a header file containing the module definitions, which also includes the PCH itself. Including through another file is necessary on
|
|
/// Clang, since we get warnings about #pragma once otherwise, but it also allows us to consistently define the preprocessor state on all
|
|
/// platforms.
|
|
/// </summary>
|
|
/// <param name="OutputFile">The output file to create</param>
|
|
/// <param name="Definitions">Definitions required by the PCH</param>
|
|
/// <param name="IncludedFile">The PCH file to include</param>
|
|
/// <returns>FileItem for the created file</returns>
|
|
static FileItem CreatePCHWrapperFile(FileReference OutputFile, IEnumerable<string> Definitions, FileItem IncludedFile)
|
|
{
|
|
// Build the contents of the wrapper file
|
|
StringBuilder WrapperContents = new StringBuilder();
|
|
using (StringWriter Writer = new StringWriter(WrapperContents))
|
|
{
|
|
Writer.WriteLine("// PCH for {0}", IncludedFile.AbsolutePath);
|
|
WriteDefinitions(Definitions, Writer);
|
|
Writer.WriteLine("#include \"{0}\"", IncludedFile.AbsolutePath);
|
|
}
|
|
|
|
// Create the item
|
|
FileItem WrapperFile = FileItem.CreateIntermediateTextFile(OutputFile, WrapperContents.ToString());
|
|
WrapperFile.CachedIncludePaths = IncludedFile.CachedIncludePaths;
|
|
|
|
// Touch it if the included file is newer, to make sure our timestamp dependency checking is accurate.
|
|
if (IncludedFile.LastWriteTime > WrapperFile.LastWriteTime)
|
|
{
|
|
File.SetLastWriteTimeUtc(WrapperFile.AbsolutePath, DateTime.UtcNow);
|
|
WrapperFile.ResetFileInfo();
|
|
}
|
|
return WrapperFile;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write a list of macro definitions to an output file
|
|
/// </summary>
|
|
/// <param name="Definitions">List of definitions</param>
|
|
/// <param name="Writer">Writer to receive output</param>
|
|
static void WriteDefinitions(IEnumerable<string> Definitions, TextWriter Writer)
|
|
{
|
|
foreach(string Definition in Definitions)
|
|
{
|
|
int EqualsIdx = Definition.IndexOf('=');
|
|
if(EqualsIdx == -1)
|
|
{
|
|
Writer.WriteLine("#define {0} 1", Definition);
|
|
}
|
|
else
|
|
{
|
|
Writer.WriteLine("#define {0} {1}", Definition.Substring(0, EqualsIdx), Definition.Substring(EqualsIdx + 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
public static FileItem CachePCHUsageForModuleSourceFile(CppCompileEnvironment ModuleCompileEnvironment, FileItem CPPFile)
|
|
{
|
|
if (!CPPFile.bExists)
|
|
{
|
|
throw new BuildException("Required source file not found: " + CPPFile.AbsolutePath);
|
|
}
|
|
|
|
DateTime PCHCacheTimerStart = DateTime.UtcNow;
|
|
|
|
// Store the module compile environment along with the .cpp file. This is so that we can use it later on when looking
|
|
// for header dependencies
|
|
CPPFile.CachedIncludePaths = ModuleCompileEnvironment.IncludePaths;
|
|
|
|
FileItem PCHFile = ModuleCompileEnvironment.Headers.CachePCHUsageForCPPFile(CPPFile, ModuleCompileEnvironment.IncludePaths, ModuleCompileEnvironment.Platform);
|
|
|
|
if (UnrealBuildTool.bPrintPerformanceInfo)
|
|
{
|
|
double PCHCacheTime = (DateTime.UtcNow - PCHCacheTimerStart).TotalSeconds;
|
|
TotalPCHCacheTime += PCHCacheTime;
|
|
}
|
|
|
|
return PCHFile;
|
|
}
|
|
|
|
|
|
public void CachePCHUsageForModuleSourceFiles(ReadOnlyTargetRules Target, CppCompileEnvironment ModuleCompileEnvironment)
|
|
{
|
|
if(Rules == null || Rules.PCHUsage == ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs || Rules.PrivatePCHHeaderFile != null)
|
|
{
|
|
if(InvalidIncludeDirectiveMessages == null)
|
|
{
|
|
// Find all the source files in this module
|
|
List<FileReference> ModuleFiles = SourceFileSearch.FindModuleSourceFiles(RulesFile);
|
|
|
|
// Find headers used by the source file.
|
|
Dictionary<string, FileReference> NameToHeaderFile = new Dictionary<string, FileReference>();
|
|
foreach(FileReference ModuleFile in ModuleFiles)
|
|
{
|
|
if(ModuleFile.HasExtension(".h"))
|
|
{
|
|
NameToHeaderFile[ModuleFile.GetFileNameWithoutExtension()] = ModuleFile;
|
|
}
|
|
}
|
|
|
|
// Store the module compile environment along with the .cpp file. This is so that we can use it later on when looking for header dependencies
|
|
foreach (FileItem CPPFile in SourceFilesFound.CPPFiles)
|
|
{
|
|
CPPFile.CachedIncludePaths = ModuleCompileEnvironment.IncludePaths;
|
|
}
|
|
|
|
// Find the directly included files for each source file, and make sure it includes the matching header if possible
|
|
InvalidIncludeDirectiveMessages = new List<string>();
|
|
if (Rules != null && Rules.bEnforceIWYU && Target.bEnforceIWYU)
|
|
{
|
|
foreach (FileItem CPPFile in SourceFilesFound.CPPFiles)
|
|
{
|
|
List<DependencyInclude> DirectIncludeFilenames = ModuleCompileEnvironment.Headers.GetDirectIncludeDependencies(CPPFile, bOnlyCachedDependencies: false);
|
|
if (DirectIncludeFilenames.Count > 0)
|
|
{
|
|
string IncludeName = Path.GetFileNameWithoutExtension(DirectIncludeFilenames[0].IncludeName);
|
|
string ExpectedName = CPPFile.Location.GetFileNameWithoutExtension();
|
|
if (String.Compare(IncludeName, ExpectedName, StringComparison.InvariantCultureIgnoreCase) != 0)
|
|
{
|
|
FileReference HeaderFile;
|
|
if (NameToHeaderFile.TryGetValue(ExpectedName, out HeaderFile) && !IgnoreMismatchedHeader(ExpectedName))
|
|
{
|
|
InvalidIncludeDirectiveMessages.Add(String.Format("{0}(1): error: Expected {1} to be first header included.", CPPFile.Location, HeaderFile.GetFileName()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ProcessedDependencies == null)
|
|
{
|
|
DateTime PCHCacheTimerStart = DateTime.UtcNow;
|
|
|
|
bool bFoundAProblemWithPCHs = false;
|
|
|
|
FileItem UniquePCH = null;
|
|
foreach (FileItem CPPFile in SourceFilesFound.CPPFiles) // @todo ubtmake: We're not caching CPPEnvironments for .c/.mm files, etc. Even though they don't use PCHs, they still have #includes! This can break dependency checking!
|
|
{
|
|
// Store the module compile environment along with the .cpp file. This is so that we can use it later on when looking
|
|
// for header dependencies
|
|
CPPFile.CachedIncludePaths = ModuleCompileEnvironment.IncludePaths;
|
|
|
|
// Find headers used by the source file.
|
|
FileItem PCH = ModuleCompileEnvironment.Headers.CachePCHUsageForCPPFile(CPPFile, ModuleCompileEnvironment.IncludePaths, ModuleCompileEnvironment.Platform);
|
|
if (PCH == null)
|
|
{
|
|
throw new BuildException("Source file \"{0}\" is not including any headers. We expect all modules to include a header file for precompiled header generation. Please add an #include statement.", CPPFile.AbsolutePath);
|
|
}
|
|
|
|
if (UniquePCH == null)
|
|
{
|
|
UniquePCH = PCH;
|
|
}
|
|
else if (!UniquePCH.Info.Name.Equals(PCH.Info.Name, StringComparison.InvariantCultureIgnoreCase)) // @todo ubtmake: We do a string compare on the file name (not path) here, because sometimes the include resolver will pick an Intermediate copy of a PCH header file and throw off our comparisons
|
|
{
|
|
// OK, looks like we have multiple source files including a different header file first. We'll keep track of this and print out
|
|
// helpful information afterwards.
|
|
bFoundAProblemWithPCHs = true;
|
|
}
|
|
}
|
|
|
|
ProcessedDependencies = new ProcessedDependenciesClass { UniquePCHHeaderFile = UniquePCH };
|
|
|
|
|
|
if (bFoundAProblemWithPCHs)
|
|
{
|
|
// Map from pch header string to the source files that use that PCH
|
|
Dictionary<FileReference, List<FileItem>> UsageMapPCH = new Dictionary<FileReference, List<FileItem>>();
|
|
foreach (FileItem CPPFile in SourceFilesToBuild.CPPFiles)
|
|
{
|
|
// Create a new entry if not in the pch usage map
|
|
List<FileItem> Files;
|
|
if (!UsageMapPCH.TryGetValue(CPPFile.PrecompiledHeaderIncludeFilename, out Files))
|
|
{
|
|
Files = new List<FileItem>();
|
|
UsageMapPCH.Add(CPPFile.PrecompiledHeaderIncludeFilename, Files);
|
|
}
|
|
Files.Add(CPPFile);
|
|
}
|
|
|
|
if (UnrealBuildTool.bPrintDebugInfo)
|
|
{
|
|
Log.TraceVerbose("{0} PCH files for module {1}:", UsageMapPCH.Count, Name);
|
|
int MostFilesIncluded = 0;
|
|
foreach (KeyValuePair<FileReference, List<FileItem>> CurPCH in UsageMapPCH)
|
|
{
|
|
if (CurPCH.Value.Count > MostFilesIncluded)
|
|
{
|
|
MostFilesIncluded = CurPCH.Value.Count;
|
|
}
|
|
|
|
Log.TraceVerbose(" {0} ({1} files including it: {2}, ...)", CurPCH.Key, CurPCH.Value.Count, CurPCH.Value[0].AbsolutePath);
|
|
}
|
|
}
|
|
|
|
if (UsageMapPCH.Count > 1)
|
|
{
|
|
// Keep track of the PCH file that is most used within this module
|
|
FileReference MostFilesAreIncludingPCH = null;
|
|
int MostFilesIncluded = 0;
|
|
foreach (KeyValuePair<FileReference, List<FileItem>> CurPCH in UsageMapPCH.Where(PCH => PCH.Value.Count > MostFilesIncluded))
|
|
{
|
|
MostFilesAreIncludingPCH = CurPCH.Key;
|
|
MostFilesIncluded = CurPCH.Value.Count;
|
|
}
|
|
|
|
// Find all of the files that are not including our "best" PCH header
|
|
StringBuilder FilesNotIncludingBestPCH = new StringBuilder();
|
|
foreach (KeyValuePair<FileReference, List<FileItem>> CurPCH in UsageMapPCH.Where(PCH => PCH.Key != MostFilesAreIncludingPCH))
|
|
{
|
|
foreach (FileItem SourceFile in CurPCH.Value)
|
|
{
|
|
FilesNotIncludingBestPCH.AppendFormat("{0} (including {1})\n", SourceFile.AbsolutePath, CurPCH.Key);
|
|
}
|
|
}
|
|
|
|
// Bail out and let the user know which source files may need to be fixed up
|
|
throw new BuildException(
|
|
"All source files in module \"{0}\" must include the same precompiled header first. Currently \"{1}\" is included by most of the source files. The following source files are not including \"{1}\" as their first include:\n\n{2}\n\nTo compile this module without implicit precompiled headers, add \"PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;\" to {0}.build.cs.",
|
|
Name,
|
|
MostFilesAreIncludingPCH,
|
|
FilesNotIncludingBestPCH);
|
|
}
|
|
}
|
|
|
|
if (UnrealBuildTool.bPrintPerformanceInfo)
|
|
{
|
|
double PCHCacheTime = (DateTime.UtcNow - PCHCacheTimerStart).TotalSeconds;
|
|
TotalPCHCacheTime += PCHCacheTime;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool IgnoreMismatchedHeader(string ExpectedName)
|
|
{
|
|
switch(ExpectedName)
|
|
{
|
|
case "Stats2":
|
|
case "DynamicRHI":
|
|
case "RHICommandList":
|
|
case "RHIUtilities":
|
|
return true;
|
|
}
|
|
switch(Name)
|
|
{
|
|
case "D3D11RHI":
|
|
case "D3D12RHI":
|
|
case "VulkanRHI":
|
|
case "OpenGLDrv":
|
|
case "MetalRHI":
|
|
case "PS4RHI":
|
|
case "Gnmx":
|
|
case "OnlineSubsystemIOS":
|
|
case "OnlineSubsystemLive":
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determine whether optimization should be enabled for a given target
|
|
/// </summary>
|
|
/// <param name="Setting">The optimization setting from the rules file</param>
|
|
/// <param name="Configuration">The active target configuration</param>
|
|
/// <param name="bIsEngineModule">Whether the current module is an engine module</param>
|
|
/// <returns>True if optimization should be enabled</returns>
|
|
public static bool ShouldEnableOptimization(ModuleRules.CodeOptimization Setting, UnrealTargetConfiguration Configuration, bool bIsEngineModule)
|
|
{
|
|
switch(Setting)
|
|
{
|
|
case ModuleRules.CodeOptimization.Never:
|
|
return false;
|
|
case ModuleRules.CodeOptimization.Default:
|
|
case ModuleRules.CodeOptimization.InNonDebugBuilds:
|
|
return (Configuration == UnrealTargetConfiguration.Debug)? false : (Configuration != UnrealTargetConfiguration.DebugGame || bIsEngineModule);
|
|
case ModuleRules.CodeOptimization.InShippingBuildsOnly:
|
|
return (Configuration == UnrealTargetConfiguration.Shipping);
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a compile environment from a base environment based on the module settings.
|
|
/// </summary>
|
|
/// <param name="Target">Rules for the target being built</param>
|
|
/// <param name="BaseCompileEnvironment">An existing environment to base the module compile environment on.</param>
|
|
/// <returns>The new module compile environment.</returns>
|
|
public CppCompileEnvironment CreateModuleCompileEnvironment(ReadOnlyTargetRules Target, CppCompileEnvironment BaseCompileEnvironment)
|
|
{
|
|
CppCompileEnvironment Result = new CppCompileEnvironment(BaseCompileEnvironment);
|
|
|
|
// Override compile environment
|
|
Result.bFasterWithoutUnity = Rules.bFasterWithoutUnity;
|
|
Result.bOptimizeCode = ShouldEnableOptimization(Rules.OptimizeCode, Target.Configuration, Rules.bTreatAsEngineModule);
|
|
Result.bUseRTTI |= Rules.bUseRTTI;
|
|
Result.bUseAVX = Rules.bUseAVX;
|
|
Result.bEnableBufferSecurityChecks = Rules.bEnableBufferSecurityChecks;
|
|
Result.MinSourceFilesForUnityBuildOverride = Rules.MinSourceFilesForUnityBuildOverride;
|
|
Result.MinFilesUsingPrecompiledHeaderOverride = Rules.MinFilesUsingPrecompiledHeaderOverride;
|
|
Result.bBuildLocallyWithSNDBS = Rules.bBuildLocallyWithSNDBS;
|
|
Result.bEnableExceptions |= Rules.bEnableExceptions;
|
|
Result.bEnableObjCExceptions |= Rules.bEnableObjCExceptions;
|
|
Result.bEnableShadowVariableWarnings = Rules.bEnableShadowVariableWarnings;
|
|
Result.bEnableUndefinedIdentifierWarnings = Rules.bEnableUndefinedIdentifierWarnings;
|
|
|
|
// Set the macro used to check whether monolithic headers can be used
|
|
if (Rules.bTreatAsEngineModule && (!Rules.bEnforceIWYU || !Target.bEnforceIWYU))
|
|
{
|
|
Result.Definitions.Add("SUPPRESS_MONOLITHIC_HEADER_WARNINGS=1");
|
|
}
|
|
|
|
// Add a macro for when we're compiling an engine module, to enable additional compiler diagnostics through code.
|
|
if (Rules.bTreatAsEngineModule)
|
|
{
|
|
Result.Definitions.Add("UE_IS_ENGINE_MODULE=1");
|
|
}
|
|
else
|
|
{
|
|
Result.Definitions.Add("UE_IS_ENGINE_MODULE=0");
|
|
}
|
|
|
|
// Switch the optimization flag if we're building a game module. Also pass the definition for building in DebugGame along (see ModuleManager.h for notes).
|
|
if (!Rules.bTreatAsEngineModule)
|
|
{
|
|
if (Target.Configuration == UnrealTargetConfiguration.DebugGame)
|
|
{
|
|
Result.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=1");
|
|
}
|
|
else
|
|
{
|
|
Result.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=0");
|
|
}
|
|
}
|
|
|
|
// For game modules, set the define for the project name. This will be used by the IMPLEMENT_PRIMARY_GAME_MODULE macro.
|
|
if (!Rules.bTreatAsEngineModule)
|
|
{
|
|
// Make sure we don't set any define for a non-engine module that's under the engine directory (eg. UE4Game)
|
|
if (Target.ProjectFile != null && RulesFile.IsUnderDirectory(Target.ProjectFile.Directory))
|
|
{
|
|
string ProjectName = Target.ProjectFile.GetFileNameWithoutExtension();
|
|
Result.Definitions.Add(String.Format("UE_PROJECT_NAME={0}", ProjectName));
|
|
}
|
|
}
|
|
|
|
// Add the module's public and private definitions.
|
|
Result.Definitions.AddRange(PublicDefinitions);
|
|
Result.Definitions.AddRange(Rules.PrivateDefinitions);
|
|
|
|
// Add the project definitions
|
|
if(!Rules.bTreatAsEngineModule)
|
|
{
|
|
Result.Definitions.AddRange(Rules.Target.ProjectDefinitions);
|
|
}
|
|
|
|
// Setup the compile environment for the module.
|
|
SetupPrivateCompileEnvironment(Result.IncludePaths.UserIncludePaths, Result.IncludePaths.SystemIncludePaths, Result.Definitions, Result.AdditionalFrameworks, (Rules != null)? Rules.bLegacyPublicIncludePaths.Value : true);
|
|
|
|
// @hack to skip adding definitions to compile environment, they will be baked into source code files
|
|
if (bSkipDefinitionsForCompileEnvironment)
|
|
{
|
|
Result.Definitions.Clear();
|
|
Result.IncludePaths.UserIncludePaths = new HashSet<DirectoryReference>(BaseCompileEnvironment.IncludePaths.UserIncludePaths);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a compile environment for a shared PCH from a base environment based on the module settings.
|
|
/// </summary>
|
|
/// <param name="Target">The target being built</param>
|
|
/// <param name="BaseCompileEnvironment">An existing environment to base the module compile environment on.</param>
|
|
/// <returns>The new shared PCH compile environment.</returns>
|
|
public CppCompileEnvironment CreateSharedPCHCompileEnvironment(UEBuildTarget Target, CppCompileEnvironment BaseCompileEnvironment)
|
|
{
|
|
CppCompileEnvironment CompileEnvironment = new CppCompileEnvironment(BaseCompileEnvironment);
|
|
|
|
// Use the default optimization setting for
|
|
CompileEnvironment.bOptimizeCode = ShouldEnableOptimization(ModuleRules.CodeOptimization.Default, Target.Configuration, Rules.bTreatAsEngineModule);
|
|
|
|
// Override compile environment
|
|
CompileEnvironment.bIsBuildingDLL = !Target.ShouldCompileMonolithic();
|
|
CompileEnvironment.bIsBuildingLibrary = false;
|
|
|
|
// Add a macro for when we're compiling an engine module, to enable additional compiler diagnostics through code.
|
|
if (Rules.bTreatAsEngineModule)
|
|
{
|
|
CompileEnvironment.Definitions.Add("UE_IS_ENGINE_MODULE=1");
|
|
}
|
|
else
|
|
{
|
|
CompileEnvironment.Definitions.Add("UE_IS_ENGINE_MODULE=0");
|
|
}
|
|
|
|
// Switch the optimization flag if we're building a game module. Also pass the definition for building in DebugGame along (see ModuleManager.h for notes).
|
|
if (!Rules.bTreatAsEngineModule)
|
|
{
|
|
if (Target.Configuration == UnrealTargetConfiguration.DebugGame)
|
|
{
|
|
CompileEnvironment.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=1");
|
|
}
|
|
else
|
|
{
|
|
CompileEnvironment.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=0");
|
|
}
|
|
}
|
|
|
|
// Add the module's private definitions.
|
|
CompileEnvironment.Definitions.AddRange(PublicDefinitions);
|
|
|
|
// Find all the modules that are part of the public compile environment for this module.
|
|
Dictionary<UEBuildModule, bool> ModuleToIncludePathsOnlyFlag = new Dictionary<UEBuildModule, bool>();
|
|
FindModulesInPublicCompileEnvironment(ModuleToIncludePathsOnlyFlag);
|
|
|
|
// Now set up the compile environment for the modules in the original order that we encountered them
|
|
foreach (UEBuildModule Module in ModuleToIncludePathsOnlyFlag.Keys)
|
|
{
|
|
Module.AddModuleToCompileEnvironment(null, CompileEnvironment.IncludePaths.UserIncludePaths, CompileEnvironment.IncludePaths.SystemIncludePaths, CompileEnvironment.Definitions, CompileEnvironment.AdditionalFrameworks, (Rules != null)? Rules.bLegacyPublicIncludePaths.Value : true);
|
|
}
|
|
return CompileEnvironment;
|
|
}
|
|
|
|
public class UHTModuleInfoCacheType
|
|
{
|
|
public UHTModuleInfoCacheType(IEnumerable<string> InHeaderFilenames, UHTModuleInfo InInfo)
|
|
{
|
|
HeaderFilenames = InHeaderFilenames;
|
|
Info = InInfo;
|
|
}
|
|
|
|
public IEnumerable<string> HeaderFilenames = null;
|
|
public UHTModuleInfo Info = null;
|
|
}
|
|
|
|
private UHTModuleInfoCacheType UHTModuleInfoCache = null;
|
|
|
|
/// Total time spent generating PCHs for modules (not actually compiling, but generating the PCH's input data)
|
|
public static double TotalPCHGenTime = 0.0;
|
|
|
|
/// Time spent caching which PCH header is included by each module and source file
|
|
public static double TotalPCHCacheTime = 0.0;
|
|
|
|
|
|
/// <summary>
|
|
/// If any of this module's source files contain UObject definitions, this will return those header files back to the caller
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public UHTModuleInfoCacheType GetCachedUHTModuleInfo(EGeneratedCodeVersion GeneratedCodeVersion)
|
|
{
|
|
if (UHTModuleInfoCache == null)
|
|
{
|
|
List<FileReference> HeaderFiles = new List<FileReference>();
|
|
FileSystemName[] ExcludedFolders = UEBuildPlatform.GetBuildPlatform(Rules.Target.Platform, true).GetExcludedFolderNames();
|
|
FindHeaders(new DirectoryInfo(ModuleDirectory.FullName), ExcludedFolders, HeaderFiles);
|
|
UHTModuleInfo Info = ExternalExecution.CreateUHTModuleInfo(HeaderFiles, Name, RulesFile, ModuleDirectory, Type, GeneratedCodeVersion);
|
|
UHTModuleInfoCache = new UHTModuleInfoCacheType(Info.PublicUObjectHeaders.Concat(Info.PublicUObjectClassesHeaders).Concat(Info.PrivateUObjectHeaders).Select(x => x.AbsolutePath).ToList(), Info);
|
|
}
|
|
|
|
return UHTModuleInfoCache;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all the headers under the given base directory, excluding any other platform folders.
|
|
/// </summary>
|
|
/// <param name="BaseDir">Base directory to search</param>
|
|
/// <param name="ExcludeFolders">Array of folders to exclude</param>
|
|
/// <param name="Headers">Receives the list of headers that was found</param>
|
|
static void FindHeaders(DirectoryInfo BaseDir, FileSystemName[] ExcludeFolders, List<FileReference> Headers)
|
|
{
|
|
if (!ExcludeFolders.Any(x => x.DisplayName.Equals(BaseDir.Name, StringComparison.InvariantCultureIgnoreCase)))
|
|
{
|
|
foreach (DirectoryInfo SubDir in BaseDir.EnumerateDirectories())
|
|
{
|
|
FindHeaders(SubDir, ExcludeFolders, Headers);
|
|
}
|
|
foreach (FileInfo File in BaseDir.EnumerateFiles("*.h"))
|
|
{
|
|
Headers.Add(new FileReference(File));
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void GetAllDependencyModules(List<UEBuildModule> ReferencedModules, HashSet<UEBuildModule> IgnoreReferencedModules, bool bIncludeDynamicallyLoaded, bool bForceCircular, bool bOnlyDirectDependencies)
|
|
{
|
|
List<UEBuildModule> AllDependencyModules = new List<UEBuildModule>();
|
|
AllDependencyModules.AddRange(PrivateDependencyModules);
|
|
AllDependencyModules.AddRange(PublicDependencyModules);
|
|
if (bIncludeDynamicallyLoaded)
|
|
{
|
|
AllDependencyModules.AddRange(DynamicallyLoadedModules);
|
|
}
|
|
|
|
foreach (UEBuildModule DependencyModule in AllDependencyModules)
|
|
{
|
|
if (!IgnoreReferencedModules.Contains(DependencyModule))
|
|
{
|
|
// Don't follow circular back-references!
|
|
bool bIsCircular = HasCircularDependencyOn(DependencyModule.Name);
|
|
if (bForceCircular || !bIsCircular)
|
|
{
|
|
IgnoreReferencedModules.Add(DependencyModule);
|
|
|
|
if (!bOnlyDirectDependencies)
|
|
{
|
|
// Recurse into dependent modules first
|
|
DependencyModule.GetAllDependencyModules(ReferencedModules, IgnoreReferencedModules, bIncludeDynamicallyLoaded, bForceCircular, bOnlyDirectDependencies);
|
|
}
|
|
|
|
ReferencedModules.Add(DependencyModule);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void RecursivelyAddPrecompiledModules(List<UEBuildModule> Modules)
|
|
{
|
|
if (!Modules.Contains(this))
|
|
{
|
|
Modules.Add(this);
|
|
|
|
// Get the dependent modules
|
|
List<UEBuildModule> DependentModules = new List<UEBuildModule>();
|
|
if (PrivateDependencyModules != null)
|
|
{
|
|
DependentModules.AddRange(PrivateDependencyModules);
|
|
}
|
|
if (PublicDependencyModules != null)
|
|
{
|
|
DependentModules.AddRange(PublicDependencyModules);
|
|
}
|
|
if (DynamicallyLoadedModules != null)
|
|
{
|
|
DependentModules.AddRange(DynamicallyLoadedModules);
|
|
}
|
|
|
|
// Find modules for each of them, and add their dependencies too
|
|
foreach (UEBuildModule DependentModule in DependentModules)
|
|
{
|
|
DependentModule.RecursivelyAddPrecompiledModules(Modules);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|