You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3175510 on 2016/10/26 by Josh.Adams - New Wolf SDK support (11). - Added new input plugin now that extra NDA is lifted Change 3176629 on 2016/10/27 by Josh.Adams Merging //UE4/Dev-Main to Dev-Platform (//UE4/Dev-Platform) Change 3177232 on 2016/10/27 by Josh.Adams - Minor comment change Change 3177348 on 2016/10/27 by Dmitry.Rekman Linux: default to GL4. Change 3177523 on 2016/10/27 by Dmitry.Rekman Linux: update libc++ to 3.9 and add AArch64. Change 3178208 on 2016/10/28 by Daniel.Lamb Enable multithreaded lightmap encoding. Change 3178273 on 2016/10/28 by Luke.Thatcher [PLATFORM] [PS4] [!] Fix crash in PS4 packaging step. - Parallel-for accessing the same log files, causing IOException. Change 3178573 on 2016/10/28 by Dmitry.Rekman Linux: fix for projects not having proper version associations (UE-5954). - Fixed by CengizT. Change3180487on 2016/10/31 by Josh.Adams Moved new file to peoper spot Change 3180508 on 2016/10/31 by Josh.Adams - Fixed crash on audio free for Wolf Change 3181821 on 2016/11/01 by Josh.Adams - Fixed ShooterGame cooking after sync from main Change 3182469 on 2016/11/01 by Josh.Adams - test/shipping build wolf fixes Change 3183078 on 2016/11/02 by Josh.Adams - Added AllDesktop back in for Windows (File | Package) Change 3183229 on 2016/11/02 by Josh.Adams - Fixed wrong path in JunkManifest.txt Change 3184245 on 2016/11/02 by Dmitry.Rekman Linux: add AArch64 (ARM64) libs. Change 3184326 on 2016/11/02 by Dmitry.Rekman Linux: add more files for AArch64. Change 3184353 on 2016/11/02 by Dmitry.Rekman Linux: Add missed AArch64 libpng. Change 3184871 on 2016/11/03 by Luke.Thatcher [PLATFORM] [PS4] [!] Fix broken DownloadImage blueprint node on PS4. - Node should return a UTexture2DDynamic, otherwise the RHI assumes the data has been pre-formatted for the GPU, and we get pitch/layout issues. #jira UE-36365 Change 3185407 on 2016/11/03 by Dmitry.Rekman Linux: fix PhysX on AArch64. (Edigrating 3184484 from Wombat to Dev-Platform). Change 3187488 on 2016/11/04 by Josh.Adams Copying //Tasks/UE4/Private-Platform-Switch to Dev-Platform-Minimal (//UE4/Dev-Platform-Minimal) Change 3187740 on 2016/11/04 by Josh.Adams - Re-copying the Switch files, now with proper case in the directory names Change 3188304 on 2016/11/07 by Dan.Mahashin - Removed deprecated functions in NVN window creation Change3188865on 2016/11/07 by Luke.Thatcher [PLATFORM] [PS4] [~] Move PS4 console input handler into engine classes from OrionGame. - Enables console input from Sony's "Console Output" tool for all games, in debug/development builds. #jira UE-37672 Change 3189517 on 2016/11/07 by Jeff.Campeau Fix incorrect local platform identification in device manager. #jira UE-38312 Change 3189897 on 2016/11/08 by Luke.Thatcher [PLATFORM] [!] Fix width/height mismatch in DownloadImage blueprint node. Change 3190042 on 2016/11/08 by Josh.Adams - Fixed default and Shooter App Ids for Switch Change 3190181 on 2016/11/08 by Joe.Barnes [UE-37275] Split reflection capture error message into two UE_LOG()s. Line length causes truncation and line wrap on some platforms. Change 3190185 on 2016/11/08 by Joe.Barnes Fix another instance of UE_LOG() where the string was being truncated on Switch platform. Change 3190272 on 2016/11/08 by Daniel.Lamb Add file hashes to depependency tracking info. Moved partial gc controlling code outside of the cooker. Store cooked file hashes in cooked asset registry. Cooked asset registry is now part of the cooker instead of chunking manifest. #test cook paragon Change 3190332 on 2016/11/08 by Omar.Rodriguez Fixing issues with iOS remote notifications * Update UPlatformGameInstance::FPlatformRegisteredForRemoteNotificationsDelegate signature so the parameter is const& which will work with BlueprintAssignable * Fix misspelling when doing respondsToSelector check * Update generated Xcode project to use the generated entitlements file * Add remote-notification as a background mode * Update the generated entitlements file contents to include APS environment for push notifications * Added bEnableRemoteNotificationsSupport ini parameter to control whether iOS push notifications code is compiled Change 3190391 on 2016/11/08 by Brent.Pease UE-31739 - Crash when Deploying to iPad Air with BC4 Texture Compression Setting (Josh's suggestion worked out of the box) Change 3190786 on 2016/11/08 by Bart.Hawthorne Fix some missing PLATFORM_WOLF changes to PLATFORM_SWITCH in ShooterGame Change 3190902 on 2016/11/08 by Alicia.Cano Allow RTTI and exceptions to be enabled for Android #jira UE-37845 #android Change 3190973 on 2016/11/08 by Chris.Babcock Add ability to set element value field with new text parameter for UPL #jira UE-37390 #PR #2869 #ue4 #upl Change 3191411 on 2016/11/09 by Josh.Stoddard Warn when user tries to use a shared pak reader on the wrong thread #jira UE-38049 Change 3191635 on 2016/11/09 by Josh.Stoddard More useful message during cook when AT9 assets fail to encode using SCE's tool #jira UE-38053 Change 3191663 on 2016/11/09 by Peter.Sauerbrei fix for ios build from PC Change 3191701 on 2016/11/09 by Brent.Pease implement iOS device logs on windows Change 3191794 on 2016/11/09 by Daniel.Lamb Fixed up compile error missing header file. #test Compile editor #jira UE-38414 Change 3191807 on 2016/11/09 by Josh.Adams - Fixed one chage that was missed in the WolfPlat->Switch rename Change 3191867 on 2016/11/09 by Josh.Adams - Enabled Switch for ShooterGame project Change 3191958 on 2016/11/09 by Jeff.Campeau Add warning for anyone still using XP Change 3192185 on 2016/11/09 by Josh.Adams - Updated to SDK 0.11.12 - Added TrackLotCheckItem API to track guidelines with limits (nothing using it yet) Change 3192241 on 2016/11/09 by Josh.Adams Merging //UE4/Dev-Main to Dev-Platform (//UE4/Dev-Platform) Change 3192324 on 2016/11/09 by Josh.Adams - Worked around an issue with RunOnTarget stripping quotes around paths with spaces #jira UE-38388 Change 3192387 on 2016/11/09 by Josh.Adams - Updating editor icon for Switch #jira UE-38295 Change 3192476 on 2016/11/09 by Dmitry.Rekman Linux: put correct OpenAL lib per architecture. (Edigrating CL 3185947 from Wombat to Dev-Platform) Change 3192527 on 2016/11/09 by Josh.Adams - Fixed a shadow variable warning #jira UE-38408 Change 3192606 on 2016/11/09 by Jeff.Campeau XP option removed #jira UEPLAT-1542 Change 3192644 on 2016/11/09 by Josh.Adams - Fixed a CIS error (not sure why I don't get it, but hey) Change 3192659 on 2016/11/09 by Josh.Adams - Fixed a crash in DeploymentServer Change 3192672 on 2016/11/09 by Jeff.Campeau Fix WinXP message spamming Change 3193252 on 2016/11/10 by Josh.Adams - Remove assertion in SwitchTextureFormat when the SDK can't be found (if you are sharing DLLs) Change 3193756 on 2016/11/10 by Dmitry.Rekman Linux: add support for touch events. (Edigrating CL 3188159 from Wombat to Dev-Platform). Change 3194297 on 2016/11/10 by Jeff.Campeau HarfBuzz implementation for Xbox One #jira UE-28590 Change 3194299 on 2016/11/10 by Jeff.Campeau Pump Xbox One messaging during slow startup tasks #jira UEPLAT-1276 Change 3194300 on 2016/11/10 by Jeff.Campeau Use response files when building for Xbox One #jira UEPLAT-1296 Change 3194313 on 2016/11/11 by Jeff.Campeau Stop uploading symbols on the first error Show a more detailed error message if symbol uploading fails Add a command line option to disable upload of symbols #1852 #jira UE-24425 Change 3194327 on 2016/11/11 by Jeff.Campeau Deduplicate Xbox One build.cs setup for several modules #jira UE-37540 Change 3194402 on 2016/11/11 by Dmitry.Rekman Linux: do not apply mouse workaround unnecessarily. - Only matters when there is more than one window. (Edigrating 3194399 from Wombat to Dev-Platform). Change 3194434 on 2016/11/11 by Dan.Mahashin - Ported fix CL 3193690: Add workaround to file I/O error about ResultInvalidCurrentMemory when reloading levels - remove uncached attribute during memory pool finalization Change 3194569 on 2016/11/11 by Daniel.Lamb Fixed issue with CreateLinker failing to return LinkerLoad but creating a UPackage which can't be cleaned up. Change 3194570 on 2016/11/11 by Daniel.Lamb Fix for DiffSerializeArchive not using the correct archive when saving packages. #test Cook paragon Change 3194571 on 2016/11/11 by Daniel.Lamb Make sure dependent packages are valid before using them. Added FastBuildCookRun bat file for paragon testing. #test Cook Paragon Change 3194575 on 2016/11/11 by Daniel.Lamb Reworked a warning for the cooker. Change 3194698 on 2016/11/11 by Daniel.Lamb Skip skin verify only runs on build machines now. Saves paragon cook time. Change 3194699 on 2016/11/11 by Daniel.Lamb Changed the wording of skip editor content setting so it's more clear. #test none Change 3194702 on 2016/11/11 by Daniel.Lamb Potential fix for default materials not being in chunk zero. #test run ps4 cooked build paragon Change3194711on 2016/11/11 by Alicia.Cano Allow RTTI and exceptions to be enabled for Android Allow RTTI to be enabled for IOS, Mac #jira UE-37845, UE-20314 #android #ios #mac Change 3194956 on 2016/11/11 by Josh.Adams - Removed the crash with unknown socket error code, left in the warning Change 3195028 on 2016/11/11 by Dmitry.Rekman Linux: repair launch on. (Edigrating 3194384 from //UE4/Private-Wombat/... to //UE4/Dev-Platform/...) Change 3195041 on 2016/11/11 by Dmitry.Rekman Linux: support selecting architectures per project. (Edigrating 3192783 from Wombat to Dev-Platform). Change 3195058 on 2016/11/11 by Dmitry.Rekman Linux: fix code to determine number of cores. - ARM topology seems not to be in line with the assumptions made by x86-centric code. (Merging 3184632 from Wombat to Dev-Platform). Change 3195082 on 2016/11/11 by Josh.Adams - Fixed name of packaged Switch builds to have the config in it (Shipping, etc) #jira UE-38394 Change 3195151 on 2016/11/11 by Bart.Hawthorne - Add game server settings to project settings to connect to the actual game server, instead of the debug login - Use the system software dialog box to show error codes for login failures Change 3195153 on 2016/11/11 by Josh.Adams - Fixed copy and paste logs errors Change 3195156 on 2016/11/11 by Josh.Adams - Fixed some default values, especially for save games (uses their default of 4MB size) - Added some LotCheck write tracking Change 3195285 on 2016/11/11 by Jeff.Campeau Fix HarfBuzz warning on Xbox One Change 3195477 on 2016/11/11 by Josh.Adams - Fixed up some IsGameOnly calls #jira UE-37575 Change 3195490 on 2016/11/11 by Dmitry.Rekman UAT: fix CIS (removed old variables). Change 3195724 on 2016/11/11 by Josh.Adams - Final fix for name of .nsp (content only projects in Shipping config, etc) #jira UE-38394 Change 3195755 on 2016/11/11 by Josh.Adams - Made translucent Switch icons Change 3195771 on 2016/11/11 by Josh.Adams - Fixed some Switch "space in path" issues #jira UE-38393 Change 3195801 on 2016/11/11 by Josh.Adams - Handle making sure the save is completed before we shutdown #jira UE-38215 Change 3196593 on 2016/11/14 by Michael.Trepka Implemented Info string in AvfMedia for display in Media Player Editor #jira UE-35386 Change 3196782 on 2016/11/14 by Josh.Adams - Added a comment for a workaround Change 3196784 on 2016/11/14 by Michael.Trepka Alembic importer for Mac #jira UE-37708 Change 3196901 on 2016/11/14 by Alicia.Cano ADB over wifi fails to deploy on Launch on. #jira UE-37957 #android Change 3197055 on 2016/11/14 by Josh.Adams - Fixed BinnedAllocator crash that happened with PoisonProxy and large allocations with large alignment Change 3197059 on 2016/11/14 by Josh.Adams - Removed some stat code with no STATS Change 3197066 on 2016/11/14 by Josh.Adams - Fixed the generic growableallocator to not free metadata before it's used for stats, and cleaned up a couple minor things Change 3197176 on 2016/11/14 by Josh.Adams - Added some helper scripts to switch in and out of debug mode on Switch Change 3197183 on 2016/11/14 by Bart.Hawthorne Error dialog fixes based on peer review feedback from JoshA Change 3197339 on 2016/11/14 by Josh.Adams Allow -htcs on the commandline now to override disabling Htcs in packaged builds Change 3197401 on 2016/11/14 by Josh.Adams - Fixed the Switch package installation script to remove the path of the package, since it causes problems with spaces, and also it makes the script less portable! #jira UE-38556 Change 3197691 on 2016/11/14 by Dmitry.Rekman Linux: save added devices. (Edigrating 3196529 from Wombat to Dev-Platform). Change 3197854 on 2016/11/15 by Dan.Mahashin - MemoryProfiler2: fixed Switch parser file path in the csproj Change 3197960 on 2016/11/15 by Dan.Mahashin - NVN RHITransitionResources() directly uses a barrier instead of relying on CopyToResolveTarget() side effect (UE-33834) Change 3198488 on 2016/11/15 by Bart.Hawthorne Submit missing NoRedist/DefaultEngine.ini file Change 3198970 on 2016/11/15 by Michael.Trepka Don't try to use installed Mono 4.6 on Mac as it's known to have issues on macOS 10.12 (for example building the editor with UBT often fails with Mono running out of file desriptors) Change 3199050 on 2016/11/15 by Daniel.Lamb Some more output to help track down iterative cooking scenarios #test Cook paragon Change 3199097 on 2016/11/15 by Josh.Adams - Fixed up Switch packaging to re-generate the meta data in case it changed since compile time (esp with content only projects - Fixed default Program Id in code - Fixed a problem with Run with a space in the path #jira UE-38608 Change 3199181 on 2016/11/15 by Dmitry.Rekman Fix CIS (compiling LinuxTargetDevice without engine). Change 3199253 on 2016/11/15 by Dmitry.Rekman Hopeful fix for a static analysis warning. Change 3199325 on 2016/11/15 by Joe.Barnes Start a new CommandBuffer immediately upon ending one. Prevents fetching when there's no CommandBuffer. Needed for Loading Screen movie playback. Change 3199814 on 2016/11/15 by Dmitry.Rekman Linux: remove forced -windowed when launching. (Merging CL 3199789 from Wombat to Dev-Platform) Change 3200580 on 2016/11/16 by Josh.Adams Updasted DeploymentServer Change 3200595 on 2016/11/16 by Joe.Barnes Removed inadvertent SleepThread() when starting movie playback. Change 3200604 on 2016/11/16 by Josh.Adams - Added NN_MIDDLEWARE macros to tag ths apps as using UE4 middleware Change 3200632 on 2016/11/16 by Brent.Pease Update PlatformShowcase with latest tests Change 3200704 on 2016/11/16 by Dmitry.Rekman Linux: fix native compilation. Change 3200711 on 2016/11/16 by Brent.Pease - Support ios audio streaming from disk - Flushed out ADPCMAudioInfo to be more flexible with buffer management in addition to support streaming from disk. This should make more code platform independent. + Other platforms should work fine but will need to be updated to use the new buffer flexability (and hence simplify their own code and buffer management) - IOS audio implementation simplified to use new ADPCMAudioInfo functionality - Fixed adpcm seamless looping NOTE: While everything works with my testing (admittedly simple tests) a little more code cleanup needs to happen... Change 3201015 on 2016/11/16 by Josh.Adams Merging //UE4/Dev-Main to Dev-Platform (//UE4/Dev-Platform) Change 3201023 on 2016/11/16 by Josh.Stoddard Fix splash screen assignment for iPad #jira UE-38623 Change 3201215 on 2016/11/16 by Brent.Pease Hopefully final fix for build breakage Change 3201259 on 2016/11/16 by Josh.Adams - Removed the clock rate settings from the Project Settings, and the cvars - it was just confusing - Further improved the metadata recreation during packaging (can get rid of the temp meta/desc files now I believe) - Reduced audio pool alignment to not waste massive memory from it Change3202332on 2016/11/17 by Daniel.Lamb Changed build scripts to support iterative cooking #test Ran new build scripts Change 3202371 on 2016/11/17 by Michael.Trepka Changed FAppleHttpResponse::GetContentLength to return expected content size instead of payload size so it's consistent with other implementations #jira UE-38392 Change 3202421 on 2016/11/17 by Michael.Trepka Decrease the number of max open files for a thread on Apple platforms from 256 to 192 to leave more file descriptors to Cocoa #jira UE-18343 Change 3202462 on 2016/11/17 by Michael.Trepka Fixed HTTP If-None-Match response code on Mac and iOS Fixed by iktomi, https://answers.unrealengine.com/questions/492514/http-if-none-match-logic-isnt-working-on-mac-due-t.html #jira UE-36317 Change 3202620 on 2016/11/17 by Daniel.Lamb Fixed issue with some objects being garbage collected which shouldn't be because the collection handler didn't get registered. Commandlets now do not always have GIsRequestingExit true. Made crash handler check for commandlets running and exit appropriately. #test Rebuild lighting QAGame Change 3202955 on 2016/11/17 by Daniel.Lamb Add support for clearing all the cached cooked platform data for a platform when requested. #test cook QA game #jira UE-38361 Change 3202983 on 2016/11/17 by Daniel.Lamb Added support to rebuild lightmaps commandlet for building lightmaps in seperate files. #test rebuild lighting Custom QAGame maps. #jira OR-31907 Change 3203128 on 2016/11/17 by Josh.Adams - Fixed split screen user selection in ShooterGame (brought over some changes from NickD for it as well) Change 3203537 on 2016/11/18 by Dmitry.Rekman Fix ProjectWorldToScreen node for letterboxed viewports. (Merging CL 3201546 from Wombat to Dev-Platform). Change 3203540 on 2016/11/18 by Dmitry.Rekman Linux: be more verbose when setting vblank sync. (Merging CL 3199633 from Private-Wombat to Dev-Platform). Change 3203599 on 2016/11/18 by Dmitry.Rekman Speedup bForceCompilationAtStartup=True when nothing changed (UE-37067). - PR #2849: Contributed by slonopotamus. Change 3203610 on 2016/11/18 by Dmitry.Rekman Add CEF support for Linux (UE-6743). Change 3203615 on 2016/11/18 by Dmitry.Rekman Linux: fix bootstrap script so it is independent of working dir (UE-37016). - PR #2842 contributed by slonopotamus Change 3203645 on 2016/11/18 by Dmitry.Rekman Linux: fix UnrealCEFSubProcess. Change 3203658 on 2016/11/18 by Dmitry.Rekman Remove hard-coded paths to mono binary (UE-35228). - Another way to implement pull request #2741. Change 3203770 on 2016/11/18 by Josh.Adams - Brought over some changes from Dev-Core to not crash in AsyncLoading with debug code Change 3204244 on 2016/11/18 by Dmitry.Rekman Unsuppress mistakenly suppressed warnings and fix one more (UE-38788). Change 3204277 on 2016/11/18 by Brent.Pease + Fix seamless looping bug found on Dan's QAGame test + Fix static analyzer warning (which was a real bug with uncompressed streaming) + Code review feedback from Aaron + Small addition from channel sync ios bug fix Change 3204576 on 2016/11/18 by Omar.Rodriguez Expose the bEnableRemoteNotificationsSupport ini setting in the iOS project settings. Change 3204629 on 2016/11/18 by Chris.Babcock Fix case of VulkanSwapChain.h #include #jira UE-38843 #ue4 #vulkan Change 3204708 on 2016/11/18 by Josh.Adams - Set SwitchMoviePlayer to include the libs from the proper directory Change 3204730 on 2016/11/18 by Josh.Adams - Changed a check to a checkf to narrow down why FMaterialUniformExpressionType::GetTypeMap().FindRef(TypeName) is returning nullptr on tvOS Change 3204865 on 2016/11/18 by Brent.Pease + Turn off ios console logs on Windows to help sort through ios packaging and launch-on issues - This is NOT a fix but it should make it easier to track down the problem with it off. Change 3204883 on 2016/11/18 by Dmitry.Rekman Linux: fix native LaunchOn (UE-38616). Change 3204914 on 2016/11/18 by Brent.Pease + Turn off the device check to prevent it from conflicting with remote packaging/launch-on Change 3204940 on 2016/11/18 by Josh.Adams Backing out changes to the profiler for Switch. Shouldn't have checked it in today during smoke Change 3204952 on 2016/11/18 by Dmitry.Rekman Linux: fix bootstrap script (UE-38851). - Caused by UE-37016. Change 3205630 on 2016/11/21 by Brent.Pease + Fix audio sound queuing bug by ensuring audio buffers are not reused by different sound source objects. + Cleaned up the locking mechanism around stopping sound sources to make its intent and function are clear + Cleaned up memory tracking and freeing. #jira ue-38846 Change 3205787 on 2016/11/21 by Josh.Adams Merging //UE4/Dev-Main to Dev-Platform (//UE4/Dev-Platform) [CL 3206922 by Josh Adams in Main branch]
2046 lines
86 KiB
C#
2046 lines
86 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;
|
|
}
|
|
|
|
if (bModuleUsesUnityBuild)
|
|
{
|
|
LinkInputFiles.AddRange(CompileUnityFilesWithToolChain(ToolChain, Target, CPPCompileEnvironment, CPPFilesToBuild, Name).ObjectFiles);
|
|
}
|
|
else
|
|
{
|
|
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(CompileUnityFilesWithToolChain(ToolChain, Target, CPPCompileEnvironment, CPPFilesToCompile, Name).ObjectFiles);
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compiles the provided CPP unity files. Will
|
|
/// </summary>
|
|
private CPPOutput CompileUnityFilesWithToolChain(UEToolChain ToolChain, UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
|
|
{
|
|
List<FileItem> NormalFiles = new List<FileItem>();
|
|
List<FileItem> AdaptiveFiles = new List<FileItem>();
|
|
|
|
if (BuildConfiguration.bAdaptiveUnityDisablesOptimizations && !BuildConfiguration.bStressTestUnity)
|
|
{
|
|
foreach (FileItem File in SourceFiles)
|
|
{
|
|
// Basic check as to whether something in this module is/isn't a unity file...
|
|
if (File.ToString().StartsWith(Unity.ModulePrefix))
|
|
{
|
|
NormalFiles.Add(File);
|
|
}
|
|
else
|
|
{
|
|
AdaptiveFiles.Add(File);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NormalFiles.AddRange(SourceFiles);
|
|
}
|
|
|
|
CPPOutput OutputFiles = new CPPOutput();
|
|
|
|
if (NormalFiles.Count > 0)
|
|
{
|
|
OutputFiles = ToolChain.CompileCPPFiles(Target, CompileEnvironment, NormalFiles, Name);
|
|
}
|
|
|
|
if (AdaptiveFiles.Count > 0)
|
|
{
|
|
// Create an unoptmized compilation environment. Need to turn of PCH due to different
|
|
// compiler settings
|
|
CPPEnvironment UnoptimziedEnvironment = CompileEnvironment.DeepCopy();
|
|
UnoptimziedEnvironment.Config.OptimizeCode = ModuleRules.CodeOptimization.Never;
|
|
UnoptimziedEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.None;
|
|
|
|
// Compile the files
|
|
CPPOutput AdaptiveOutput = ToolChain.CompileCPPFiles(Target, UnoptimziedEnvironment, AdaptiveFiles, Name);
|
|
|
|
// Merge output
|
|
OutputFiles.ObjectFiles.AddRange(AdaptiveOutput.ObjectFiles);
|
|
OutputFiles.DebugDataFiles.AddRange(AdaptiveOutput.DebugDataFiles);
|
|
}
|
|
|
|
return OutputFiles;
|
|
}
|
|
|
|
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 || UEBuildConfiguration.bForceEnableRTTI;
|
|
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);
|
|
}
|
|
}
|
|
}
|