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 ========================== MAJOR FEATURES + CHANGES ========================== Change 3016173 on 2016/06/16 by Lukasz.Furman fixed path updates in nested move tasks #jira FORT-25742 Change 3015722 on 2016/06/15 by Bob.Tellez #UE4 Avoiding a crash in FOnlinePartySystemMcp::PublishPartyInfoToPresence #JIRA OR-14102 Change 3015626 on 2016/06/15 by Bob.Tellez #UE4 Experimental fix for hitches involving spinlocks in windows. #JIRA FORT-25253 Change 3015473 on 2016/06/15 by Bob.Tellez #UE4 Compiling CrashReportClient in VS2013 instead of 2015 until we can figure out the appropriate way to install the redist on end-user machines. #JIRA FORT-25748 Change 3014721 on 2016/06/15 by Bob.Tellez #UE4 Returning false in cases where we want to skip replication of GameplayAbilities structures in NetDeltaSerialize. This fixes a bug where actors trying to become net dormant were not allowed because they were continuously reporting that they had data to replicate. #JIRA FORT-25689 Change 3014323 on 2016/06/15 by Rob.Cannaday When kicked from lobby beacon, restore the persistent party after leaving the previous persistent party #jira FORT-25407 #tests front end parties, being kicked from outpost lobby Change 3013712 on 2016/06/14 by Bob.Tellez #UE4 Fix DrawNetDriverDebug crash during map transitions Change 3013418 on 2016/06/14 by Mark.Satterthwaite Don't release Metal buffers directly into the buffer pool, instead defer this until the command-buffer is known to have finished. This prevents the CPU from trying to modify the buffer while the GPU is still reading it if the GPU has fallen so far behind the CPU and therefore eliminates one possible cause of invalid access on the GPU. #jira FORT-24510 Change 3013394 on 2016/06/14 by Mark.Satterthwaite Report Metal command-buffer failures in MetalQuery in the same way as MetalCommandList and make them fatal as well. This ensures that the game doesn't try to continue if the commands failed as that is unsafe. #jira FORT-24808 Change 3012977 on 2016/06/14 by Fred.Kimberley Add a blueprint exposed function to evaluate an attribute from a given base value. Change 3012755 on 2016/06/14 by Bob.Tellez #UE4 ExclusiveInternalFlags is now respected when passing in a null ObjectPackage in StaticFindObjectFastInternalThreadSafe #JIRA FORT-113 Change 3011948 on 2016/06/13 by Mark.Satterthwaite Workaround a Fortnite crash on launch for Mac OpenGL - one or more shaders are using the bit-cast operators (asuint(), asfloat()) that aren't available with GLSL version 150. In order to use them the GLSL version must be 330 which means switching the version tag at runtime. There will be Mac GPUs on 10.10.5 which don't correctly implement these instructions so this really isn't a fix - that would be to change shaders to not use SM5-level instructions. Change 3011659 on 2016/06/13 by Bob.Tellez #UE4 Better handling of checked state in SGameplayTagWidget::IsTagChecked. Checking direct child tags was not sufficient and also not needed since HasTag allows you to follow parent tags when checking for an explicit tag. Change 3011647 on 2016/06/13 by Rob.Cannaday Fix for multiple account login not kicking previous logins Client was not parsing response from backend. Client was expecting content-type to be "application/json" (using FString::Equals). Backend was returning "application/json;charset=UTF-8". Changed usage from FString::Equals to FString::StartsWith #jira FORT-25452 #tests multiple account login, frontend only Change 3011436 on 2016/06/13 by Nick.Cooper #UE4 - Added bRelativeToInitialFOV option to UCameraAnim, defaulting to true. If turned off, camera anims will use the camera's current FOV as the initial FOV for the animation #jira FORT-23606 Change 3010411 on 2016/06/12 by Bob.Tellez #UE4 Fix for a possible case where a reference to an async loading package that would contain a level gets replicated before the level it contains is fully serialized, causing network loading code client side to attempt to load the package even though it is not allowed to load maps. #jira FORT-113, FORT-22222 Change 3009885 on 2016/06/10 by Billy.Bramer #jira FORT-25361 [FORT-25361] Health and shield values are incorrect when slotting survivors with bonuses - Fix some resultant bugs from swapping attributes to be struct-based: - Fix issue wherein the initial creation of the client-side aggregator could be initialized with the computed final value from the server, resulting in incorrect client-side math - Fix issue where subsequent changes to the aggregator's base value on the client would be lost Change 3009514 on 2016/06/10 by Bob.Tellez #UE4 Remove final usage of the task graph in WmfMediaPlayer to dodge shutdown crashes. Change 3009197 on 2016/06/10 by Michael.Trepka Disabled reverb on Mac again. It's too expensive and doesn't fix FORT-22090 anyway Change 3008392 on 2016/06/09 by Ben.Zeigler #jira FORT-25244 Change it so application error codes like 400/404 do not cause the mcp to think it is disconnected from the backend. Only 408, 501, 502, and 504 now result in ServiceUnavailable. Change 3008106 on 2016/06/09 by Lukasz.Furman fixed cutting corners near navmesh obstacles in detour crowd's string pulling #jira FORT-24981 Change 3008039 on 2016/06/09 by Bob.Tellez #UE4 Fixed conversion of TAssetPtr to UObject* properties for the case where the referenced object is not already loaded. Change 3007864 on 2016/06/09 by Fred.Kimberley Updates to supporting attributes as structs. Adding functionality that makes them easier to use and override in projects. Change 3007682 on 2016/06/09 by Michael.Trepka Re-enabled reverb on Mac Change 3006971 on 2016/06/08 by Saul.Abreu #fortnite #jira FORT-25169 Added node costs types, cost amounts, and remaining balance for each cost type to the NodePurchase analytics event. Change3006933on 2016/06/08 by Chris.Gagnon Fixed up all the Power levle widget use cases. #Jira FORT-23472, FORT-24132, FORT-24144, FORT-24952, FORT-24924 Change 3006633 on 2016/06/08 by Dmitry.Rekman Linux: propagate ensure message to the CR (FORT-23030). - Without this, ensure() has a generic "SIGTRAP" error message, which is misleading for QA. #tests Tried "debug ensure" a few times, observed crash report (on the website) with the proper message #jira FORT-23030 Change 3006036 on 2016/06/08 by Rob.Cannaday Remove warning about missing "recentplayers" field. The absence of the field is gracefully handled in the client and is only absent if the list is absent on the server. #jira FORT-18687 Change 3005216 on 2016/06/07 by Bob.Tellez #UE4 Avoiding layout invalidation if you use SetEnabled to set an identical enabled state. This is the same as how SetVisibility works. Change 3004857 on 2016/06/07 by Rob.Cannaday Fix for incorrect reason displayed for inability to join party #jira FORT-13517 Change 3004811 on 2016/06/07 by Michael.Trepka Increased the number of input buses for CoreAudio 3D Mixer to support 64 audio channels. Also, added a warning to FAudioDevice::StartSources so it doesn't silently ignore sound source initialization failures. Change 3004553 on 2016/06/07 by Lukasz.Furman fixed AnySpawners activating before navmesh unlock & rebuild #jira FORT-25067 Change 3004083 on 2016/06/07 by Bob.Tellez #UE4 Fixing GenerateApplicationPath for monolithic games. Change 3003457 on 2016/06/06 by Bob.Tellez #UE4 Add a little info to a warning about failing to load a file for streaming. Change 3003256 on 2016/06/06 by Bob.Tellez #UE4 Fixed a bug where not having a crash report would cause CrashReportClient not not properly exit on Mac Change 3003146 on 2016/06/06 by jonathan.lindquist switching from a ceil and lerp technique to an if statement to provide better transform results. Change 3002048 on 2016/06/06 by Daniel.Broder Support for setting Scalar and Vector Materials by Index rather than by name on MIDs. This feature allows much better performance in cases where large numbers of parameters are being set per frame and where the indices can be cached by the calling code in an initialization step. #RB Stephan.Delmer #CodeReview Bob.Tellez #UE4 #ReleaseNote Change 3001315 on 2016/06/05 by Daniel.Broder Fixed crash that could occur when the FPhysScene* was null (the world has no PhysicsScene) in USkeletalMeshComponent::TermArticulated(). That could happen when loading a world without fully instantiating it, such as when right-clicking a world in the context browser rather than opening the world directly. #RB Stephan.Delmer Ori, I wasn't sure if the whole line (and the line below it using PScene) should be moved within the if (PhysScene) block or not, but this change seems to fix it. If they can safely be moved, that would be presumably more efficeint though (since we'd only compare vs. nullptr once). #CodeReview Ori.Cohen #UE4 #Fortnite #BugFix Change 3001001 on 2016/06/04 by Fred.Kimberley Added meta data about attributes and a post serialize function so we can recover attributes that have changed their type. Adding Fortnite specific attribute type specialization. This type enforces minimum and maximum values for attributes. Change 3000613 on 2016/06/03 by Sam.Spiro #fort online 24747 Take change from SamZ to get connection change delegates firing correctly Add a delegate to the frontend player controller to logout if the connection goes bad (when all retries have failed) #RB Ben.Zeigler Change 3000482 on 2016/06/03 by Rob.Cannaday Fix problem where newly added friends don't recognize party invitations #jira FORT-19415 From CL2953432: Ignore presence updates for local user with different resources #jira OR-19929 #tests front end party invites Change 2998044 on 2016/06/02 by Lukasz.Furman fixed path box intersection test used to verify if hotspot is still required for updated path #jira FORT-24422 Change 2997948 on 2016/06/02 by Eric.Newman Moved ProdCom to bottom of file w/ deprecation comment, and clarified deprecation criteria. Will probably need to be removed in //UE4 first and check for any fallout from EC jobs failing Change 2997660 on 2016/06/02 by Chris.Wood Changed Linux server crash handler to force CRC log paths to match main engine log. [UE-30259] - Some server crashes are missing from crashreporter database Should allow us to have CRC logs uploaded to S3 along with main logs easily. Change 2996702 on 2016/06/01 by Bob.Tellez #UE4 You can now use Edit Asset on Level assets in the reference viewer. Change2996683on 2016/06/01 by Tim.Tillotson #fortnite Fix analytics comments, changed a few NULL to nullptr, and removed stale code. #JIRA FORT-23833 Change 2996548 on 2016/06/01 by Bob.Tellez #Fortnite Fixing up or deleting remaining references to homebase buildings. HBOnboarding_BuildHeroBuilding is the last reference now and it will be removed soon. Change 2996322 on 2016/06/01 by Bob.Tellez #UE4 Fix for specifying more than one ini override on the command line Change 2996306 on 2016/06/01 by Bob.Tellez #UE4 Delete unneeded and broken script to unlock files in xcode. Does not work since XCode 6.3. Change 2995634 on 2016/06/01 by Jonathan.Lindquist imrpoving the wind magnitude and noise texture Change 2995249 on 2016/05/31 by Bob.Tellez #UE4 Importing "INVALID" in FUniqueNetIdRepl no longer triggers the warning about using ImportText during cook. Change 2992135 on 2016/05/26 by Bob.Tellez #UE4 extern for GuardedMain in LaunchLinux to fix nonunity Change 2991912 on 2016/05/26 by jonathan.lindquist moved a texture sample into a new grouping Change 2991738 on 2016/05/26 by Bob.Tellez #UE4 Level SaveAs now duplicates the world before saving it. This fixes a problem where level assets had the same guids for objects saved in them, which causes LazyObjectPtr issues when they are both in memory at the same time since they can not be uniquely identified. Change 2991449 on 2016/05/26 by Lukasz.Furman AI Ftests will now delay spawning until navmesh is ready #fortnite Change 2990705 on 2016/05/25 by Chris.Gagnon New stats panel, upon stat changes there is a delta pop up. New Squads Tab. Navigation from nodes to squad slots working. Added GetAnimationCurrentTime() to UMG Animation API. #RB Fred.Kimberley, Saul.Abreu Change 2990286 on 2016/05/25 by Bob.Tellez #UE4 Fix logging error regarding max tag container replication size Change 2990285 on 2016/05/25 by Bob.Tellez #UE4 Fix for crash when using "ShowDebug Game" client side Change 2989977 on 2016/05/25 by Lukasz.Furman auto generating navigation bounds from building grid data, UnitNavMeshBounds volume is no longer required #fortnite Change 2989174 on 2016/05/24 by Bob.Tellez #UE4 Added GC reason to the log message declaring that we are doing a GC during the cook commandlet. Change 2988571 on 2016/05/24 by Jonathan.Lindquist submitting a fix for grass-like hierarchy layouts Change 2985428 on 2016/05/20 by Bob.Tellez Experimenting with making UGS CIS not rebuild UBT when incremental building. Change 2985319 on 2016/05/20 by Bob.Tellez #UE4 Removing NumActorChannelsReadyDormant stat as it is somewhat expensive to calculate. Change 2985258 on 2016/05/20 by Billy.Bramer - Add GetFloatAttributeBase and GetFloatAttributeBaseFromAbilitySystemComponent to AbilitySystemBlueprintLibrary, allows querying for a base value of an attribute Change 2985157 on 2016/05/20 by Bob.Tellez Experimenting with non-unity CIS Change 2984664 on 2016/05/19 by Bob.Tellez #UE4 Pasting multiple cells into the property matrix no longer depends on your selected tiles, only your target cell. This is to match the behavior in Excel. Pasting a single cell into multiple cells remains unchanged. Change 2984663 on 2016/05/19 by Bob.Tellez #UE4 Fixed a crash in the property matrix involving going into edit mode on rows that include widgets that are not editable. Change 2984613 on 2016/05/19 by Bob.Tellez #UE4 You can now text import gameplay tags by directly using the tag string (i.e. Evolution.Hero.Soldier). This allows pasting these strings directly into the property matrix or other property-based editors. Change 2984508 on 2016/05/19 by Billy.Bramer - Add constructors for the new struct based attribute Change 2983883 on 2016/05/19 by Lukasz.Furman disabled movement mode in EQS testing pawn to prevent it from falling at PIE start #ue4 Change 2983770 on 2016/05/19 by Bob.Tellez #UE4 Fixed a bug where "OutputToScreen" BP messages would get stuck disabled after a screenshot (using a number of different codepaths). All screenshots now preserve the state of the "suppress messages" bool. #JIRA FORT-24303 Change 2982306 on 2016/05/18 by Bob.Tellez Also experimenting with not updating version files in UGS CIS. Change 2982154 on 2016/05/18 by Lukasz.Furman changed navwalking geometry conforming to use building prop special case #jira FORT-24215 Change 2982019 on 2016/05/18 by Bob.Tellez Trying out incremental CIS builds Change 2981192 on 2016/05/17 by Bob.Tellez #UE4 No longer staging movie files for dedicated server builds. Change 2981023 on 2016/05/17 by Lukasz.Furman added new mode for NavWalking geometry conforming: prefer height closer to current one this should allow standing on top of props or walking off them in lower LOD, instead of moving at ground level - needed for survivors on low cars Change 2980578 on 2016/05/17 by Lukasz.Furman added option for disabling path replan in crowd manager, turned it off in fortnite this must be handled through path update events and corridor assignment or else hotspot detection will break #jira FORT-24116 Change 2980364 on 2016/05/17 by Lukasz.Furman unified bounds tests for applying navmesh modifiers, always expanding bounds one cell height on Z axis to cover for voxelization roundings #jira FORT-24045 Change 2980360 on 2016/05/17 by Lukasz.Furman more detailed logs for using custom navlinks #jira FORT-23990 Change 2979880 on 2016/05/16 by Bob.Tellez #UE4 Raising scalability threshold for high end machines to adjust for modern hardware. Change 2979522 on 2016/05/16 by Saul.Abreu #fortnite Added IsValid BP-exposed method for FGameplayAttribute (which is already a BP-exposed struct type), as there is no existing method of validating a gameplay attribute from blueprints. Useful for UI that represents an attribute. Change 2977690 on 2016/05/13 by Daniel.Broder Made most FBox functions FORCEINLINE to improve DebugGame performance. #Fortnite: This change (just on IsInsideOrOn()) improved DebugGame performance for one part of Wind performance in Fortnite by ~18%. #CodeReview Bob.Tellez #UE4 #ReleaseNotes Change 2977517 on 2016/05/13 by Daniel.Broder Added ForceInline to TIndexedContainerIterator<...>::operator!=(...). This change improved DebugGame performance of a for loop using ranged-based syntax by ~27%! #CodeReview Bob.Tellez #Fortnite Wind perf improvement in DebugGame builds. #UE4 #ReleaseNote Change2974910on 2016/05/11 by Bob.Tellez #UE4 More graceful handling of export class names in string asset references. Change 2974095 on 2016/05/11 by Bob.Tellez #UE4 Fixed a bug where the RenderTargetOutputFormat for velocity rendering when using r.BasePassOutputsVelocity=True was using the wrong output index. Change 2973663 on 2016/05/11 by John.Abercrombie [implemented by Ben.Marsh] UBT: Add a config setting to allow overriding the output directory for PCH files. To use, edit Engine\Saved\UnrealBuildTool\BuildConfiguration.xml and add: <BuildConfiguration> <PCHOutputDirectory>D:\TestOutputDir</PCHOutputDirectory> </BuildConfiguration> Change2972603on 2016/05/10 by Saad.Nader #Fort Added the catalyst to the requirements of an evolvable item. It will only disable the evolution button if there is a catalyst. Change 2971741 on 2016/05/09 by Bob.Tellez #UE4 Adding more context to an error message about serializing FUniqueNetIdRepl during cook. Change 2969838 on 2016/05/06 by Bob.Tellez #Fortnite Added FN PS4 to build scripts Change 2969542 on 2016/05/06 by Bob.Tellez #UE4 Fixed a crash that involved renaming SCS nodes during compile on load. #JIRA FORT-23754 Change 2969520 on 2016/05/06 by Billy.Bramer - Fix missing virtual destructor now that the initter struct has virtual members Change 2969467 on 2016/05/06 by Billy.Bramer - Change FAttributeSetInitter to only contain pure virtual functions in preparation for making it easier to provide a custom implementation per game - Change the existing example FAttributeSetInitter to be called FAttributeSetInitterDiscreteLevels, make it derive from FAttributeSetInitter (DiscreteLevels is now allocated by default for now) - Add support for the new struct-based attribute type to FAttributeSetInitterDiscreteLevels - Fix typos in the initter - Convert usages of FString in AbilitySystemGlobals to FStringAssetReference, where appropriate - Allow attribute init data to come from several curve tables instead of just one - Remove reimport bindings from attribute metadata and global curve table, as neither was in use Change 2969279 on 2016/05/06 by John.Abercrombie Behavior tree auxilary nodes, parallel tasks, active tasks, and aborting tasks shouldn't be ticked while the behavior tree is paused Change 2966311 on 2016/05/04 by Rob.Cannaday Fix PS4 Orion players being able to whisper chat with non-Orion players #jira OR-20626 #tests chat with launcher, fortnite (From //Orion/Dev-General CL 2963555) Change 2966255 on 2016/05/04 by Bob.Tellez #UE4 Added an ensure to track down the cause of FORT-23604 and to gracefully recover from what would have been a crash. #JIRA FORT-23604 Change 2966083 on 2016/05/04 by Bob.Tellez #UE4 Adjusted material quality level for "Medium" settings to medium quality. High quality is still used in High and Epic scalability levels. Change 2965669 on 2016/05/04 by Nicholas.Davies Change the restricted platform ID to PSN to prevent Fortnite > PS4 paragon whisper chat #OPP-5268 Integrate PS4 Chat block Social and OSS code to Fortnite, UT, and Launcher #RB Antony.Carter Change 2965316 on 2016/05/03 by Ben.Zeigler #jira FORT-23600 Fix issue where stalled mcp queries never finished. This causes the query to properly fail Manual merge of CL #2907874: When MCP cancels a request due to its required auth failing, the http retry system would never kick off the complete delegates. This was due to the system only adding a request to its list once ProcessRequest was called, which does not happen in the above case. The fix is to add the request to the list when it is cancelled if we did not find it. Change 2965164 on 2016/05/03 by Bob.Tellez #UE4 Fix for Crash in WmfMedia for when the player is destroyed while loading media. Thanks MaxP! Change 2963754 on 2016/05/02 by Billy.Bramer - Switch ability system from binding to OnPostWorldCreation to PreLoadMap for its cleanup functions, as OnPostWorldCreation is called repeatedly with sublevels and can cause data loss - This is a bit of a stopgap, as where and when this happens should probably be configured per game (example: a long session game like an MMO would want to trigger these on something other than a map transition possibly) Change 2962922 on 2016/05/02 by Lukasz.Furman fixed gameplay debugger in "simulate in editor" mode Change 2959860 on 2016/04/28 by David.Nikdel #OGF #McpProfile - Add Profile Write Lock support to client API NOTE: Still need to finish backend support so haven't been able to test yet but this is enough for API hookup NOTE2: You may see a log message about "write lock unexpectedly released" when you do your first command after locking. This is expected because the backend isn't sending down the write lock timeout yet. #CodeReview: Ben.Zeigler Change 2959810 on 2016/04/28 by Jonathan.Lindquist A few more saftey measures to warn the user of incorrect settings and faulty meshes. (In response a licensee's question) Change 2959336 on 2016/04/28 by Bob.Tellez #UE4 Some improvements to asset save time: Added an early-out in PackageBackup to avoid inspecting files in cases where we don't care about the resutls. Also now using GetObjectsWithOuter when passing in a package list to GetObjectsInPackages (which probably should be renamed to GetAssetsInPackage) Change 2958942 on 2016/04/28 by Jonathan.Lindquist Wrote a new portion of pivot painter 2 that unifies edge normals across multiple static meshes Change 2958644 on 2016/04/27 by Jonathan.Lindquist lowering default recursive steps Change 2956612 on 2016/04/26 by Jonathan.Lindquist A few new saftey measures Change 2956197 on 2016/04/26 by Fred.Kimberley Fix a bug where a delegate won't be fired if the base value of an attribute has been changed and the attribute is the new type and doesn't have an aggregator. Fix a bug in gameplay effect tag matching where the deprecated tag is being checked but not the current one. Change 2955386 on 2016/04/25 by Jonathan.Lindquist Fixed a ui bug related to the first time path geo generator is run Pivot painter 2 has a new feature. It duplicates each model in a hierarchy, combines them and then welds their verts. Change 2955230 on 2016/04/25 by Billy.Bramer - Add a debug gameplay tag to string blueprint function, should only be used for debugging purposes Change 2954899 on 2016/04/25 by Fred.Kimberley Added a new backing data type for gameplay attributes. The new type holds both the current and base values. Currently, this new type can coexist with numeric types for gameplay attributes. Change 2953511 on 2016/04/22 by Bob.Tellez #UE4 Bumping up texture streaming pool allowance for min spec and redistributing mid an high to match. Also reduced mip bias at min spec. Change 2953496 on 2016/04/22 by Chris.Gagnon When the console closes it now properly restores the viewports input state (both focus and capture). Change 2952930 on 2016/04/22 by Lukasz.Furman fixed behavior tree getting stuck on instantly finished gameplay tasks #jira FORT-23041 Change 2951765 on 2016/04/21 by John.Abercrombie Removed unused code when initializing attribute sets Change 2951617 on 2016/04/21 by Jonathan.Lindquist new elements to the grass shader to include wind influence also adding a test model and the latest version of canopy creator Change 2950861 on 2016/04/21 by Jonathan.Lindquist Submitting a new material for grass so that it may react to the wind New wind test maps Functions to support global wind a new "fuzzy" mat functions Adding wind to the rift portals Change 2950725 on 2016/04/20 by Bob.Tellez Fixups for non NewEC in GetLastSucceededCL Change 2950695 on 2016/04/20 by Bob.Tellez Adding a small helper function to get the last succeeded CL of a given node. Change 2950616 on 2016/04/20 by Maury.Mountain hook up the pivot (+ (0,-1,0)) section of material function that was causing offset motion from pivots Change 2950207 on 2016/04/20 by Bob.Tellez #UE4 NoTimeouts is now respected even in the initial connection timeout. This fixes a bug where a large stall when starting pie causes you to transition to the entry map. Change 2950162 on 2016/04/20 by Lukasz.Furman fixed processing of repath requests, added infinite loop protection #jira FORT-23090 Change 2949974 on 2016/04/20 by Lukasz.Furman another batch of fixes for hotspot tasks getting out of sync: abort move is now ignored if instigated by new task at goal, clearing hotspot data on dying while gameplay tasks are still accessible, ignoring move resume when controller is being destroyed Change 2949923 on 2016/04/20 by Rob.Cannaday FOnlineIdentityMcp: Cancel ClientAuthRequests and ExternalAuthRequests on shutdown #tests PIE start game / shutdown Change 2949210 on 2016/04/19 by Bob.Tellez #UE4 Removing all local players from the game instance when it is shut down. This ensures that local players are properly torn down and events related to the lifespan of the player or controller are fired when exiting the game normally. #JIRA FORT-23024 Change 2947381 on 2016/04/18 by Rob.Cannaday Change XMPP presence, pubsub, messages, multi user chat, and chat's ref counting to be thread safe #jira FORT-22861 #tests front end partying Change 2945301 on 2016/04/15 by Michael.Trepka Reset SyncStatus in FAvfMediaVideoTrack::SeekToTime to fix issues with video not updating after rewind Change 2944422 on 2016/04/14 by Michael.Trepka Fixed Mono compile errors in UAT Change 2944375 on 2016/04/14 by Fred.Kimberley Changed how we handle missing gameplay tags so we now ensure once per missing tag instead of only ensuring on the first missing gameplay tag. Change 2944040 on 2016/04/14 by Michael.Trepka Fixed a problem with CoreAudio AudioUnitGraph update caused by adding and deleting the same node in a single tick Change2943864on 2016/04/14 by Lukasz.Furman fixed initialization order of gameplay debugger replicators on client #jira FORT-22885 Change 2943228 on 2016/04/13 by Bob.Tellez #UE4 Moved the addition of the IsDataOnly tag out of the if (ParentClass) block. Tags should not be dynamically added like this or else they can not be discovered by the editor which relies on asking the CDO for the tags relevant to an asset type. Change 2942303 on 2016/04/13 by Daniel.Broder Added support to be able to set a CanvasRenderTarget2D NOT to clear to green whenever it's updated (so you can just draw pixels that have changed instead of always having to redraw everything. #RB Bob.Tellez #UE4 Change 2941919 on 2016/04/13 by Jonathan.Lindquist Adding a new maxscript that allows artists to procedurally generate trees. Change 2941816 on 2016/04/13 by Saul.Abreu Demoted errors regarding widget-bound properties when first compling a new created widget blueprint - otherwise an ensure occurs. Change 2941752 on 2016/04/12 by jonathan.lindquist adding a new function to optimize trees and fix a few issues Change 2941519 on 2016/04/12 by Jonathan.Lindquist submitting a new warning regarding file unit types Change 2940980 on 2016/04/12 by John.Abercrombie Turned Graphs off by default in the Visual Logger Change 2940134 on 2016/04/11 by Billy.Bramer - Add support for new overrideable function OnPostDataImport to FTableRowBase; Can be override to perform custom parsing, fix-up, etc. per struct type whenever a data table is imported or reimported - Change row struct combo box on the data table importer to be sorted alphabetically Change 2938828 on 2016/04/08 by David.Hunt #FN || Economy Rebuild Updating several code references to items and item paths that no longer exist, with Bob's help. This fixes FORT-22784 (hopefully for real) and several other build and item errors. It also indicates that the various redirector issues I have been experiencing were likely red herrings - they were C++ defaults that were showing up on items that had nothing set, as opposed to redirects that failed. #CodeReview Bob.Tellez, Ben.Zeigler, William.Ewen, Carlos.Cuello Change 2938675 on 2016/04/08 by Lukasz.Furman fixed gameplay debugger displaying paths of killed pawns #fortnite Change 2938426 on 2016/04/08 by Rob.Cannaday Implement new command line party invitation format into Fortnite #jira FORT-22685 #tests launch with command line party invite Integrate CLs 2908339 and 2917498 from Orion Change 2938367 on 2016/04/08 by Billy.Bramer - Mark the reimport data table factory with UNREALED_API for external use - Change CSVImportFactory to respect the class of existing data being reimported upon Change 2937319 on 2016/04/07 by Lukasz.Furman improved gameplay task info in gameplay debugger tool Change 2937178 on 2016/04/07 by Lukasz.Furman fixed aborting undermine tasks when player becomes reachable #jira FORT-22240, FORT-22077 Change 2937166 on 2016/04/07 by Saul.Abreu Fixed redundant typename in TPair that was causing clang compilation errors. Change 2937093 on 2016/04/07 by Saul.Abreu #fortnite Made ElementSetType protected again in the Map family. Change 2937044 on 2016/04/07 by Saul.Abreu Tweaked Set/Map family of data structures to expose the typedefs for their key, value, and pair types. Change 2936940 on 2016/04/07 by Bob.Tellez #UE4 Fixed a bug that prevented the log summary from being printed after a blueprint compile. Change 2936696 on 2016/04/07 by Bob.Tellez #UE4 Blueprint names are once again part of Blueprint compile log messages. Change 2936572 on 2016/04/07 by Lukasz.Furman added more debug logs for tracking rare NaN error in player movement #jira FORT-19426 Change 2934892 on 2016/04/06 by Lukasz.Furman fixed updating hotspot information after all tasks instigated by it are finished #jira FORT-22515 Change 2933664 on 2016/04/05 by Michael.Trepka Fixed a rare crash in USoundNodeLooping::NotifyWaveInstanceFinished Change 2933554 on 2016/04/05 by Lukasz.Furman fixed taker's portal move (priorities of gameplay tasks spawned by path following) #jira FORT-22482 Change 2933343 on 2016/04/05 by John.Abercrombie Changed FGameplayAbilityActorInfo's AnimInstance property to a SkeletalMeshComponent in case AnimInstances are ever changed on a SkeletalMeshComponent - AnimInstance can be used through an accessor Change 2933300 on 2016/04/05 by Lukasz.Furman fixed number of spawned AI in FTests using PreSpawnDelay #fortnite Change 2933171 on 2016/04/05 by Lukasz.Furman added PreSpawnDelay param to function test spawn sets #fortnite Change 2931072 on 2016/04/01 by Lukasz.Furman changed pawn actions to gameplay tasks #jira FORT-21314 Change 2930987 on 2016/04/01 by Billy.Bramer - Add method to data table to get all rows as a type - Add metadata tag for data table rows to report columns as DataTableImportOptional, at which point they will not be warned against if missing during import (this allows games to do custom post-import fix-up or synthesis of data w/o expecting it to be imported) - Use new method for getting all tags to fix FORT-20563 "Gameplay tag table import checks by numerical row name for no reason" Change 2929651 on 2016/03/31 by Nick.Cooper #Fortnite - Fixed Actor AttachmentReplication not being cleared on detachment, which would cause issues with the actor's location for clients joining in progress #jira FORT-21330 #RB ben.zeigler Change 2929360 on 2016/03/31 by Daniel.Broder Fixed bug where CanvasRenderTarget2D assets would crash on load in editor due to trying to update the asset during post-load. Thanks to Bob for what I needed to check to early-out and avoid the crash. #RB Bob.Tellez #UE4 Change 2928845 on 2016/03/31 by Nicholas.Davies Add fix for chat text not clearing #jira FORT-22049 Textbox does not clear when text is sent through chat Change 2928574 on 2016/03/30 by Ben.Zeigler Fix issue with redirectors not working properly for blueprint function libraries. When a blueprint got regenerated it patched the old export, but failed to clear the "load failed" flag, so it would fail to find it when later pointed to by a redirect Change 2928572 on 2016/03/30 by Ben.Zeigler #Jira FORT-20763 Fix issue with "Server re-loading object" warning going off for deleted actors. It now only logs, and only for things that are going to successfully load Change 2928436 on 2016/03/30 by Bob.Tellez #UE4 Added Canvas Render Target factory and asset type actions so you can create them in the content browser and search for them after they are created. Change 2928372 on 2016/03/30 by Bob.Tellez #UE4 Added verbose message about animation assets that need to be resaved due to resetting the skeleton. Change 2926805 on 2016/03/29 by Bob.Tellez #UE4 Made SetOverallScalabilityLevel virtual so game-specific features can be updated based on a single-value level. Change 2926752 on 2016/03/29 by Bob.Tellez #UE4 Using DesiredScreenHeight is now optional. Often games use ResolutionQuality as purely a way to run better on slower machines so it should be controlled entirely by scalability. Change 2926189 on 2016/03/29 by Rob.Cannaday Change storing HTTP requests as raw pointers to weak pointers with validity being checked via Pinning it #jira FORT-18947 #jira OR-17695 #tests golden path Change 2924921 on 2016/03/28 by Lukasz.Furman removed log message showing as navmesh generation error when it skips over degenerated poly #fortnite Change 2924843 on 2016/03/28 by Lukasz.Furman added more debug logs for navmesh's failed triangulate() #jira FORT-22186 Change 2924719 on 2016/03/28 by Lukasz.Furman fixed offmesh link connection issue causing path portal edges to have duplicated data and breaking hotspot detection traces #jira FORT-22132 Change 2921698 on 2016/03/24 by Lukasz.Furman fixed EQS instancing queries by debug name instead of using unique one, fixed debug name on asset duplication #fortnite Change 2920395 on 2016/03/23 by Bob.Tellez #UE4 Added a call to FBaseServiceMcp::Shutdown() in FOnlineServiceAvailabilityMcp::Shutdown. The parent class doesnt do anything today, but this may fix a bug in the future. Change 2920343 on 2016/03/23 by Ben.Zeigler In ConvertScalarUPropertyToJsonValue, move the execution of the custom callback up above the specific property types. This is needed to allow us to override the TextProperty export, and allows overriding in general. It can have a performance implication if the custom callback is very slow #RB josh.markiewicz Change 2920310 on 2016/03/23 by Bob.Tellez #UE4 FOnlineServiceAvailabilityMcp::Init was not invoking the Superclass' Init Change 2920254 on 2016/03/23 by Aaron.McLeran FORT-22090 Re-disabling reverb. Will add an ini-based disabling ability but this CL quickly re-disables to resolve volume issue on FN and (hopefully) bypass crash mentioned in FORT-22037 Change 2920249 on 2016/03/23 by Rob.Cannaday Fix for crash in FOnlinePartySystemMcp::InternalCleanUpPartyMember Don't trigger "member left" type events if we are leaving the party #jira FORT-20422 #jira FORT-21726 Change 2920178 on 2016/03/23 by Bob.Tellez #UE4 Calling the platform-specific implementation of StackWalkAndDump when invoking StackWalkAndDumpEx. This fixes a bug in Windows where the first ensure does not produce a callstack. Change 2919858 on 2016/03/23 by Bob.Tellez #UE4 Fix for ensure about accessing a CVar in UParticleModuleLight on a non-game thread using GetValueOnGameThread. I changed this to GetValueOnAnyThread. Change 2919775 on 2016/03/23 by Bob.Tellez #UE4 Restoring enforced uniqueness in FUObjectAnnotationSparseSearchable and put all manipulations of InverseAnnotationMap in critical sections. This will make RemoveAnnotation fast again. Change 2919233 on 2016/03/22 by Bob.Tellez #UE4 Removing a warning that is pretty chatty in our cooked logs. Change 2919125 on 2016/03/22 by Bob.Tellez #UE4 Added ParticleLightQuality scalability setting since lower-end machines have trouble with particle lights. They are disabled on low and medium spec machines. HQ lights are only allowed on high-end machines. Change 2918831 on 2016/03/22 by Bob.Tellez #UE4 Fixed a bug where WinInet response headers were not properly being trimmed. #JIRA FORT-22054 Change 2917722 on 2016/03/21 by Ben.Zeigler Remove FortniteServer module and move those classes to FortniteGame. The engine doesn't support classes that only exist on servers but not clients, so this fixes a lot of error spam bugs, and should improve compile times Resave assets that directly referenced FortniteServer Change 2917588 on 2016/03/21 by Bob.Tellez #UE4 Fixed shadow variable that I introduced Change 2914169 on 2016/03/17 by Ben.Zeigler Disable extra logging that was added to track down Auth issues, they look to be resolved Change 2912626 on 2016/03/16 by Bob.Tellez #UE4 Success messages should not be warnings. Change 2911171 on 2016/03/15 by Bob.Tellez #UE4 Minor fix to correctly display GetBulkDataSize in the warning in FUntypedBulkData::WaitForAsyncLoading Change 2911170 on 2016/03/15 by Billy.Bramer #jira [FORT-6139] Trap models persist after destroying supporting structure in Outpost - Root issue was caused by error within network dormancy and queued bunches: If a dormant actor's open bunch ended up queued and a close bunch came in before the bunch was processed, the actor would never be properly destroyed client side as a result of not re-establishing the channel's actor pointer - Fix issue by changing close bunches to not be fully processed until their appropriate place in the queue. While this could cause superfluous execution (i.e. actor recreated just to be immediately destroyed), it should respect gameplay programming intent in regards to RPCs Change 2911009 on 2016/03/15 by Bob.Tellez #UE4 Fixed a bug in UHierarchicalInstancedStaticMeshComponent where RemoveInstances would not rebuild the ClusterTree, causing SortedInstances to contain incorect indices in GetInstancesOverlappingBox. This is the behavior of the singular RemoveInstance so this is what should also be done in the plural RemoveInstances. #JIRA FORT-21605 Change 2910295 on 2016/03/15 by Bob.Tellez #UE4 World thumbnails no longer cull primitives. This is because the camera is very far away and if terrain pieces are culled, the level is not visible. Change 2909324 on 2016/03/14 by Bob.Tellez #UE4 Since empty headers values cause GenerateHeaderBuffer to emit ERROR_HTTP_HEADER_NOT_FOUND, they are now omitted from the header buffer in WinInet. Change 2905920 on 2016/03/11 by Lukasz.Furman fixed crowd simulation getting stuck with invalid velocity (moonwalking husks) #fortnite Change 2905612 on 2016/03/11 by Bob.Tellez #UE4 Made the minimum quadtree size configurable in ProceduralFoliageSpawner. You need to reduce the minimum size a little if you are spawning very many small foliage meshes. [CL 3027184 by Bob Tellez in Main branch]
1980 lines
84 KiB
C#
1980 lines
84 KiB
C#
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml;
|
|
using Tools.DotNETCommon.CaselessDictionary;
|
|
|
|
namespace UnrealBuildTool
|
|
{
|
|
/// <summary>
|
|
/// Distribution level of module.
|
|
/// Note: The name of each entry is used to search for/create folders
|
|
/// </summary>
|
|
public enum UEBuildModuleDistribution
|
|
{
|
|
/// Binaries can be distributed to everyone
|
|
Public,
|
|
|
|
/// Can be used by UE4 but not required
|
|
CarefullyRedist,
|
|
|
|
/// Epic Employees and Contractors
|
|
NotForLicensees,
|
|
|
|
/// Epic Employees only
|
|
NoRedist,
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// A unit of code compilation and linking.
|
|
/// </summary>
|
|
public abstract class UEBuildModule
|
|
{
|
|
/// <summary>
|
|
/// Checks what distribution level a particular path should have by checking for key folders anywhere in it
|
|
/// </summary>
|
|
public static UEBuildModuleDistribution GetModuleDistributionLevelBasedOnLocation(string FilePath)
|
|
{
|
|
// Get full path to ensure all folder separators are the same
|
|
FilePath = Path.GetFullPath(FilePath);
|
|
|
|
// Check from highest to lowest (don't actually need to check 'Everyone')
|
|
for (UEBuildModuleDistribution DistributionLevel = UEBuildModuleDistribution.NoRedist; DistributionLevel > UEBuildModuleDistribution.Public; DistributionLevel--)
|
|
{
|
|
string DistributionFolderName = String.Format("{0}{1}{0}", Path.DirectorySeparatorChar, DistributionLevel.ToString());
|
|
if (FilePath.IndexOf(DistributionFolderName, StringComparison.InvariantCultureIgnoreCase) >= 0)
|
|
{
|
|
return DistributionLevel;
|
|
}
|
|
|
|
if (DistributionLevel == UEBuildModuleDistribution.NotForLicensees)
|
|
{
|
|
// Extra checks for PS4 and XboxOne folders, which are equivalent to NotForLicensees
|
|
string PS4FolderName = String.Format("{0}ps4{0}", Path.DirectorySeparatorChar);
|
|
string XboxFolderName = String.Format("{0}xboxone{0}", Path.DirectorySeparatorChar);
|
|
if (FilePath.IndexOf(PS4FolderName, StringComparison.InvariantCultureIgnoreCase) >= 0
|
|
|| FilePath.IndexOf(XboxFolderName, StringComparison.InvariantCultureIgnoreCase) >= 0)
|
|
{
|
|
return UEBuildModuleDistribution.NotForLicensees;
|
|
}
|
|
}
|
|
}
|
|
|
|
return UEBuildModuleDistribution.Public;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines the distribution level of a module based on its directory and includes.
|
|
/// </summary>
|
|
public UEBuildModuleDistribution DetermineDistributionLevel()
|
|
{
|
|
List<string> PathsToCheck = new List<string>();
|
|
PathsToCheck.Add(ModuleDirectory.FullName);
|
|
PathsToCheck.AddRange(PublicIncludePaths);
|
|
PathsToCheck.AddRange(PrivateIncludePaths);
|
|
// Not sure if these two are necessary as paths will usually be in basic includes too
|
|
PathsToCheck.AddRange(PublicSystemIncludePaths);
|
|
PathsToCheck.AddRange(PublicLibraryPaths);
|
|
|
|
UEBuildModuleDistribution DistributionLevel = UEBuildModuleDistribution.Public;
|
|
|
|
if (!Rules.bOutputPubliclyDistributable)
|
|
{
|
|
// Keep checking as long as we haven't reached the maximum level
|
|
for (int PathIndex = 0; PathIndex < PathsToCheck.Count && DistributionLevel != UEBuildModuleDistribution.NoRedist; ++PathIndex)
|
|
{
|
|
DistributionLevel = Utils.Max(DistributionLevel, UEBuildModule.GetModuleDistributionLevelBasedOnLocation(PathsToCheck[PathIndex]));
|
|
}
|
|
}
|
|
|
|
return DistributionLevel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts an optional string list parameter to a well-defined hash set.
|
|
/// </summary>
|
|
protected static HashSet<string> HashSetFromOptionalEnumerableStringParameter(IEnumerable<string> InEnumerableStrings)
|
|
{
|
|
return InEnumerableStrings == null ? new HashSet<string>() : new HashSet<string>(InEnumerableStrings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The name that uniquely identifies the module.
|
|
/// </summary>
|
|
public readonly string Name;
|
|
|
|
/// <summary>
|
|
/// The type of module being built. Used to switch between debug/development and precompiled/source configurations.
|
|
/// </summary>
|
|
public UHTModuleType Type;
|
|
|
|
/// <summary>
|
|
/// The rules for this module
|
|
/// </summary>
|
|
public ModuleRules Rules;
|
|
|
|
/// <summary>
|
|
/// Path to the module directory
|
|
/// </summary>
|
|
public readonly DirectoryReference ModuleDirectory;
|
|
|
|
/// <summary>
|
|
/// Is this module allowed to be redistributed.
|
|
/// </summary>
|
|
private readonly bool? IsRedistributableOverride;
|
|
|
|
/// <summary>
|
|
/// The name of the .Build.cs file this module was created from, if any
|
|
/// </summary>
|
|
public FileReference RulesFile;
|
|
|
|
/// <summary>
|
|
/// The binary the module will be linked into for the current target. Only set after UEBuildBinary.BindModules is called.
|
|
/// </summary>
|
|
public UEBuildBinary Binary = null;
|
|
|
|
/// <summary>
|
|
/// Include path for this module's base directory, relative to the Engine/Source directory
|
|
/// </summary>
|
|
protected string NormalizedModuleIncludePath;
|
|
|
|
/// <summary>
|
|
/// The name of the _API define for this module
|
|
/// </summary>
|
|
protected readonly string ModuleApiDefine;
|
|
|
|
protected readonly HashSet<string> PublicDefinitions;
|
|
protected readonly HashSet<string> PublicIncludePaths;
|
|
protected readonly HashSet<string> PrivateIncludePaths;
|
|
protected readonly HashSet<string> PublicSystemIncludePaths;
|
|
protected readonly HashSet<string> PublicLibraryPaths;
|
|
protected readonly HashSet<string> PublicAdditionalLibraries;
|
|
protected readonly HashSet<string> PublicFrameworks;
|
|
protected readonly HashSet<string> PublicWeakFrameworks;
|
|
protected readonly HashSet<UEBuildFramework> PublicAdditionalFrameworks;
|
|
protected readonly HashSet<string> PublicAdditionalShadowFiles;
|
|
protected readonly HashSet<UEBuildBundleResource> PublicAdditionalBundleResources;
|
|
|
|
/// <summary>
|
|
/// Names of modules with header files that this module's public interface needs access to.
|
|
/// </summary>
|
|
protected List<UEBuildModule> PublicIncludePathModules;
|
|
|
|
/// <summary>
|
|
/// Names of modules that this module's public interface depends on.
|
|
/// </summary>
|
|
protected List<UEBuildModule> PublicDependencyModules;
|
|
|
|
/// <summary>
|
|
/// Names of DLLs that this module should delay load
|
|
/// </summary>
|
|
protected HashSet<string> PublicDelayLoadDLLs;
|
|
|
|
/// <summary>
|
|
/// Names of modules with header files that this module's private implementation needs access to.
|
|
/// </summary>
|
|
protected List<UEBuildModule> PrivateIncludePathModules;
|
|
|
|
/// <summary>
|
|
/// Names of modules that this module's private implementation depends on.
|
|
/// </summary>
|
|
protected List<UEBuildModule> PrivateDependencyModules;
|
|
|
|
/// <summary>
|
|
/// Extra modules this module may require at run time
|
|
/// </summary>
|
|
protected List<UEBuildModule> DynamicallyLoadedModules;
|
|
|
|
/// <summary>
|
|
/// Extra modules this module may require at run time, that are on behalf of another platform (i.e. shader formats and the like)
|
|
/// </summary>
|
|
protected List<UEBuildModule> PlatformSpecificDynamicallyLoadedModules;
|
|
|
|
/// <summary>
|
|
/// Files which this module depends on at runtime.
|
|
/// </summary>
|
|
public RuntimeDependencyList RuntimeDependencies;
|
|
|
|
/// <summary>
|
|
/// Returns a list of this module's immediate dependencies.
|
|
/// </summary>
|
|
/// <returns>An enumerable containing the dependencies of the module.</returns>
|
|
public IEnumerable<UEBuildModule> GetDirectDependencyModules()
|
|
{
|
|
return PublicDependencyModules.Concat(PrivateDependencyModules).Concat(DynamicallyLoadedModules).Concat(PlatformSpecificDynamicallyLoadedModules);
|
|
}
|
|
|
|
public UEBuildModule(
|
|
string InName,
|
|
UHTModuleType InType,
|
|
DirectoryReference InModuleDirectory,
|
|
ModuleRules InRules,
|
|
FileReference InRulesFile
|
|
)
|
|
{
|
|
Name = InName;
|
|
Type = InType;
|
|
ModuleDirectory = InModuleDirectory;
|
|
Rules = InRules;
|
|
RulesFile = InRulesFile;
|
|
|
|
NormalizedModuleIncludePath = Utils.CleanDirectorySeparators(ModuleDirectory.MakeRelativeTo(UnrealBuildTool.EngineSourceDirectory), '/');
|
|
ModuleApiDefine = Name.ToUpperInvariant() + "_API";
|
|
|
|
PublicDefinitions = HashSetFromOptionalEnumerableStringParameter(InRules.Definitions);
|
|
PublicIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicIncludePaths);
|
|
PublicSystemIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicSystemIncludePaths);
|
|
PublicLibraryPaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicLibraryPaths);
|
|
PublicAdditionalLibraries = HashSetFromOptionalEnumerableStringParameter(InRules.PublicAdditionalLibraries);
|
|
PublicFrameworks = HashSetFromOptionalEnumerableStringParameter(InRules.PublicFrameworks);
|
|
PublicWeakFrameworks = HashSetFromOptionalEnumerableStringParameter(InRules.PublicWeakFrameworks);
|
|
PublicAdditionalFrameworks = InRules.PublicAdditionalFrameworks == null ? new HashSet<UEBuildFramework>() : new HashSet<UEBuildFramework>(InRules.PublicAdditionalFrameworks);
|
|
PublicAdditionalShadowFiles = HashSetFromOptionalEnumerableStringParameter(InRules.PublicAdditionalShadowFiles);
|
|
PublicAdditionalBundleResources = InRules.AdditionalBundleResources == null ? new HashSet<UEBuildBundleResource>() : new HashSet<UEBuildBundleResource>(InRules.AdditionalBundleResources);
|
|
PublicDelayLoadDLLs = HashSetFromOptionalEnumerableStringParameter(InRules.PublicDelayLoadDLLs);
|
|
PrivateIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PrivateIncludePaths);
|
|
RuntimeDependencies = (InRules.RuntimeDependencies == null) ? new RuntimeDependencyList() : new RuntimeDependencyList(InRules.RuntimeDependencies);
|
|
IsRedistributableOverride = InRules.IsRedistributableOverride;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether this module has a circular dependency on the given module
|
|
/// </summary>
|
|
public bool HasCircularDependencyOn(string ModuleName)
|
|
{
|
|
return Rules.CircularlyReferencedDependentModules.Contains(ModuleName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all the modules which affect the public compile environment. Searches through
|
|
/// </summary>
|
|
/// <param name="Modules"></param>
|
|
/// <param name="bIncludePathsOnly"></param>
|
|
/// <param name="DependencyModules"></param>
|
|
protected void FindModulesInPublicCompileEnvironment(List<UEBuildModule> Modules, Dictionary<UEBuildModule, bool> ModuleToIncludePathsOnlyFlag)
|
|
{
|
|
//
|
|
bool bModuleIncludePathsOnly;
|
|
if (!ModuleToIncludePathsOnlyFlag.TryGetValue(this, out bModuleIncludePathsOnly))
|
|
{
|
|
Modules.Add(this);
|
|
}
|
|
else if (!bModuleIncludePathsOnly)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ModuleToIncludePathsOnlyFlag[this] = false;
|
|
|
|
foreach (UEBuildModule DependencyModule in PublicDependencyModules)
|
|
{
|
|
DependencyModule.FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
|
|
}
|
|
|
|
// Now add an include paths from modules with header files that we need access to, but won't necessarily be importing
|
|
foreach (UEBuildModule IncludePathModule in PublicIncludePathModules)
|
|
{
|
|
IncludePathModule.FindIncludePathModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all the modules which affect the public compile environment. Searches through
|
|
/// </summary>
|
|
/// <param name="Modules"></param>
|
|
/// <param name="bIncludePathsOnly"></param>
|
|
/// <param name="DependencyModules"></param>
|
|
protected void FindIncludePathModulesInPublicCompileEnvironment(List<UEBuildModule> Modules, Dictionary<UEBuildModule, bool> ModuleToIncludePathsOnlyFlag)
|
|
{
|
|
if (!ModuleToIncludePathsOnlyFlag.ContainsKey(this))
|
|
{
|
|
// Add this module to the list
|
|
Modules.Add(this);
|
|
ModuleToIncludePathsOnlyFlag.Add(this, true);
|
|
|
|
// Include any of its public include path modules in the compile environment too
|
|
foreach (UEBuildModule IncludePathModule in PublicIncludePathModules)
|
|
{
|
|
IncludePathModule.FindIncludePathModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets up the environment for compiling any module that includes the public interface of this module.
|
|
/// </summary>
|
|
public void AddModuleToCompileEnvironment(
|
|
UEBuildBinary SourceBinary,
|
|
bool bIncludePathsOnly,
|
|
HashSet<string> IncludePaths,
|
|
HashSet<string> SystemIncludePaths,
|
|
List<string> Definitions,
|
|
List<UEBuildFramework> AdditionalFrameworks
|
|
)
|
|
{
|
|
// Add this module's public include paths and definitions.
|
|
AddIncludePathsWithChecks(IncludePaths, PublicIncludePaths);
|
|
AddIncludePathsWithChecks(SystemIncludePaths, PublicSystemIncludePaths);
|
|
Definitions.AddRange(PublicDefinitions);
|
|
|
|
// If this module is being built into a DLL or EXE, set up an IMPORTS or EXPORTS definition for it.
|
|
if (Binary == null)
|
|
{
|
|
// If we're referencing include paths for a module that's not being built, we don't actually need to import anything from it, but we need to avoid barfing when
|
|
// the compiler encounters an _API define. We also want to avoid changing the compile environment in cases where the module happens to be compiled because it's a dependency
|
|
// of something else, which cause a fall-through to the code below and set up an empty _API define.
|
|
if (bIncludePathsOnly)
|
|
{
|
|
Log.TraceVerbose("{0}: Include paths only for {1} (no binary)", SourceBinary.Config.OutputFilePaths[0].GetFileNameWithoutExtension(), Name);
|
|
Definitions.Add(ModuleApiDefine + "=");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FileReference BinaryPath = Binary.Config.OutputFilePaths[0];
|
|
FileReference SourceBinaryPath = SourceBinary.Config.OutputFilePaths[0];
|
|
|
|
if (ProjectFileGenerator.bGenerateProjectFiles || (Binary.Config.Type == UEBuildBinaryType.StaticLibrary))
|
|
{
|
|
// When generating IntelliSense files, never add dllimport/dllexport specifiers as it
|
|
// simply confuses the compiler
|
|
Definitions.Add(ModuleApiDefine + "=");
|
|
}
|
|
else if (Binary == SourceBinary)
|
|
{
|
|
if (Binary.Config.bAllowExports)
|
|
{
|
|
Log.TraceVerbose("{0}: Exporting {1} from {2}", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
|
|
Definitions.Add(ModuleApiDefine + "=DLLEXPORT");
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("{0}: Not importing/exporting {1} (binary: {2})", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
|
|
Definitions.Add(ModuleApiDefine + "=");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// @todo SharedPCH: Public headers included from modules that are not importing the module of that public header, seems invalid.
|
|
// Those public headers have no business having APIs in them. OnlineSubsystem has some public headers like this. Without changing
|
|
// this, we need to suppress warnings at compile time.
|
|
if (bIncludePathsOnly)
|
|
{
|
|
Log.TraceVerbose("{0}: Include paths only for {1} (binary: {2})", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
|
|
Definitions.Add(ModuleApiDefine + "=");
|
|
}
|
|
else if (Binary.Config.bAllowExports)
|
|
{
|
|
Log.TraceVerbose("{0}: Importing {1} from {2}", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
|
|
Definitions.Add(ModuleApiDefine + "=DLLIMPORT");
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("{0}: Not importing/exporting {1} (binary: {2})", SourceBinaryPath.GetFileNameWithoutExtension(), Name, BinaryPath.GetFileNameWithoutExtension());
|
|
Definitions.Add(ModuleApiDefine + "=");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add the module's directory to the include path, so we can root #includes to it
|
|
IncludePaths.Add(NormalizedModuleIncludePath);
|
|
|
|
// Add the additional frameworks so that the compiler can know about their #include paths
|
|
AdditionalFrameworks.AddRange(PublicAdditionalFrameworks);
|
|
|
|
// Remember the module so we can refer to it when needed
|
|
foreach (UEBuildFramework Framework in PublicAdditionalFrameworks)
|
|
{
|
|
Framework.OwningModule = this;
|
|
}
|
|
}
|
|
|
|
static Regex VCMacroRegex = new Regex(@"\$\([A-Za-z0-9_]+\)");
|
|
|
|
/// <summary>
|
|
/// Checks if path contains a VC macro
|
|
/// </summary>
|
|
protected bool DoesPathContainVCMacro(string Path)
|
|
{
|
|
return VCMacroRegex.IsMatch(Path);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds PathsToAdd to IncludePaths, performing path normalization and ignoring duplicates.
|
|
/// </summary>
|
|
protected void AddIncludePathsWithChecks(HashSet<string> IncludePaths, HashSet<string> PathsToAdd)
|
|
{
|
|
if (ProjectFileGenerator.bGenerateProjectFiles)
|
|
{
|
|
// Extra checks are switched off for IntelliSense generation as they provide
|
|
// no additional value and cause performance impact.
|
|
IncludePaths.UnionWith(PathsToAdd);
|
|
}
|
|
else
|
|
{
|
|
foreach (string Path in PathsToAdd)
|
|
{
|
|
string NormalizedPath = Path.TrimEnd('/');
|
|
// If path doesn't exist, it may contain VC macro (which is passed directly to and expanded by compiler).
|
|
if (Directory.Exists(NormalizedPath) || DoesPathContainVCMacro(NormalizedPath))
|
|
{
|
|
IncludePaths.Add(NormalizedPath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets up the environment for compiling this module.
|
|
/// </summary>
|
|
protected virtual void SetupPrivateCompileEnvironment(
|
|
HashSet<string> IncludePaths,
|
|
HashSet<string> SystemIncludePaths,
|
|
List<string> Definitions,
|
|
List<UEBuildFramework> AdditionalFrameworks
|
|
)
|
|
{
|
|
HashSet<UEBuildModule> VisitedModules = new HashSet<UEBuildModule>();
|
|
|
|
if (this.Type.IsGameModule())
|
|
{
|
|
Definitions.Add("DEPRECATED_FORGAME=DEPRECATED");
|
|
}
|
|
|
|
// Add this module's private include paths and definitions.
|
|
AddIncludePathsWithChecks(IncludePaths, PrivateIncludePaths);
|
|
|
|
// Find all the modules that are part of the public compile environment for this module.
|
|
List<UEBuildModule> Modules = new List<UEBuildModule>();
|
|
Dictionary<UEBuildModule, bool> ModuleToIncludePathsOnlyFlag = new Dictionary<UEBuildModule, bool>();
|
|
FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
|
|
|
|
// Add in all the modules that are private dependencies
|
|
foreach (UEBuildModule DependencyModule in PrivateDependencyModules)
|
|
{
|
|
DependencyModule.FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
|
|
}
|
|
|
|
// And finally add in all the modules that are include path only dependencies
|
|
foreach (UEBuildModule IncludePathModule in PrivateIncludePathModules)
|
|
{
|
|
IncludePathModule.FindIncludePathModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
|
|
}
|
|
|
|
// Now set up the compile environment for the modules in the original order that we encountered them
|
|
foreach (UEBuildModule Module in Modules)
|
|
{
|
|
Module.AddModuleToCompileEnvironment(Binary, ModuleToIncludePathsOnlyFlag[Module], IncludePaths, SystemIncludePaths, Definitions, AdditionalFrameworks);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets up the environment for linking any module that includes the public interface of this module.
|
|
/// </summary>
|
|
protected virtual void SetupPublicLinkEnvironment(
|
|
UEBuildBinary SourceBinary,
|
|
List<string> LibraryPaths,
|
|
List<string> AdditionalLibraries,
|
|
List<string> Frameworks,
|
|
List<string> WeakFrameworks,
|
|
List<UEBuildFramework> AdditionalFrameworks,
|
|
List<string> AdditionalShadowFiles,
|
|
List<UEBuildBundleResource> AdditionalBundleResources,
|
|
List<string> DelayLoadDLLs,
|
|
List<UEBuildBinary> BinaryDependencies,
|
|
HashSet<UEBuildModule> VisitedModules
|
|
)
|
|
{
|
|
// There may be circular dependencies in compile dependencies, so we need to avoid reentrance.
|
|
if (VisitedModules.Add(this))
|
|
{
|
|
// Add this module's binary to the binary dependencies.
|
|
if (Binary != null
|
|
&& Binary != SourceBinary
|
|
&& !BinaryDependencies.Contains(Binary))
|
|
{
|
|
BinaryDependencies.Add(Binary);
|
|
}
|
|
|
|
// If this module belongs to a static library that we are not currently building, recursively add the link environment settings for all of its dependencies too.
|
|
// Keep doing this until we reach a module that is not part of a static library (or external module, since they have no associated binary).
|
|
// Static libraries do not contain the symbols for their dependencies, so we need to recursively gather them to be linked into other binary types.
|
|
bool bIsBuildingAStaticLibrary = (SourceBinary != null && SourceBinary.Config.Type == UEBuildBinaryType.StaticLibrary);
|
|
bool bIsModuleBinaryAStaticLibrary = (Binary != null && Binary.Config.Type == UEBuildBinaryType.StaticLibrary);
|
|
if (!bIsBuildingAStaticLibrary && bIsModuleBinaryAStaticLibrary)
|
|
{
|
|
// Gather all dependencies and recursively call SetupPublicLinkEnvironmnet
|
|
List<UEBuildModule> AllDependencyModules = new List<UEBuildModule>();
|
|
AllDependencyModules.AddRange(PrivateDependencyModules);
|
|
AllDependencyModules.AddRange(PublicDependencyModules);
|
|
|
|
foreach (UEBuildModule DependencyModule in AllDependencyModules)
|
|
{
|
|
bool bIsExternalModule = (DependencyModule as UEBuildExternalModule != null);
|
|
bool bIsInStaticLibrary = (DependencyModule.Binary != null && DependencyModule.Binary.Config.Type == UEBuildBinaryType.StaticLibrary);
|
|
if (bIsExternalModule || bIsInStaticLibrary)
|
|
{
|
|
DependencyModule.SetupPublicLinkEnvironment(SourceBinary, LibraryPaths, AdditionalLibraries, Frameworks, WeakFrameworks,
|
|
AdditionalFrameworks, AdditionalShadowFiles, AdditionalBundleResources, DelayLoadDLLs, BinaryDependencies, VisitedModules);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add this module's public include library paths and additional libraries.
|
|
LibraryPaths.AddRange(PublicLibraryPaths);
|
|
AdditionalLibraries.AddRange(PublicAdditionalLibraries);
|
|
Frameworks.AddRange(PublicFrameworks);
|
|
WeakFrameworks.AddRange(PublicWeakFrameworks);
|
|
AdditionalBundleResources.AddRange(PublicAdditionalBundleResources);
|
|
// Remember the module so we can refer to it when needed
|
|
foreach (UEBuildFramework Framework in PublicAdditionalFrameworks)
|
|
{
|
|
Framework.OwningModule = this;
|
|
}
|
|
AdditionalFrameworks.AddRange(PublicAdditionalFrameworks);
|
|
AdditionalShadowFiles.AddRange(PublicAdditionalShadowFiles);
|
|
DelayLoadDLLs.AddRange(PublicDelayLoadDLLs);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets up the environment for linking this module.
|
|
/// </summary>
|
|
public virtual void SetupPrivateLinkEnvironment(
|
|
UEBuildBinary SourceBinary,
|
|
LinkEnvironment LinkEnvironment,
|
|
List<UEBuildBinary> BinaryDependencies,
|
|
HashSet<UEBuildModule> VisitedModules
|
|
)
|
|
{
|
|
// Allow the module's public dependencies to add library paths and additional libraries to the link environment.
|
|
SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.Config.LibraryPaths, LinkEnvironment.Config.AdditionalLibraries, LinkEnvironment.Config.Frameworks, LinkEnvironment.Config.WeakFrameworks,
|
|
LinkEnvironment.Config.AdditionalFrameworks, LinkEnvironment.Config.AdditionalShadowFiles, LinkEnvironment.Config.AdditionalBundleResources, LinkEnvironment.Config.DelayLoadDLLs, BinaryDependencies, VisitedModules);
|
|
|
|
// Also allow the module's public and private dependencies to modify the link environment.
|
|
List<UEBuildModule> AllDependencyModules = new List<UEBuildModule>();
|
|
AllDependencyModules.AddRange(PrivateDependencyModules);
|
|
AllDependencyModules.AddRange(PublicDependencyModules);
|
|
|
|
foreach (UEBuildModule DependencyModule in AllDependencyModules)
|
|
{
|
|
DependencyModule.SetupPublicLinkEnvironment(SourceBinary, LinkEnvironment.Config.LibraryPaths, LinkEnvironment.Config.AdditionalLibraries, LinkEnvironment.Config.Frameworks, LinkEnvironment.Config.WeakFrameworks,
|
|
LinkEnvironment.Config.AdditionalFrameworks, LinkEnvironment.Config.AdditionalShadowFiles, LinkEnvironment.Config.AdditionalBundleResources, LinkEnvironment.Config.DelayLoadDLLs, BinaryDependencies, VisitedModules);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compiles the module, and returns a list of files output by the compiler.
|
|
/// </summary>
|
|
public abstract List<FileItem> Compile(UEBuildTarget Target, UEToolChain ToolChain, CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment);
|
|
|
|
// Object interface.
|
|
public override string ToString()
|
|
{
|
|
return Name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds the modules referenced by this module which have not yet been bound to a binary
|
|
/// </summary>
|
|
/// <returns>List of unbound modules</returns>
|
|
public List<UEBuildModule> GetUnboundReferences()
|
|
{
|
|
List<UEBuildModule> Modules = new List<UEBuildModule>();
|
|
Modules.AddRange(PrivateDependencyModules.Where(x => x.Binary == null));
|
|
Modules.AddRange(PublicDependencyModules.Where(x => x.Binary == null));
|
|
return Modules;
|
|
}
|
|
|
|
[DebuggerDisplay("{Index}: {Module}")]
|
|
public class ModuleIndexPair
|
|
{
|
|
public UEBuildModule Module;
|
|
public int Index;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets all of the modules referenced by this module
|
|
/// </summary>
|
|
/// <param name="ReferencedModules">Hash of all referenced modules with their addition index.</param>
|
|
/// <param name="IgnoreReferencedModules">Hashset used to ignore modules which are already added to the list</param>
|
|
/// <param name="bIncludeDynamicallyLoaded">True if dynamically loaded modules (and all of their dependent modules) should be included.</param>
|
|
/// <param name="bForceCircular">True if circular dependencies should be processed</param>
|
|
/// <param name="bOnlyDirectDependencies">True to return only this module's direct dependencies</param>
|
|
public virtual void GetAllDependencyModules(List<UEBuildModule> ReferencedModules, HashSet<UEBuildModule> IgnoreReferencedModules, bool bIncludeDynamicallyLoaded, bool bForceCircular, bool bOnlyDirectDependencies)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets all of the modules precompiled along with this module
|
|
/// </summary>
|
|
/// <param name="Modules">Set of all the precompiled modules</param>
|
|
public virtual void RecursivelyAddPrecompiledModules(List<UEBuildModule> Modules)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates all the modules required for this target
|
|
/// </summary>
|
|
public void RecursivelyCreateModules(UEBuildTarget Target)
|
|
{
|
|
// Create all the include path modules. These modules may not be added to the target (and we don't process their dependencies), but they need
|
|
// to be created to set up their compile environment.
|
|
RecursivelyCreateIncludePathModulesByName(Target, Rules.PublicIncludePathModuleNames, ref PublicIncludePathModules);
|
|
RecursivelyCreateIncludePathModulesByName(Target, Rules.PrivateIncludePathModuleNames, ref PrivateIncludePathModules);
|
|
|
|
// Create all the dependency modules
|
|
RecursivelyCreateModulesByName(Target, Rules.PublicDependencyModuleNames, ref PublicDependencyModules);
|
|
RecursivelyCreateModulesByName(Target, Rules.PrivateDependencyModuleNames, ref PrivateDependencyModules);
|
|
RecursivelyCreateModulesByName(Target, Rules.DynamicallyLoadedModuleNames, ref DynamicallyLoadedModules);
|
|
RecursivelyCreateModulesByName(Target, Rules.PlatformSpecificDynamicallyLoadedModuleNames, ref PlatformSpecificDynamicallyLoadedModules);
|
|
}
|
|
|
|
private static void RecursivelyCreateModulesByName(UEBuildTarget Target, List<string> ModuleNames, ref List<UEBuildModule> Modules)
|
|
{
|
|
// Check whether the module list is already set. We set this immediately (via the ref) to avoid infinite recursion.
|
|
if (Modules == null)
|
|
{
|
|
Modules = new List<UEBuildModule>();
|
|
foreach (string ModuleName in ModuleNames)
|
|
{
|
|
UEBuildModule Module = Target.FindOrCreateModuleByName(ModuleName);
|
|
if (!Modules.Contains(Module))
|
|
{
|
|
Module.RecursivelyCreateModules(Target);
|
|
Modules.Add(Module);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void RecursivelyCreateIncludePathModulesByName(UEBuildTarget Target, List<string> ModuleNames, ref List<UEBuildModule> Modules)
|
|
{
|
|
// Check whether the module list is already set. We set this immediately (via the ref) to avoid infinite recursion.
|
|
if (Modules == null)
|
|
{
|
|
Modules = new List<UEBuildModule>();
|
|
foreach (string ModuleName in ModuleNames)
|
|
{
|
|
UEBuildModule Module = Target.FindOrCreateModuleByName(ModuleName);
|
|
RecursivelyCreateIncludePathModulesByName(Target, Module.Rules.PublicIncludePathModuleNames, ref Module.PublicIncludePathModules);
|
|
Modules.Add(Module);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// A module that is never compiled by us, and is only used to group include paths and libraries into a dependency unit.
|
|
/// </summary>
|
|
class UEBuildExternalModule : UEBuildModule
|
|
{
|
|
public UEBuildExternalModule(
|
|
UHTModuleType InType,
|
|
string InName,
|
|
DirectoryReference InModuleDirectory,
|
|
ModuleRules InRules,
|
|
FileReference InRulesFile
|
|
)
|
|
: base(
|
|
InType: InType,
|
|
InName: InName,
|
|
InModuleDirectory: InModuleDirectory,
|
|
InRules: InRules,
|
|
InRulesFile: InRulesFile
|
|
)
|
|
{
|
|
}
|
|
|
|
// UEBuildModule interface.
|
|
public override List<FileItem> Compile(UEBuildTarget Target, UEToolChain ToolChain, CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment)
|
|
{
|
|
return new List<FileItem>();
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// A module that is compiled from C++ code.
|
|
/// </summary>
|
|
public class UEBuildModuleCPP : UEBuildModule
|
|
{
|
|
public class AutoGenerateCppInfoClass
|
|
{
|
|
public class BuildInfoClass
|
|
{
|
|
/// <summary>
|
|
/// The wildcard of the *.generated.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 .generated.cpp files. If this is null, then we're not building .generated.cpp files for this module.
|
|
/// </summary>
|
|
public BuildInfoClass BuildInfo;
|
|
|
|
public AutoGenerateCppInfoClass(BuildInfoClass InBuildInfo)
|
|
{
|
|
BuildInfo = InBuildInfo;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Information about the .generated.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)
|
|
{
|
|
SourceFilesToBuild.CPPFiles.AddRange(Files);
|
|
}
|
|
|
|
/// <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 generated code
|
|
/// </summary>
|
|
public readonly DirectoryReference GeneratedCodeDirectory;
|
|
|
|
/// <summary>
|
|
/// The preprocessor definitions used to compile this module's private implementation.
|
|
/// </summary>
|
|
HashSet<string> Definitions;
|
|
|
|
/// When set, allows this module to report compiler definitions and include paths for Intellisense
|
|
IntelliSenseGatherer IntelliSenseGatherer;
|
|
|
|
public List<string> IncludeSearchPaths = new List<string>();
|
|
|
|
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>
|
|
/// Hack to skip adding definitions to compile environment. They will be baked into source code by external code.
|
|
/// </summary>
|
|
public bool bSkipDefinitionsForCompileEnvironment = false;
|
|
|
|
public int FindNumberOfGeneratedCppFiles()
|
|
{
|
|
return ((null == GeneratedCodeDirectory) || !GeneratedCodeDirectory.Exists()) ? 0
|
|
: (GeneratedCodeDirectory.EnumerateFileReferences("*.generated.*.cpp", SearchOption.AllDirectories).Count()
|
|
+ GeneratedCodeDirectory.EnumerateFileReferences("*.generated.cpp", SearchOption.AllDirectories).Count());
|
|
}
|
|
|
|
/// <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);
|
|
}
|
|
}
|
|
}
|
|
|
|
public UEBuildModuleCPP(
|
|
string InName,
|
|
UHTModuleType InType,
|
|
DirectoryReference InModuleDirectory,
|
|
DirectoryReference InGeneratedCodeDirectory,
|
|
IntelliSenseGatherer InIntelliSenseGatherer,
|
|
IEnumerable<FileItem> InSourceFiles,
|
|
ModuleRules InRules,
|
|
bool bInBuildSourceFiles,
|
|
FileReference InRulesFile
|
|
)
|
|
: base(
|
|
InName,
|
|
InType,
|
|
InModuleDirectory,
|
|
InRules,
|
|
InRulesFile
|
|
)
|
|
{
|
|
GeneratedCodeDirectory = InGeneratedCodeDirectory;
|
|
IntelliSenseGatherer = InIntelliSenseGatherer;
|
|
|
|
CategorizeSourceFiles(InSourceFiles, SourceFilesFound);
|
|
if (bInBuildSourceFiles)
|
|
{
|
|
SourceFilesToBuild.CopyFrom(SourceFilesFound);
|
|
}
|
|
|
|
Definitions = HashSetFromOptionalEnumerableStringParameter(InRules.Definitions);
|
|
foreach (string Def in Definitions)
|
|
{
|
|
Log.TraceVerbose("Compile Env {0}: {1}", Name, Def);
|
|
}
|
|
}
|
|
|
|
// UEBuildModule interface.
|
|
public override List<FileItem> Compile(UEBuildTarget Target, UEToolChain ToolChain, CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment)
|
|
{
|
|
UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);
|
|
|
|
List<FileItem> LinkInputFiles = new List<FileItem>();
|
|
if (ProjectFileGenerator.bGenerateProjectFiles && IntelliSenseGatherer == null)
|
|
{
|
|
// Nothing to do for IntelliSense, bail out early
|
|
return LinkInputFiles;
|
|
}
|
|
|
|
CPPEnvironment ModuleCompileEnvironment = CreateModuleCompileEnvironment(Target, CompileEnvironment);
|
|
IncludeSearchPaths = ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths.ToList();
|
|
IncludeSearchPaths.AddRange(ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.ToList());
|
|
|
|
if (IntelliSenseGatherer != null)
|
|
{
|
|
// Update project file's set of preprocessor definitions and include paths
|
|
IntelliSenseGatherer.AddIntelliSensePreprocessorDefinitions(ModuleCompileEnvironment.Config.Definitions);
|
|
IntelliSenseGatherer.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths, bAddingSystemIncludes: true);
|
|
IntelliSenseGatherer.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths, bAddingSystemIncludes: false);
|
|
|
|
// Bail out. We don't need to actually compile anything while generating project files.
|
|
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))
|
|
);
|
|
}
|
|
|
|
// For an executable or a static library do not use the default RC file -
|
|
// If the executable wants it, it will be in their source list anyway.
|
|
// The issue here is that when making a monolithic game, the processing
|
|
// of the other game modules will stomp the game-specific rc file.
|
|
if (Binary.Config.Type == UEBuildBinaryType.DynamicLinkLibrary)
|
|
{
|
|
// Add default PCLaunch.rc file if this module has no own resource file specified
|
|
if (SourceFilesToBuild.RCFiles.Count <= 0)
|
|
{
|
|
FileReference DefRC = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Launch", "Resources", "Windows", "PCLaunch.rc");
|
|
FileItem Item = FileItem.GetItemByFileReference(DefRC);
|
|
SourceFilesToBuild.RCFiles.Add(Item);
|
|
}
|
|
|
|
// Always compile in the API version resource separately. This is required for the module manager to detect compatible API versions.
|
|
FileReference ModuleVersionRC = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Core", "Resources", "Windows", "ModuleVersionResource.rc.inl");
|
|
FileItem ModuleVersionItem = FileItem.GetItemByFileReference(ModuleVersionRC);
|
|
if (!SourceFilesToBuild.RCFiles.Contains(ModuleVersionItem))
|
|
{
|
|
SourceFilesToBuild.RCFiles.Add(ModuleVersionItem);
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
// 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)
|
|
{
|
|
RCFile.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo;
|
|
}
|
|
}
|
|
|
|
|
|
// Check to see if this is an Engine module (including program or plugin modules). That is, the module is located under the "Engine" folder
|
|
bool IsPluginModule = ModuleDirectory.IsUnderDirectory(DirectoryReference.Combine(Target.ProjectDirectory, "Plugins"));
|
|
bool IsGameModule = !IsPluginModule && !ModuleDirectory.IsUnderDirectory(UnrealBuildTool.EngineDirectory);
|
|
|
|
// 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 = BuildConfiguration.MinFilesUsingPrecompiledHeader;
|
|
if (Rules.MinFilesUsingPrecompiledHeaderOverride != 0)
|
|
{
|
|
MinFilesUsingPrecompiledHeader = Rules.MinFilesUsingPrecompiledHeaderOverride;
|
|
}
|
|
else if (IsGameModule && BuildConfiguration.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 (IsGameModule)
|
|
{
|
|
// 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 = BuildConfiguration.MinGameModuleSourceFilesForUnityBuild;
|
|
}
|
|
|
|
|
|
// Should we use unity build mode for this module?
|
|
bool bModuleUsesUnityBuild = false;
|
|
if (BuildConfiguration.bUseUnityBuild || BuildConfiguration.bForceUnityBuild)
|
|
{
|
|
if (BuildConfiguration.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 (enabled in BuildConfiguration)", this.Name);
|
|
bModuleUsesUnityBuild = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("Module '{0}' not using unity build mode (disabled in BuildConfiguration)", this.Name);
|
|
}
|
|
|
|
// The environment with which to compile the CPP files
|
|
CPPEnvironment CPPCompileEnvironment = ModuleCompileEnvironment;
|
|
|
|
// Precompiled header support.
|
|
bool bWasModuleCodeCompiled = false;
|
|
if (BuildPlatform.ShouldUsePCHFiles(CompileEnvironment.Config.Target.Platform, CompileEnvironment.Config.Target.Configuration))
|
|
{
|
|
DateTime PCHGenTimerStart = DateTime.UtcNow;
|
|
|
|
// The code below will figure out whether this module will either use a "unique PCH" (private PCH that will only be included by
|
|
// this module's code files), or a "shared PCH" (potentially included by many code files in many modules.) Only one or the other
|
|
// will be used.
|
|
FileItem SharedPCHHeaderFile = null;
|
|
|
|
// In the case of a shared PCH, we also need to keep track of which module that PCH's header file is a member of
|
|
string SharedPCHModuleName = String.Empty;
|
|
|
|
if (BuildConfiguration.bUseSharedPCHs && CompileEnvironment.Config.bIsBuildingLibrary)
|
|
{
|
|
Log.TraceVerbose("Module '{0}' was not allowed to use Shared PCHs, because we're compiling to a library", this.Name);
|
|
}
|
|
|
|
bool bUseSharedPCHFiles = BuildConfiguration.bUseSharedPCHs && !CompileEnvironment.Config.bIsBuildingLibrary && GlobalCompileEnvironment.SharedPCHHeaderFiles.Count > 0;
|
|
|
|
if (bUseSharedPCHFiles)
|
|
{
|
|
FileReference SharingPCHHeaderFilePath = null;
|
|
bool bIsASharedPCHModule = bUseSharedPCHFiles && GlobalCompileEnvironment.SharedPCHHeaderFiles.Any(PCH => PCH.Module == this);
|
|
if (bIsASharedPCHModule)
|
|
{
|
|
SharingPCHHeaderFilePath = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, Rules.SharedPCHHeaderFile);
|
|
}
|
|
|
|
// We can't use a shared PCH file when compiling a module
|
|
// with exports, because the shared PCH can only have imports in it to work correctly.
|
|
bool bAllowSharedPCH = (Rules.PCHUsage == ModuleRules.PCHUsageMode.NoSharedPCHs) ? false : true;
|
|
bool bCanModuleUseOwnSharedPCH = bAllowSharedPCH && bIsASharedPCHModule && !Binary.Config.bAllowExports && ProcessedDependencies.UniquePCHHeaderFile.Reference == SharingPCHHeaderFilePath;
|
|
if (bAllowSharedPCH && (!bIsASharedPCHModule || bCanModuleUseOwnSharedPCH))
|
|
{
|
|
// Figure out which shared PCH tier we're in
|
|
List<UEBuildModule> ReferencedModules = new List<UEBuildModule>();
|
|
{
|
|
this.GetAllDependencyModules(ReferencedModules, new HashSet<UEBuildModule>(), bIncludeDynamicallyLoaded: false, bForceCircular: false, bOnlyDirectDependencies: true);
|
|
}
|
|
|
|
int LargestSharedPCHHeaderFileIndex = -1;
|
|
foreach (UEBuildModule DependencyModule in ReferencedModules)
|
|
{
|
|
// These Shared PCHs are ordered from least complex to most complex. We'll start at the last one and search backwards.
|
|
for (int SharedPCHHeaderFileIndex = GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1; SharedPCHHeaderFileIndex > LargestSharedPCHHeaderFileIndex; --SharedPCHHeaderFileIndex)
|
|
{
|
|
SharedPCHHeaderInfo CurSharedPCHHeaderFile = GlobalCompileEnvironment.SharedPCHHeaderFiles[SharedPCHHeaderFileIndex];
|
|
|
|
if (DependencyModule == CurSharedPCHHeaderFile.Module ||
|
|
(bIsASharedPCHModule && CurSharedPCHHeaderFile.Module == this)) // If we ourselves are a shared PCH module, always at least use our own module as our shared PCH header if we can't find anything better
|
|
{
|
|
SharedPCHModuleName = CurSharedPCHHeaderFile.Module.Name;
|
|
SharedPCHHeaderFile = CurSharedPCHHeaderFile.PCHHeaderFile;
|
|
LargestSharedPCHHeaderFileIndex = SharedPCHHeaderFileIndex;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (LargestSharedPCHHeaderFileIndex == GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1)
|
|
{
|
|
// We've determined that the module is using our most complex PCH header, so we can early-out
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Did we not find a shared PCH header that is being included by this module? This could happen if the module is not including Core.h, even indirectly.
|
|
if (String.IsNullOrEmpty(SharedPCHModuleName))
|
|
{
|
|
throw new BuildException("Module {0} doesn't use a Shared PCH! Please add a dependency on a Shared PCH module to this module's dependency list", this.Name);
|
|
}
|
|
|
|
// Keep track of how many modules make use of this PCH for performance diagnostics
|
|
SharedPCHHeaderInfo LargestSharedPCHHeader = GlobalCompileEnvironment.SharedPCHHeaderFiles[LargestSharedPCHHeaderFileIndex];
|
|
++LargestSharedPCHHeader.NumModulesUsingThisPCH;
|
|
|
|
// Don't allow game modules to use engine PCHs in DebugGame - the optimization settings aren't correct.
|
|
// @todo: we should be creating shared PCHs ahead of time, and only using them if our settings match. as it is, the first modules compiled
|
|
// (which are currently plugins) get to call the shots for how the shared PCH gets built, and that might be a game plugin built in debug...
|
|
if(Target.Configuration == UnrealTargetConfiguration.DebugGame && SharedPCHHeaderFile.Reference.IsUnderDirectory(UnrealBuildTool.EngineDirectory) && !RulesFile.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
|
|
{
|
|
SharedPCHModuleName = null;
|
|
SharedPCHHeaderFile = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("Module '{0}' cannot create or use Shared PCHs, because it needs its own private PCH", this.Name);
|
|
}
|
|
}
|
|
|
|
|
|
// The precompiled header environment for all source files in this module that use a precompiled header, if we even need one
|
|
PrecompileHeaderEnvironment ModulePCHEnvironment = null;
|
|
|
|
// 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 (SharedPCHHeaderFile != null || SourceFilesToBuild.CPPFiles.Count >= MinFilesUsingPrecompiledHeader)
|
|
{
|
|
FileItem PCHToUse;
|
|
|
|
if (SharedPCHHeaderFile != null)
|
|
{
|
|
ModulePCHEnvironment = ApplySharedPCH(GlobalCompileEnvironment, CompileEnvironment, ModuleCompileEnvironment, SourceFilesToBuild.CPPFiles, ref SharedPCHHeaderFile);
|
|
if (ModulePCHEnvironment != null)
|
|
{
|
|
// @todo SharedPCH: Ideally we would exhaustively check for a compatible compile environment (definitions, imports/exports, etc)
|
|
// Currently, it's possible for the shared PCH to be compiled differently depending on which module UBT happened to have
|
|
// include it first during the build phase. This could create problems with deterministic builds, or turn up compile
|
|
// errors unexpectedly due to compile environment differences.
|
|
Log.TraceVerbose("Module " + Name + " uses existing Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "' (from module " + ModulePCHEnvironment.ModuleName + ")");
|
|
}
|
|
|
|
PCHToUse = SharedPCHHeaderFile;
|
|
}
|
|
else
|
|
{
|
|
PCHToUse = ProcessedDependencies.UniquePCHHeaderFile;
|
|
}
|
|
|
|
if (PCHToUse != null)
|
|
{
|
|
// Update all CPPFiles to point to the PCH
|
|
foreach (FileItem CPPFile in SourceFilesToBuild.CPPFiles)
|
|
{
|
|
CPPFile.PCHHeaderNameInCode = PCHToUse.AbsolutePath;
|
|
CPPFile.PrecompiledHeaderIncludeFilename = PCHToUse.Reference;
|
|
}
|
|
}
|
|
|
|
// A shared PCH was not already set up for us, so set one up.
|
|
if (ModulePCHEnvironment == null && SourceFilesToBuild.CPPFiles.Count > 0)
|
|
{
|
|
FileItem PCHHeaderFile = ProcessedDependencies.UniquePCHHeaderFile;
|
|
string PCHModuleName = this.Name;
|
|
if (SharedPCHHeaderFile != null)
|
|
{
|
|
PCHHeaderFile = SharedPCHHeaderFile;
|
|
PCHModuleName = SharedPCHModuleName;
|
|
}
|
|
string PCHHeaderNameInCode = SourceFilesToBuild.CPPFiles[0].PCHHeaderNameInCode;
|
|
|
|
ModulePCHEnvironment = new PrecompileHeaderEnvironment(PCHModuleName, PCHHeaderNameInCode, PCHHeaderFile, ModuleCompileEnvironment.Config.CLRMode, ModuleCompileEnvironment.Config.OptimizeCode);
|
|
|
|
if (SharedPCHHeaderFile != null)
|
|
{
|
|
// Add to list of shared PCH environments
|
|
GlobalCompileEnvironment.SharedPCHEnvironments.Add(ModulePCHEnvironment);
|
|
Log.TraceVerbose("Module " + Name + " uses new Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'");
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("Module " + Name + " uses a Unique PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log.TraceVerbose("Module " + Name + " doesn't use a Shared PCH, and only has " + SourceFilesToBuild.CPPFiles.Count.ToString() + " source file(s). No Unique PCH will be generated.");
|
|
}
|
|
|
|
// Compile the C++ source or the unity C++ files that use a PCH environment.
|
|
if (ModulePCHEnvironment != null)
|
|
{
|
|
// Setup a new compile environment for this module's source files. It's pretty much the exact same as the
|
|
// module's compile environment, except that it will include a PCH file.
|
|
|
|
CPPEnvironment ModulePCHCompileEnvironment = ModuleCompileEnvironment.DeepCopy();
|
|
ModulePCHCompileEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.Include;
|
|
ModulePCHCompileEnvironment.Config.PrecompiledHeaderIncludeFilename = ModulePCHEnvironment.PrecompiledHeaderIncludeFilename.Reference;
|
|
ModulePCHCompileEnvironment.Config.PCHHeaderNameInCode = ModulePCHEnvironment.PCHHeaderNameInCode;
|
|
|
|
if (SharedPCHHeaderFile != null)
|
|
{
|
|
// Shared PCH headers need to be force included, because we're basically forcing the module to use
|
|
// the precompiled header that we want, instead of the "first include" in each respective .cpp file
|
|
ModulePCHCompileEnvironment.Config.bForceIncludePrecompiledHeader = true;
|
|
}
|
|
|
|
List<FileItem> CPPFilesToBuild = SourceFilesToBuild.CPPFiles;
|
|
if (bModuleUsesUnityBuild)
|
|
{
|
|
// unity files generated for only the set of files which share the same PCH environment
|
|
CPPFilesToBuild = Unity.GenerateUnityCPPs(ToolChain, Target, CPPFilesToBuild, ModulePCHCompileEnvironment, Name);
|
|
}
|
|
|
|
// Check if there are enough unity files to warrant pch generation (and we haven't already generated the shared one)
|
|
if (ModulePCHEnvironment.PrecompiledHeaderFile == null)
|
|
{
|
|
if (SharedPCHHeaderFile != null || CPPFilesToBuild.Count >= MinFilesUsingPrecompiledHeader)
|
|
{
|
|
CPPOutput PCHOutput;
|
|
if (SharedPCHHeaderFile == null)
|
|
{
|
|
PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction(
|
|
ToolChain,
|
|
Target,
|
|
CPPFilesToBuild[0].PCHHeaderNameInCode,
|
|
ModulePCHEnvironment.PrecompiledHeaderIncludeFilename,
|
|
ModuleCompileEnvironment,
|
|
ModuleCompileEnvironment.Config.OutputDirectory,
|
|
ModuleCompileEnvironment.Config.PCHOutputDirectory,
|
|
Name,
|
|
true);
|
|
}
|
|
else
|
|
{
|
|
UEBuildModuleCPP SharedPCHModule = (UEBuildModuleCPP)Target.FindOrCreateModuleByName(SharedPCHModuleName);
|
|
|
|
CPPEnvironment SharedPCHCompileEnvironment = GlobalCompileEnvironment.DeepCopy();
|
|
SharedPCHCompileEnvironment.Config.bEnableShadowVariableWarning = SharedPCHModule.Rules.bEnableShadowVariableWarnings;
|
|
|
|
List<UEBuildModule> Modules = new List<UEBuildModule>();
|
|
Dictionary<UEBuildModule, bool> ModuleToIncludePathsOnlyFlag = new Dictionary<UEBuildModule, bool>();
|
|
SharedPCHModule.FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);
|
|
|
|
foreach (UEBuildModule Module in Modules)
|
|
{
|
|
Module.AddModuleToCompileEnvironment(
|
|
Binary,
|
|
ModuleToIncludePathsOnlyFlag[Module],
|
|
SharedPCHCompileEnvironment.Config.CPPIncludeInfo.IncludePaths,
|
|
SharedPCHCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths,
|
|
SharedPCHCompileEnvironment.Config.Definitions,
|
|
SharedPCHCompileEnvironment.Config.AdditionalFrameworks);
|
|
}
|
|
|
|
PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction(
|
|
ToolChain,
|
|
Target,
|
|
CPPFilesToBuild[0].PCHHeaderNameInCode,
|
|
ModulePCHEnvironment.PrecompiledHeaderIncludeFilename,
|
|
SharedPCHCompileEnvironment,
|
|
DirectoryReference.Combine(CompileEnvironment.Config.OutputDirectory, "SharedPCHs"),
|
|
(CompileEnvironment.Config.PCHOutputDirectory == null)? null : DirectoryReference.Combine(CompileEnvironment.Config.PCHOutputDirectory, "SharedPCHs"),
|
|
"Shared",
|
|
false);
|
|
}
|
|
|
|
ModulePCHEnvironment.PrecompiledHeaderFile = PCHOutput.PrecompiledHeaderFile;
|
|
|
|
ModulePCHEnvironment.OutputObjectFiles.Clear();
|
|
ModulePCHEnvironment.OutputObjectFiles.AddRange(PCHOutput.ObjectFiles);
|
|
}
|
|
else if (CPPFilesToBuild.Count < MinFilesUsingPrecompiledHeader)
|
|
{
|
|
Log.TraceVerbose("Module " + Name + " doesn't use a Shared PCH, and only has " + CPPFilesToBuild.Count.ToString() + " unity source file(s). No Unique PCH will be generated.");
|
|
}
|
|
}
|
|
|
|
if (ModulePCHEnvironment.PrecompiledHeaderFile != null)
|
|
{
|
|
// Link in the object files produced by creating the precompiled header.
|
|
LinkInputFiles.AddRange(ModulePCHEnvironment.OutputObjectFiles);
|
|
|
|
// if pch action was generated for the environment then use pch
|
|
ModulePCHCompileEnvironment.PrecompiledHeaderFile = ModulePCHEnvironment.PrecompiledHeaderFile;
|
|
|
|
// Use this compile environment from now on
|
|
CPPCompileEnvironment = ModulePCHCompileEnvironment;
|
|
}
|
|
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, CPPFilesToBuild, Name).ObjectFiles);
|
|
bWasModuleCodeCompiled = true;
|
|
}
|
|
|
|
if (BuildConfiguration.bPrintPerformanceInfo)
|
|
{
|
|
double PCHGenTime = (DateTime.UtcNow - PCHGenTimerStart).TotalSeconds;
|
|
TotalPCHGenTime += PCHGenTime;
|
|
}
|
|
}
|
|
|
|
if (!bWasModuleCodeCompiled && SourceFilesToBuild.CPPFiles.Count > 0)
|
|
{
|
|
List<FileItem> CPPFilesToCompile = SourceFilesToBuild.CPPFiles;
|
|
if (bModuleUsesUnityBuild)
|
|
{
|
|
CPPFilesToCompile = Unity.GenerateUnityCPPs(ToolChain, Target, CPPFilesToCompile, CPPCompileEnvironment, Name);
|
|
}
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, CPPFilesToCompile, Name).ObjectFiles);
|
|
}
|
|
|
|
if (AutoGenerateCppInfo != null && AutoGenerateCppInfo.BuildInfo != null && !CPPCompileEnvironment.bHackHeaderGenerator)
|
|
{
|
|
string[] GeneratedFiles = Directory.GetFiles(Path.GetDirectoryName(AutoGenerateCppInfo.BuildInfo.FileWildcard), Path.GetFileName(AutoGenerateCppInfo.BuildInfo.FileWildcard));
|
|
foreach (string GeneratedFilename in GeneratedFiles)
|
|
{
|
|
FileItem GeneratedCppFileItem = FileItem.GetItemByPath(GeneratedFilename);
|
|
|
|
CachePCHUsageForModuleSourceFile(Target, CPPCompileEnvironment, 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?)
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, new List<FileItem> { GeneratedCppFileItem }, Name).ObjectFiles);
|
|
}
|
|
}
|
|
|
|
// Compile C files directly.
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.CFiles, Name).ObjectFiles);
|
|
|
|
// Compile CC files directly.
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.CCFiles, Name).ObjectFiles);
|
|
|
|
// Compile MM files directly.
|
|
LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.MMFiles, Name).ObjectFiles);
|
|
|
|
// Compile RC files.
|
|
LinkInputFiles.AddRange(ToolChain.CompileRCFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.RCFiles).ObjectFiles);
|
|
|
|
return LinkInputFiles;
|
|
}
|
|
|
|
private PrecompileHeaderEnvironment ApplySharedPCH(CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment, CPPEnvironment ModuleCompileEnvironment, List<FileItem> CPPFiles, ref FileItem SharedPCHHeaderFile)
|
|
{
|
|
// Check to see if we have a PCH header already setup that we can use
|
|
FileItem SharedPCHHeaderFileCopy = SharedPCHHeaderFile;
|
|
PrecompileHeaderEnvironment SharedPCHEnvironment = GlobalCompileEnvironment.SharedPCHEnvironments.Find(Env => Env.PrecompiledHeaderIncludeFilename == SharedPCHHeaderFileCopy);
|
|
if (SharedPCHEnvironment == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Don't mix CLR modes
|
|
if (SharedPCHEnvironment.CLRMode != ModuleCompileEnvironment.Config.CLRMode)
|
|
{
|
|
Log.TraceVerbose("Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because CLR modes don't match", Name, SharedPCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath, SharedPCHEnvironment.ModuleName);
|
|
SharedPCHHeaderFile = null;
|
|
return null;
|
|
}
|
|
// Don't mix RTTI modes
|
|
if (Rules.bUseRTTI)
|
|
{
|
|
Log.TraceVerbose("Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because RTTI modes don't match", Name, SharedPCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath, SharedPCHEnvironment.ModuleName);
|
|
SharedPCHHeaderFile = null;
|
|
return null;
|
|
}
|
|
|
|
// Don't mix non-optimized code with optimized code (PCHs won't be compatible)
|
|
ModuleRules.CodeOptimization SharedPCHCodeOptimization = SharedPCHEnvironment.OptimizeCode;
|
|
ModuleRules.CodeOptimization ModuleCodeOptimization = ModuleCompileEnvironment.Config.OptimizeCode;
|
|
|
|
if (CompileEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Debug)
|
|
{
|
|
if (SharedPCHCodeOptimization == ModuleRules.CodeOptimization.InNonDebugBuilds)
|
|
{
|
|
SharedPCHCodeOptimization = ModuleRules.CodeOptimization.Always;
|
|
}
|
|
|
|
if (ModuleCodeOptimization == ModuleRules.CodeOptimization.InNonDebugBuilds)
|
|
{
|
|
ModuleCodeOptimization = ModuleRules.CodeOptimization.Always;
|
|
}
|
|
}
|
|
|
|
if (SharedPCHCodeOptimization != ModuleCodeOptimization)
|
|
{
|
|
Log.TraceVerbose("Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because optimization levels don't match", Name, SharedPCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath, SharedPCHEnvironment.ModuleName);
|
|
SharedPCHHeaderFile = null;
|
|
return null;
|
|
}
|
|
|
|
return SharedPCHEnvironment;
|
|
}
|
|
|
|
public static FileItem CachePCHUsageForModuleSourceFile(UEBuildTarget Target, CPPEnvironment ModuleCompileEnvironment, FileItem CPPFile)
|
|
{
|
|
if (!CPPFile.bExists)
|
|
{
|
|
throw new BuildException("Required source file not found: " + CPPFile.AbsolutePath);
|
|
}
|
|
|
|
DateTime PCHCacheTimerStart = DateTime.UtcNow;
|
|
|
|
UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(ModuleCompileEnvironment.Config.Target.Platform);
|
|
List<string> IncludePathsToSearch = ModuleCompileEnvironment.Config.CPPIncludeInfo.GetIncludesPathsToSearch(CPPFile);
|
|
|
|
// 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.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo;
|
|
|
|
FileItem PCHFile = CachePCHUsageForCPPFile(Target, CPPFile, BuildPlatform, IncludePathsToSearch, ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludeFileSearchDictionary);
|
|
|
|
if (BuildConfiguration.bPrintPerformanceInfo)
|
|
{
|
|
double PCHCacheTime = (DateTime.UtcNow - PCHCacheTimerStart).TotalSeconds;
|
|
TotalPCHCacheTime += PCHCacheTime;
|
|
}
|
|
|
|
return PCHFile;
|
|
}
|
|
|
|
|
|
public void CachePCHUsageForModuleSourceFiles(UEBuildTarget Target, CPPEnvironment ModuleCompileEnvironment)
|
|
{
|
|
if (ProcessedDependencies == null)
|
|
{
|
|
DateTime PCHCacheTimerStart = DateTime.UtcNow;
|
|
|
|
UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(ModuleCompileEnvironment.Config.Target.Platform);
|
|
|
|
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!
|
|
{
|
|
// Build a single list of include paths to search.
|
|
List<string> IncludePathsToSearch = ModuleCompileEnvironment.Config.CPPIncludeInfo.GetIncludesPathsToSearch(CPPFile);
|
|
|
|
// 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.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo;
|
|
|
|
// Find headers used by the source file.
|
|
FileItem PCH = UEBuildModuleCPP.CachePCHUsageForCPPFile(Target, CPPFile, BuildPlatform, IncludePathsToSearch, ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludeFileSearchDictionary);
|
|
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
|
|
UsageMapPCH.GetOrAddNew(CPPFile.PrecompiledHeaderIncludeFilename).Add(CPPFile);
|
|
}
|
|
|
|
if (BuildConfiguration.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}",
|
|
Name,
|
|
MostFilesAreIncludingPCH,
|
|
FilesNotIncludingBestPCH);
|
|
}
|
|
}
|
|
|
|
if (BuildConfiguration.bPrintPerformanceInfo)
|
|
{
|
|
double PCHCacheTime = (DateTime.UtcNow - PCHCacheTimerStart).TotalSeconds;
|
|
TotalPCHCacheTime += PCHCacheTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static FileItem CachePCHUsageForCPPFile(UEBuildTarget Target, FileItem CPPFile, UEBuildPlatform BuildPlatform, List<string> IncludePathsToSearch, Dictionary<string, FileItem> IncludeFileSearchDictionary)
|
|
{
|
|
// @todo ubtmake: We don't really need to scan every file looking for PCH headers, just need one. The rest is just for error checking.
|
|
// @todo ubtmake: We don't need all of the direct includes either. We just need the first, unless we want to check for errors.
|
|
List<DependencyInclude> DirectIncludeFilenames = CPPEnvironment.GetDirectIncludeDependencies(Target, CPPFile, BuildPlatform, bOnlyCachedDependencies: false);
|
|
if (BuildConfiguration.bPrintDebugInfo)
|
|
{
|
|
Log.TraceVerbose("Found direct includes for {0}: {1}", Path.GetFileName(CPPFile.AbsolutePath), string.Join(", ", DirectIncludeFilenames.Select(F => F.IncludeName)));
|
|
}
|
|
|
|
if (DirectIncludeFilenames.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
DependencyInclude FirstInclude = DirectIncludeFilenames[0];
|
|
|
|
// The pch header should always be the first include in the source file.
|
|
// NOTE: This is not an absolute path. This is just the literal include string from the source file!
|
|
CPPFile.PCHHeaderNameInCode = FirstInclude.IncludeName;
|
|
|
|
// Resolve the PCH header to an absolute path.
|
|
// Check NullOrEmpty here because if the file could not be resolved we need to throw an exception
|
|
if (FirstInclude.IncludeResolvedNameIfSuccessful != null &&
|
|
// ignore any preexisting resolve cache if we are not configured to use it.
|
|
BuildConfiguration.bUseIncludeDependencyResolveCache &&
|
|
// if we are testing the resolve cache, we force UBT to resolve every time to look for conflicts
|
|
!BuildConfiguration.bTestIncludeDependencyResolveCache)
|
|
{
|
|
CPPFile.PrecompiledHeaderIncludeFilename = FirstInclude.IncludeResolvedNameIfSuccessful;
|
|
return FileItem.GetItemByFileReference(CPPFile.PrecompiledHeaderIncludeFilename);
|
|
}
|
|
|
|
// search the include paths to resolve the file.
|
|
FileItem PrecompiledHeaderIncludeFile = CPPEnvironment.FindIncludedFile(CPPFile.PCHHeaderNameInCode, !BuildConfiguration.bCheckExternalHeadersForModification, IncludePathsToSearch, IncludeFileSearchDictionary);
|
|
if (PrecompiledHeaderIncludeFile == null)
|
|
{
|
|
throw new BuildException("The first include statement in source file '{0}' is trying to include the file '{1}' as the precompiled header, but that file could not be located in any of the module's include search paths.", CPPFile.AbsolutePath, CPPFile.PCHHeaderNameInCode);
|
|
}
|
|
|
|
CPPEnvironment.IncludeDependencyCache[Target].CacheResolvedIncludeFullPath(CPPFile, 0, PrecompiledHeaderIncludeFile.Reference);
|
|
CPPFile.PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFile.Reference;
|
|
|
|
return PrecompiledHeaderIncludeFile;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a compile environment from a base environment based on the module settings.
|
|
/// </summary>
|
|
/// <param name="BaseCompileEnvironment">An existing environment to base the module compile environment on.</param>
|
|
/// <returns>The new module compile environment.</returns>
|
|
public CPPEnvironment CreateModuleCompileEnvironment(UEBuildTarget Target, CPPEnvironment BaseCompileEnvironment)
|
|
{
|
|
CPPEnvironment Result = BaseCompileEnvironment.DeepCopy();
|
|
|
|
if (Binary == null)
|
|
{
|
|
// Adding this check here as otherwise the call to Binary.Config.IntermediateDirectory will give an
|
|
// unhandled exception
|
|
throw new BuildException("UEBuildBinary not set up for module {0}", this.ToString());
|
|
}
|
|
|
|
// Override compile environment
|
|
Result.Config.bFasterWithoutUnity = Rules.bFasterWithoutUnity;
|
|
Result.Config.OptimizeCode = Rules.OptimizeCode;
|
|
Result.Config.bUseRTTI = Rules.bUseRTTI;
|
|
Result.Config.bUseAVX = Rules.bUseAVX;
|
|
Result.Config.bEnableBufferSecurityChecks = Rules.bEnableBufferSecurityChecks;
|
|
Result.Config.MinSourceFilesForUnityBuildOverride = Rules.MinSourceFilesForUnityBuildOverride;
|
|
Result.Config.MinFilesUsingPrecompiledHeaderOverride = Rules.MinFilesUsingPrecompiledHeaderOverride;
|
|
Result.Config.bBuildLocallyWithSNDBS = Rules.bBuildLocallyWithSNDBS;
|
|
Result.Config.bEnableExceptions = Rules.bEnableExceptions;
|
|
Result.Config.bEnableShadowVariableWarning = Rules.bEnableShadowVariableWarnings;
|
|
Result.Config.bUseStaticCRT = (Target.Rules != null && Target.Rules.bUseStaticCRT);
|
|
Result.Config.OutputDirectory = DirectoryReference.Combine(Binary.Config.IntermediateDirectory, Name);
|
|
|
|
// 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 (Target.Configuration == UnrealTargetConfiguration.DebugGame)
|
|
{
|
|
if (!ModuleDirectory.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
|
|
{
|
|
Result.Config.Target.Configuration = CPPTargetConfiguration.Debug;
|
|
Result.Config.Definitions.Add("UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=1");
|
|
}
|
|
}
|
|
|
|
// Add the module's private definitions.
|
|
Result.Config.Definitions.AddRange(Definitions);
|
|
|
|
// Setup the compile environment for the module.
|
|
SetupPrivateCompileEnvironment(Result.Config.CPPIncludeInfo.IncludePaths, Result.Config.CPPIncludeInfo.SystemIncludePaths, Result.Config.Definitions, Result.Config.AdditionalFrameworks);
|
|
|
|
// @hack to skip adding definitions to compile environment, they will be baked into source code files
|
|
if (bSkipDefinitionsForCompileEnvironment)
|
|
{
|
|
Result.Config.Definitions.Clear();
|
|
Result.Config.CPPIncludeInfo.IncludePaths = new HashSet<string>(BaseCompileEnvironment.Config.CPPIncludeInfo.IncludePaths);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
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>
|
|
public UHTModuleInfoCacheType GetCachedUHTModuleInfo(EGeneratedCodeVersion GeneratedCodeVersion)
|
|
{
|
|
if (UHTModuleInfoCache == null)
|
|
{
|
|
IEnumerable<string> HeaderFilenames = Directory.GetFiles(ModuleDirectory.FullName, "*.h", SearchOption.AllDirectories);
|
|
UHTModuleInfo Info = ExternalExecution.CreateUHTModuleInfo(HeaderFilenames, Name, ModuleDirectory, Type, GeneratedCodeVersion);
|
|
UHTModuleInfoCache = new UHTModuleInfoCacheType(Info.PublicUObjectHeaders.Concat(Info.PublicUObjectClassesHeaders).Concat(Info.PrivateUObjectHeaders).Select(x => x.AbsolutePath).ToList(), Info);
|
|
}
|
|
|
|
return UHTModuleInfoCache;
|
|
}
|
|
|
|
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);
|
|
AllDependencyModules.AddRange(PlatformSpecificDynamicallyLoadedModules);
|
|
}
|
|
|
|
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);
|
|
}
|
|
if (PlatformSpecificDynamicallyLoadedModules != null)
|
|
{
|
|
DependentModules.AddRange(PlatformSpecificDynamicallyLoadedModules);
|
|
}
|
|
|
|
// Find modules for each of them, and add their dependencies too
|
|
foreach (UEBuildModule DependentModule in DependentModules)
|
|
{
|
|
DependentModule.RecursivelyAddPrecompiledModules(Modules);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A module that is compiled from C++ CLR code.
|
|
/// </summary>
|
|
class UEBuildModuleCPPCLR : UEBuildModuleCPP
|
|
{
|
|
/// <summary>
|
|
/// The assemblies referenced by the module's private implementation.
|
|
/// </summary>
|
|
HashSet<string> PrivateAssemblyReferences;
|
|
|
|
public UEBuildModuleCPPCLR(
|
|
string InName,
|
|
UHTModuleType InType,
|
|
DirectoryReference InModuleDirectory,
|
|
DirectoryReference InGeneratedCodeDirectory,
|
|
IntelliSenseGatherer InIntelliSenseGatherer,
|
|
IEnumerable<FileItem> InSourceFiles,
|
|
ModuleRules InRules,
|
|
bool bInBuildSourceFiles,
|
|
FileReference InRulesFile
|
|
)
|
|
: base(InName, InType, InModuleDirectory, InGeneratedCodeDirectory, InIntelliSenseGatherer,
|
|
InSourceFiles, InRules,
|
|
bInBuildSourceFiles, InRulesFile)
|
|
{
|
|
PrivateAssemblyReferences = HashSetFromOptionalEnumerableStringParameter(InRules.PrivateAssemblyReferences);
|
|
}
|
|
|
|
// UEBuildModule interface.
|
|
public override List<FileItem> Compile(UEBuildTarget Target, UEToolChain ToolChain, CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment)
|
|
{
|
|
CPPEnvironment ModuleCLREnvironment = CompileEnvironment.DeepCopy();
|
|
|
|
// Setup the module environment for the project CLR mode
|
|
ModuleCLREnvironment.Config.CLRMode = CPPCLRMode.CLREnabled;
|
|
|
|
// Add the private assembly references to the compile environment.
|
|
foreach (string PrivateAssemblyReference in PrivateAssemblyReferences)
|
|
{
|
|
ModuleCLREnvironment.AddPrivateAssembly(PrivateAssemblyReference);
|
|
}
|
|
|
|
// Pass the CLR compilation environment to the standard C++ module compilation code.
|
|
return base.Compile(Target, ToolChain, GlobalCompileEnvironment, ModuleCLREnvironment);
|
|
}
|
|
|
|
public override void SetupPrivateLinkEnvironment(
|
|
UEBuildBinary SourceBinary,
|
|
LinkEnvironment LinkEnvironment,
|
|
List<UEBuildBinary> BinaryDependencies,
|
|
HashSet<UEBuildModule> VisitedModules
|
|
)
|
|
{
|
|
base.SetupPrivateLinkEnvironment(SourceBinary, LinkEnvironment, BinaryDependencies, VisitedModules);
|
|
|
|
// Setup the link environment for linking a CLR binary.
|
|
LinkEnvironment.Config.CLRMode = CPPCLRMode.CLREnabled;
|
|
}
|
|
}
|
|
|
|
public class UEBuildFramework
|
|
{
|
|
public UEBuildFramework(string InFrameworkName)
|
|
{
|
|
FrameworkName = InFrameworkName;
|
|
}
|
|
|
|
public UEBuildFramework(string InFrameworkName, string InFrameworkZipPath)
|
|
{
|
|
FrameworkName = InFrameworkName;
|
|
FrameworkZipPath = InFrameworkZipPath;
|
|
}
|
|
|
|
public UEBuildFramework(string InFrameworkName, string InFrameworkZipPath, string InCopyBundledAssets)
|
|
{
|
|
FrameworkName = InFrameworkName;
|
|
FrameworkZipPath = InFrameworkZipPath;
|
|
CopyBundledAssets = InCopyBundledAssets;
|
|
}
|
|
|
|
public UEBuildModule OwningModule = null;
|
|
public string FrameworkName = null;
|
|
public string FrameworkZipPath = null;
|
|
public string CopyBundledAssets = null;
|
|
}
|
|
|
|
public class UEBuildBundleResource
|
|
{
|
|
public UEBuildBundleResource(string InResourcePath, string InBundleContentsSubdir = "Resources", bool bInShouldLog = true)
|
|
{
|
|
ResourcePath = InResourcePath;
|
|
BundleContentsSubdir = InBundleContentsSubdir;
|
|
bShouldLog = bInShouldLog;
|
|
}
|
|
|
|
public string ResourcePath = null;
|
|
public string BundleContentsSubdir = null;
|
|
public bool bShouldLog = true;
|
|
}
|
|
|
|
public class PrecompileHeaderEnvironment
|
|
{
|
|
/// <summary>
|
|
/// The name of the module this PCH header is a member of
|
|
/// </summary>
|
|
public readonly string ModuleName;
|
|
|
|
/// <summary>
|
|
/// PCH header file name as it appears in an #include statement in source code (might include partial, or no relative path.)
|
|
/// This is needed by some compilers to use PCH features.
|
|
/// </summary>
|
|
public string PCHHeaderNameInCode;
|
|
|
|
/// <summary>
|
|
/// The source header file that this precompiled header will be generated for
|
|
/// </summary>
|
|
public readonly FileItem PrecompiledHeaderIncludeFilename;
|
|
|
|
/// <summary>
|
|
/// Whether this precompiled header will be built with CLR features enabled. We won't mix and match CLR PCHs with non-CLR PCHs
|
|
/// </summary>
|
|
public readonly CPPCLRMode CLRMode;
|
|
|
|
/// <summary>
|
|
/// Whether this precompiled header will be built with code optimization enabled.
|
|
/// </summary>
|
|
public readonly ModuleRules.CodeOptimization OptimizeCode;
|
|
|
|
/// <summary>
|
|
/// The PCH file we're generating
|
|
/// </summary>
|
|
public FileItem PrecompiledHeaderFile = null;
|
|
|
|
/// <summary>
|
|
/// Object files emitted from the compiler when generating this precompiled header. These will be linked into modules that
|
|
/// include this PCH
|
|
/// </summary>
|
|
public readonly List<FileItem> OutputObjectFiles = new List<FileItem>();
|
|
|
|
public PrecompileHeaderEnvironment(string InitModuleName, string InitPCHHeaderNameInCode, FileItem InitPrecompiledHeaderIncludeFilename, CPPCLRMode InitCLRMode, ModuleRules.CodeOptimization InitOptimizeCode)
|
|
{
|
|
ModuleName = InitModuleName;
|
|
PCHHeaderNameInCode = InitPCHHeaderNameInCode;
|
|
PrecompiledHeaderIncludeFilename = InitPrecompiledHeaderIncludeFilename;
|
|
CLRMode = InitCLRMode;
|
|
OptimizeCode = InitOptimizeCode;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a precompiled header action to generate a new pch file
|
|
/// </summary>
|
|
/// <param name="PCHHeaderNameInCode">The precompiled header name as it appeared in an #include statement</param>
|
|
/// <param name="PrecompiledHeaderIncludeFilename">Name of the header used for pch.</param>
|
|
/// <param name="ProjectCPPEnvironment">The environment the C/C++ files in the project are compiled with.</param>
|
|
/// <param name="OutputDirectory">The folder to save the generated PCH file to</param>
|
|
/// <param name="ModuleName">Name of the module this PCH is being generated for</param>
|
|
/// <param name="bAllowDLLExports">True if we should allow DLLEXPORT definitions for this PCH</param>
|
|
/// <returns>the compilation output result of the created pch.</returns>
|
|
public static CPPOutput GeneratePCHCreationAction(UEToolChain ToolChain, UEBuildTarget Target, string PCHHeaderNameInCode, FileItem PrecompiledHeaderIncludeFilename, CPPEnvironment ProjectCPPEnvironment, DirectoryReference OutputDirectory, DirectoryReference PCHOutputDirectory, string ModuleName, bool bAllowDLLExports)
|
|
{
|
|
// Find the header file to be precompiled. Don't skip external headers
|
|
if (PrecompiledHeaderIncludeFilename.bExists)
|
|
{
|
|
// Create a Dummy wrapper around the PCH to avoid problems with #pragma once on clang
|
|
string PCHGuardDefine = Path.GetFileNameWithoutExtension(PrecompiledHeaderIncludeFilename.AbsolutePath).ToUpperInvariant();
|
|
string LocalPCHHeaderNameInCode = ToolChain.ConvertPath(PrecompiledHeaderIncludeFilename.AbsolutePath);
|
|
string TmpPCHHeaderContents = String.Format("#ifndef __AUTO_{0}_H__\n#define __AUTO_{0}_H__\n//Last Write: {2}\n#include \"{1}\"\n#endif//__AUTO_{0}_H__", PCHGuardDefine, LocalPCHHeaderNameInCode, PrecompiledHeaderIncludeFilename.LastWriteTime);
|
|
FileReference DummyPath = FileReference.Combine(
|
|
ProjectCPPEnvironment.Config.OutputDirectory,
|
|
Path.GetFileName(PrecompiledHeaderIncludeFilename.AbsolutePath));
|
|
FileItem DummyPCH = FileItem.CreateIntermediateTextFile(DummyPath, TmpPCHHeaderContents);
|
|
|
|
// Create a new C++ environment that is used to create the PCH.
|
|
CPPEnvironment ProjectPCHEnvironment = ProjectCPPEnvironment.DeepCopy();
|
|
ProjectPCHEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.Create;
|
|
ProjectPCHEnvironment.Config.PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFilename.Reference;
|
|
ProjectPCHEnvironment.Config.PCHHeaderNameInCode = PCHHeaderNameInCode;
|
|
ProjectPCHEnvironment.Config.OutputDirectory = OutputDirectory;
|
|
ProjectPCHEnvironment.Config.PCHOutputDirectory = PCHOutputDirectory;
|
|
|
|
if (!bAllowDLLExports)
|
|
{
|
|
for (int CurDefinitionIndex = 0; CurDefinitionIndex < ProjectPCHEnvironment.Config.Definitions.Count; ++CurDefinitionIndex)
|
|
{
|
|
// We change DLLEXPORT to DLLIMPORT for "shared" PCH headers
|
|
string OldDefinition = ProjectPCHEnvironment.Config.Definitions[CurDefinitionIndex];
|
|
if (OldDefinition.EndsWith("=DLLEXPORT"))
|
|
{
|
|
ProjectPCHEnvironment.Config.Definitions[CurDefinitionIndex] = OldDefinition.Replace("DLLEXPORT", "DLLIMPORT");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cache our CPP environment so that we can check for outdatedness quickly. Only files that have includes need this.
|
|
DummyPCH.CachedCPPIncludeInfo = ProjectPCHEnvironment.Config.CPPIncludeInfo;
|
|
|
|
Log.TraceVerbose("Found PCH file \"{0}\".", PrecompiledHeaderIncludeFilename);
|
|
|
|
// Create the action to compile the PCH file.
|
|
return ToolChain.CompileCPPFiles(Target, ProjectPCHEnvironment, new List<FileItem>() { DummyPCH }, ModuleName);
|
|
}
|
|
throw new BuildException("Couldn't find PCH file \"{0}\".", PrecompiledHeaderIncludeFilename);
|
|
}
|
|
}
|
|
}
|