LiveCoding

LiveCoding

#Overview

name: LiveCoding

This variable is created as a Console Variable (cvar).

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:

  1. LiveUpdateForSlate plugin
  2. HotReload module
  3. GameProjectGeneration module
  4. LevelEditor module
  5. 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:

Developers should be aware of the following when using LiveCoding:

  1. It cannot be enabled while hot-reloaded modules are active.
  2. It may require closing the editor and rebuilding from an IDE in certain situations.
  3. It can automatically compile new classes if configured to do so.

Best practices for using LiveCoding include:

  1. Enable it at the start of a development session to avoid conflicts with hot-reload.
  2. Use it in conjunction with the LiveCoding console for better visibility into the compilation process.
  3. Be prepared to close the editor and rebuild from an IDE if LiveCoding encounters issues or cannot be enabled.
  4. Consider the performance impact of frequent compilations, especially in larger projects.
  5. 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);