LiveCoding
LiveCoding
#Overview
name: LiveCoding
This variable is created as a Console Variable (cvar).
- type:
Cmd
- help:
Enables live coding support
It is referenced in 19
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of LiveCoding is to enable real-time code compilation and reloading in Unreal Engine 5, allowing developers to make changes to C++ code without needing to restart the editor or rebuild the entire project.
LiveCoding is primarily used by the editor and development tools within Unreal Engine. Based on the callsites, it’s utilized by several subsystems and modules, including:
- LiveUpdateForSlate plugin
- HotReload module
- GameProjectGeneration module
- LevelEditor module
- PackFactory
The value of this variable is set through the LiveCoding module, which can be enabled or disabled for a session. It’s typically controlled via console commands or editor UI actions.
Several other variables interact with LiveCoding, such as:
- GIsCompileActive
- GTriggerReload
- GHasLoadedPatch
- GPostCompileResult
Developers should be aware of the following when using LiveCoding:
- It cannot be enabled while hot-reloaded modules are active.
- It may require closing the editor and rebuilding from an IDE in certain situations.
- It can automatically compile new classes if configured to do so.
Best practices for using LiveCoding include:
- Enable it at the start of a development session to avoid conflicts with hot-reload.
- Use it in conjunction with the LiveCoding console for better visibility into the compilation process.
- Be prepared to close the editor and rebuild from an IDE if LiveCoding encounters issues or cannot be enabled.
- Consider the performance impact of frequent compilations, especially in larger projects.
- Use the provided API methods (like IsEnabledForSession(), Compile(), etc.) to interact with LiveCoding programmatically when needed.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Editor/LiveUpdateForSlate/Source/LiveUpdateForSlate/Private/LiveUpdateForSlate.cpp:29
Scope (from outer to inner):
file
function void FLiveUpdateForSlateModule::StartupModule
Source code excerpt:
#if WITH_LIVE_CODING
if (ILiveCodingModule* LiveCoding = FModuleManager::LoadModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME))
{
OnPatchCompleteHandle = LiveCoding->GetOnPatchCompleteDelegate().AddRaw(this, &FLiveUpdateForSlateModule::OnPatchComplete);
}
#endif
}
void FLiveUpdateForSlateModule::ShutdownModule()
{
#Loc: <Workspace>/Engine/Plugins/Editor/LiveUpdateForSlate/Source/LiveUpdateForSlate/Private/LiveUpdateForSlate.cpp:44
Scope (from outer to inner):
file
function void FLiveUpdateForSlateModule::ShutdownModule
Source code excerpt:
#if WITH_LIVE_CODING
if (ILiveCodingModule* LiveCoding = FModuleManager::LoadModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME))
{
LiveCoding->GetOnPatchCompleteDelegate().Remove(OnPatchCompleteHandle);
}
#endif
}
void FLiveUpdateForSlateModule::OnPatchComplete()
{
#Loc: <Workspace>/Engine/Source/Developer/HotReload/Private/HotReload.cpp:634
Scope (from outer to inner):
file
function bool FHotReloadModule::RecompileModule
Source code excerpt:
#if WITH_LIVE_CODING
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledForSession())
{
UE_LOG(LogHotReload, Error, TEXT("Unable to hot-reload modules while Live Coding is enabled."));
return false;
}
#endif
#Loc: <Workspace>/Engine/Source/Developer/HotReload/Private/HotReload.cpp:1240
Scope (from outer to inner):
file
function bool FHotReloadModule::Tick
Source code excerpt:
// Early out if live coding is enabled
#if WITH_LIVE_CODING
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledForSession())
{
return false;
}
#endif
#if WITH_EDITOR
#Loc: <Workspace>/Engine/Source/Developer/Windows/LiveCoding/Private/LiveCodingModule.cpp:42
Scope: file
Source code excerpt:
#include <subauth.h> // for UNICODE_STRING
IMPLEMENT_MODULE(FLiveCodingModule, LiveCoding)
#define LOCTEXT_NAMESPACE "LiveCodingModule"
LLM_DEFINE_TAG(LiveCoding);
bool GIsCompileActive = false;
bool GTriggerReload = false;
bool GHasLoadedPatch = false;
commands::PostCompileResult GPostCompileResult = commands::PostCompileResult::Success;
FString GLiveCodingConsolePath;
#Loc: <Workspace>/Engine/Source/Developer/Windows/LiveCoding/Private/LiveCodingModule.cpp:68
Scope (from outer to inner):
file
class class FNullReload : public IReload
function FNullReload
Source code excerpt:
: LiveCodingModule(InLiveCodingModule)
{
BeginReload(EActiveReloadType::LiveCoding, *this);
}
~FNullReload()
{
EndReload();
}
#Loc: <Workspace>/Engine/Source/Developer/Windows/LiveCoding/Private/LiveCodingModule.cpp:78
Scope (from outer to inner):
file
class class FNullReload : public IReload
function virtual EActiveReloadType GetType
Source code excerpt:
virtual EActiveReloadType GetType() const
{
return EActiveReloadType::LiveCoding;
}
virtual const TCHAR* GetPrefix() const
{
return TEXT("LIVECODING");
#Loc: <Workspace>/Engine/Source/Developer/Windows/LiveCoding/Private/LiveCodingModule.cpp:333
Scope (from outer to inner):
file
function void FLiveCodingModule::StartupModule
Source code excerpt:
void FLiveCodingModule::StartupModule()
{
LLM_SCOPE_BYTAG(LiveCoding);
// Register with NT to get dll nitrifications
FNtDllFunction RegisterFunc("LdrRegisterDllNotification");
RegisterFunc(0, OnDllNotification, this, &CallbackCookie);
// Get the creating process main executable name. We want to skip this file when iterating through the dll list
#Loc: <Workspace>/Engine/Source/Developer/Windows/LiveCoding/Private/LiveCodingModule.cpp:410
Scope (from outer to inner):
file
function void FLiveCodingModule::StartupModule
Source code excerpt:
EnableCommand = ConsoleManager.RegisterConsoleCommand(
TEXT("LiveCoding"),
TEXT("Enables live coding support"),
FConsoleCommandWithOutputDeviceDelegate::CreateRaw(this, &FLiveCodingModule::EnableConsoleCommand),
ECVF_Cheat
);
CompileCommand = ConsoleManager.RegisterConsoleCommand(
TEXT("LiveCoding.Compile"),
TEXT("Initiates a live coding compile"),
FConsoleCommandDelegate::CreateLambda([this] { Compile(ELiveCodingCompileFlags::None, nullptr); }),
ECVF_Cheat
);
#Loc: <Workspace>/Engine/Source/Developer/Windows/LiveCoding/Private/LiveCodingModule.cpp:1431
Scope (from outer to inner):
file
function void FLiveCodingModule::BeginReload
Source code excerpt:
GPostCompileResult = commands::PostCompileResult::Success;
#if WITH_EDITOR
GLiveCodingModule->Reload.Reset(new FReload(EActiveReloadType::LiveCoding, TEXT("LIVECODING"), *GLog));
GLiveCodingModule->Reload->SetEnableReinstancing(GLiveCodingModule->IsReinstancingEnabled());
GLiveCodingModule->Reload->SetSendReloadCompleteNotification(false);
#else
GLiveCodingModule->Reload.Reset(new FNullReload(*GLiveCodingModule));
#endif
}
#Loc: <Workspace>/Engine/Source/Developer/Windows/LiveCodingServer/Private/External/LC_LiveProcess.cpp:293
Scope (from outer to inner):
file
function void LiveProcess::Restart
Source code excerpt:
{
// restart the target application
// BEGIN EPIC MOD - Force LiveCoding to start up for child processes
std::wstring commandLine(m_commandLine);
const std::wstring argument(L" -LiveCoding");
if (commandLine.length() >= argument.length() && commandLine.compare(commandLine.length() - argument.length(), argument.length(), argument) != 0)
{
commandLine += argument;
#Loc: <Workspace>/Engine/Source/Editor/GameProjectGeneration/Private/GameProjectUtils.cpp:4108
Scope (from outer to inner):
file
function GameProjectUtils::EAddCodeToProjectResult GameProjectUtils::AddCodeToProject_Internal
Source code excerpt:
#if WITH_LIVE_CODING
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledForSession())
{
if (!bProjectHadCodeFiles)
{
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("LiveCodingNoSources", "Project now includes sources, please close the editor and build from your IDE."));
return EAddCodeToProjectResult::Succeeded;
}
if (LiveCoding->AutomaticallyCompileNewClasses())
{
LiveCoding->Compile(ELiveCodingCompileFlags::None, nullptr);
OutReloadStatus = EReloadStatus::Reloaded;
}
return EAddCodeToProjectResult::Succeeded;
}
#endif
#Loc: <Workspace>/Engine/Source/Editor/LevelEditor/Private/LevelEditorActions.cpp:1199
Scope (from outer to inner):
file
function void FLevelEditorActionCallbacks::RecompileGameCode_Clicked
Source code excerpt:
{
#if WITH_LIVE_CODING
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledByDefault())
{
LiveCoding->EnableForSession(true);
if (LiveCoding->IsEnabledForSession())
{
LiveCoding->Compile();
}
else
{
FText EnableErrorText = LiveCoding->GetEnableErrorText();
if (EnableErrorText.IsEmpty())
{
EnableErrorText = LOCTEXT("NoLiveCodingCompileAfterHotReload", "Live Coding cannot be enabled while hot-reloaded modules are active. Please close the editor and build from your IDE before restarting.");
}
FMessageDialog::Open(EAppMsgType::Ok, EnableErrorText);
}
#Loc: <Workspace>/Engine/Source/Editor/LevelEditor/Private/LevelEditorActions.cpp:1232
Scope (from outer to inner):
file
function bool FLevelEditorActionCallbacks::Recompile_CanExecute
Source code excerpt:
{
#if WITH_LIVE_CODING
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledByDefault())
{
return !LiveCoding->IsCompiling();
}
#endif
// We can't recompile while in PIE
if (GEditor->IsPlaySessionInProgress())
{
#Loc: <Workspace>/Engine/Source/Editor/LevelEditor/Private/LevelEditorActions.cpp:1254
Scope (from outer to inner):
file
function void FLevelEditorActionCallbacks::LiveCoding_ToggleEnabled
Source code excerpt:
void FLevelEditorActionCallbacks::LiveCoding_ToggleEnabled()
{
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr)
{
LiveCoding->EnableByDefault(!LiveCoding->IsEnabledByDefault());
if (LiveCoding->IsEnabledByDefault() && !LiveCoding->IsEnabledForSession())
{
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("NoEnableLiveCodingAfterHotReload", "Live Coding cannot be enabled while hot-reloaded modules are active. Please close the editor and build from your IDE before restarting."));
}
}
}
bool FLevelEditorActionCallbacks::LiveCoding_IsEnabled( )
{
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
return LiveCoding != nullptr && LiveCoding->IsEnabledByDefault();
}
void FLevelEditorActionCallbacks::LiveCoding_StartSession_Clicked()
{
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr)
{
LiveCoding->EnableForSession(true);
if (!LiveCoding->IsEnabledForSession())
{
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("NoStartedLiveCodingAfterHotReload", "Live Coding cannot be started after hot-reload has been used. Please close the editor and build from your IDE before restarting."));
}
}
}
bool FLevelEditorActionCallbacks::LiveCoding_CanStartSession()
{
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
return LiveCoding != nullptr && LiveCoding->IsEnabledByDefault() && !LiveCoding->HasStarted();
}
void FLevelEditorActionCallbacks::LiveCoding_ShowConsole_Clicked()
{
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding!= nullptr)
{
LiveCoding->ShowConsole();
}
}
bool FLevelEditorActionCallbacks::LiveCoding_CanShowConsole()
{
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
return LiveCoding!= nullptr && LiveCoding->IsEnabledForSession();
}
void FLevelEditorActionCallbacks::LiveCoding_Settings_Clicked()
{
FModuleManager::LoadModuleChecked<ISettingsModule>("Settings").ShowViewer("Editor", "General", "Live Coding");
}
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Factories/PackFactory.cpp:734
Scope (from outer to inner):
file
function UObject* UPackFactory::FactoryCreateBinary
Source code excerpt:
if (bCompileSource)
{
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledForSession())
{
if (bProjectHadSourceFiles)
{
if (!LiveCoding->Compile(ELiveCodingCompileFlags::WaitForCompletion, nullptr))
{
FMessageDialog::Open(EAppMsgType::Ok, NSLOCTEXT("PackFactory", "LiveCodingFailedToCompile", "Failed to compile sources, please close the editor and build from your IDE."));
}
}
else
{
#Loc: <Workspace>/Engine/Source/Runtime/Core/Public/Modules/ModuleManager.h:1025
Scope: file
Source code excerpt:
#endif
#if WITH_LIVE_CODING
LiveCoding,
#endif
};
class IReload;
#if WITH_RELOAD
#Loc: <Workspace>/Projects/Lyra/Plugins/Developer/RiderLink/Source/RiderLC/Private/RiderLC.cpp:27
Scope (from outer to inner):
file
lambda-function
lambda-function
lambda-function
Source code excerpt:
{
#if WITH_LIVE_CODING
ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledByDefault())
{
LiveCoding->EnableForSession(true);
if (LiveCoding->IsEnabledForSession())
{
LiveCoding->Compile();
}
}
else
#endif
{
#if WITH_HOT_RELOAD
#Loc: <Workspace>/Projects/Lyra/Plugins/Developer/RiderLink/Source/RiderLC/Private/RiderLC.cpp:57
Scope (from outer to inner):
file
function bool FRiderLCModule::Tick
Source code excerpt:
bool bIsCompiling = false;
#if WITH_LIVE_CODING
const ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
if (LiveCoding != nullptr && LiveCoding->IsEnabledByDefault())
{
bIsAvailable = true;
bIsCompiling = LiveCoding->IsCompiling();
}
else
#endif
{
#if WITH_HOT_RELOAD
const IHotReloadInterface* HotReload = FModuleManager::GetModulePtr<IHotReloadInterface>(HotReloadModule);