You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Allows fast iteration of C++ changes without restarting the application. To use, select the "Live Coding (Experimental)" mode from the drop down menu next to the editor's compile button, or type "LiveCoding" into the console for a monolithic build. Press Ctrl+Alt+F11 to find changes and compile.
Changes vs standalone Live++ version:
* UBT is used to execute builds. This allows standard UE4 adaptive unity mode, allows us to reuse object files when we do regular builds, supports using any build executor allowed by UBT (XGE, SNDBS, etc..).
* Adding new source files is supported.
* Custom visualizer for FNames is supported via a weakly linked symbol in a static library (Engine/Extras/NatvisHelpers).
* Settings are exposed in the editor's project settings dialog.
* Standalone application has been rewritten as a Slate app ("LiveCodingConsole"). There is an additional option to start the program as hidden, where it will not be visible until Ctrl+Alt+F11 is hit. Similarly, closing the window will hide it instead of closing the application.
* Does not require a standalone licensed version of Live++.
Known issues:
* Does not currently support class layout changes / object reinstancing
#rb none
#fyi Marc.Audy, Stefan.Boberg, Nick.Penwarden
#jira
[CL 5304722 by Ben Marsh in 4.22 branch]
138 lines
4.3 KiB
C++
138 lines
4.3 KiB
C++
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreTypes.h"
|
|
#include "LC_CoffCache.h"
|
|
#include "LC_ModuleCache.h"
|
|
#include "LC_Symbols.h"
|
|
#include "LC_Process.h"
|
|
#include "LC_Commands.h"
|
|
#include "LC_Executable.h"
|
|
#include "LC_Semaphore.h"
|
|
#include "LC_RunMode.h"
|
|
|
|
|
|
class DuplexPipe;
|
|
class FileAttributeCache;
|
|
class DirectoryCache;
|
|
class ModulePatch;
|
|
class LiveProcess;
|
|
|
|
class LiveModule
|
|
{
|
|
public:
|
|
struct PerProcessData
|
|
{
|
|
LiveProcess* liveProcess;
|
|
void* originalModuleBase;
|
|
std::wstring modulePath;
|
|
};
|
|
|
|
struct ErrorType
|
|
{
|
|
enum Enum
|
|
{
|
|
NO_CHANGE,
|
|
COMPILE_ERROR,
|
|
LINK_ERROR,
|
|
LOAD_PATCH_ERROR,
|
|
ACTIVATE_PATCH_ERROR,
|
|
SUCCESS
|
|
};
|
|
};
|
|
|
|
struct UpdateType
|
|
{
|
|
enum Enum
|
|
{
|
|
DEFAULT,
|
|
NO_CLIENT_COMMUNICATION
|
|
};
|
|
};
|
|
|
|
struct CompileResult
|
|
{
|
|
unsigned int exitCode;
|
|
bool wasCompiled;
|
|
};
|
|
|
|
LiveModule(const wchar_t* moduleName, const executable::Header& imageHeader, RunMode::Enum runMode);
|
|
~LiveModule(void);
|
|
|
|
void Load(symbols::Provider* provider, symbols::DiaCompilandDB* diaCompilandDb);
|
|
|
|
// unloads all patches that have been loaded into all processes so far
|
|
void Unload(void);
|
|
|
|
void RegisterProcess(LiveProcess* liveProcess, void* moduleBase, const std::wstring& modulePath);
|
|
void UnregisterProcess(LiveProcess* liveProcess);
|
|
|
|
void DisableControlFlowGuard(LiveProcess* liveProcess, void* moduleBase);
|
|
|
|
void UpdateDirectoryCache(DirectoryCache* cache);
|
|
|
|
// builds a patch for this module according to changed files.
|
|
// in DEFAULT mode, this checks for file modifications, compiles files automatically, builds a patch containing changes, and loads them into the host application.
|
|
// in EXTERNAL_BUILD_SYSTEM mode, this does not compile files but builds a patch containing modified .objs, loading the patch into the host application.
|
|
// optionally, an array of modified or new .objs can be given in this mode, which builds a patch containing these files, not checking for any other modifications.
|
|
ErrorType::Enum Update(FileAttributeCache* fileCache, DirectoryCache* directoryCache, UpdateType::Enum updateType, const std::vector<std::wstring>& modifiedOrNewObjFiles);
|
|
bool InstallCompiledPatches(LiveProcess* liveProcess, void* originalModuleBase);
|
|
|
|
const std::wstring& GetModuleName(void) const;
|
|
const executable::Header& GetImageHeader(void) const;
|
|
|
|
const symbols::CompilandDB* GetCompilandDatabase(void) const;
|
|
const symbols::LinkerDB* GetLinkerDatabase(void) const;
|
|
|
|
bool HasInstalledPatches(void) const;
|
|
|
|
private:
|
|
void UpdateDirectoryCache(const ImmutableString& path, symbols::Dependency* dependency, DirectoryCache* cache);
|
|
|
|
void OnCompiledFile(const symbols::ObjPath& objPath, symbols::Compiland* compiland, const CompileResult& compileResult, double compileTime, bool forceAmalgamationPartsLinkage);
|
|
|
|
// actions
|
|
struct LoadPatchInfoAction
|
|
{
|
|
typedef commands::LoadPatchInfo CommandType;
|
|
static bool Execute(CommandType* command, const DuplexPipe* pipe, void* context);
|
|
};
|
|
|
|
std::wstring m_moduleName;
|
|
executable::Header m_imageHeader;
|
|
RunMode::Enum m_runMode;
|
|
size_t m_mainModuleToken = 0u;
|
|
|
|
// data that stores which processes loaded this module at which address originally
|
|
types::vector<PerProcessData> m_perProcessData;
|
|
|
|
// caches
|
|
CoffCache<coff::CoffDB>* m_coffCache = nullptr;
|
|
ModuleCache* m_moduleCache = nullptr;
|
|
types::StringSet m_reconstructedCompilands;
|
|
|
|
// main databases
|
|
symbols::SymbolDB* m_symbolDB = nullptr;
|
|
symbols::ContributionDB* m_contributionDB = nullptr;
|
|
symbols::CompilandDB* m_compilandDB = nullptr;
|
|
symbols::LibraryDB* m_libraryDB = nullptr;
|
|
symbols::LinkerDB* m_linkerDB = nullptr;
|
|
symbols::ThunkDB* m_thunkDB = nullptr;
|
|
symbols::ImageSectionDB* m_imageSectionDB = nullptr;
|
|
types::StringMap<types::vector<const symbols::Symbol*>> m_externalSymbolsPerCompilandCache;
|
|
types::StringMap<ImmutableString> m_pchSymbolToCompilandName;
|
|
types::vector<ImmutableString> m_weakSymbolsInLibs;
|
|
|
|
// patch data
|
|
types::unordered_map<unsigned int, types::unordered_set<const void*>> m_patchedAddressesPerProcess;
|
|
unsigned int m_patchCounter = 0u;
|
|
|
|
// data pertaining to the next patch
|
|
types::StringSet m_modifiedFiles;
|
|
types::StringMap<symbols::Compiland*> m_compiledCompilands;
|
|
|
|
// all patches loaded so far along with recorded data how to load them into other processes
|
|
types::vector<ModulePatch*> m_compiledModulePatches;
|
|
};
|