AHotCodeReload#
Hot code reload and rapid development
Header: | #include <AUI/Remote/AHotCodeReload.h> |
CMake: | aui_link(my_target PUBLIC aui::remote_tools) |
Detailed Description#
The development workflow for UI applications can be repetitive and slow, commonly requiring you to:
- Write or modify code.
- Compile.
- Run the application.
- Navigate to the affected UI or feature.
- Check for expected results.
- Repeat as needed.
Steps 2-5
are very slow and exhausting. This page briefly describes ways to reduce turnaround time during
development of your application.
Precompiled Headers#
Precompiled headers (PCH) can significantly speed up C++ compilation by parsing common headers only once. They are especially beneficial for large projects with many dependencies.
How to use precompiled headers with CMake:
- Create a header file (e.g.
pch.h
) containing your frequently used includes:
#include <AUI/Platform/AWindow.h>
#include <AUI/Util/UIBuildingHelpers.h>
// Add other common headers here
- In your
CMakeLists.txt
:
# CMake 3.16 or newer recommended for target_precompile_headers
add_library(my_target ...)
target_precompile_headers(my_target PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/pch.h")
Make sure all source files include pch.h
(either directly or via your main header). For more complex setups, review
CMake’s documentation on precompiled headers.
The AHotCodeReload Class#
AHotCodeReload
enables runtime reloading of object files, injecting new function code into a live application.
This gives rapid feedback and reduces iteration time during development.

Platform | Supported |
---|---|
Windows | No |
Linux | Yes |
macOS | No |
Android | No |
iOS | No |
It works by observing changes on object files, which are generated by compiler and picked up by linker. AHotCodeReload implements its own linker designed specifically to load these intermediate build files and link them against a program which is already running. Then, it scans for newly loaded functions and places hooks on old versions of these functions, so the newer version is called.
Unlike classic way of implementing hot code reload with dynamic libraries, approach implemented in AUI does not interfere with build process nor require special project structure with complicated state management. It does not replace older symbols with newer ones, it keeps them both in memory, so referencing both is safe.
Setup#
Link to remote_tools module: aui_link(my_target PUBLIC aui::remote_tools)
Add object files to track:
|
|
Observe AHotCodeReload::inst().patchEnd
to re-call patched functions to see the effect. For UI, extract
setContents
call to a member function and call it in constructor. Also, connect to
AHotCodeReload::inst().patchEnd
to re-initialize UI components after the patch. Use __has_include
to check if
aui::remote_tools
was added in your CMakeLists.txt
.
|
Usage#
- Launch your application.
- Edit your source code.
- Compile. (You may skip the linking step.). In IDEs, it can be accomplished by shortcuts. CLion: Ctrl+9.
- Wait for patching to complete.
- Repeat steps 2–4 as needed.
Limitations#
AHotCodeReload
performs some safety checks, but a patch could still break your application.- Only functions are hooked. New function versions will reflect changes to certain variables (see below)
- For changes to become effective, the patched functions need to be called (e.g. by re-triggering relevant UI
actions or re-calling UI inflate routines
setContents
). See setup. - Do not modify struct or class layouts, function signatures; the system cannot reliably detect or adjust for such changes.
What will change (in the new version of function)
- function logic
static
/thread_local
/global constants, literals ("string literals"
,123
,true
,nullptr
)static
/thread_local
/global non-constant variables initialized with zeroes, which will be reinitialized with zeroes at the time of patch, i.e.,static int counter = 0;
will reset to zero. (because those are stored in.bss
which linker has to create a new instance of)
Think of it this way: when you update the source code of a function, these changes will be reflected in the new version of the function and take effect the next time that function is called. The modification is as direct as changing the text of the function itself.
What will not change
static
/thread_local
/global non-constant variables initialized with non-zero values, which will use the values prior patch.static int counter = 1;
will not be reset to1
- any values that were allocated on the heap or stack, including class fields. Exploit this to preserve state of your application
Best Practices#
- Use hot code reloading for iterative development on function logic and UI changes.
- Do not rely on this system for data or memory layout changes.
- Consider combining hot reload with precompiled headers to further minimize turnaround time.
Public fields and Signals#
patchBegin#
emits<> patchBegin
Signal emitted when a binary patch operation begins.
This signal is emitted before the hot code reload system starts patching the application with new code. Can be used to prepare the application state for the upcoming changes.
patchEnd#
emits<> patchEnd
Signal emitted when a binary patch operation completes.
This signal is emitted after the hot code reload system has finished patching the application. Can be used to refresh UI or reinitialize components after the changes have been applied.
Public Methods#
addFile#
void AHotCodeReload::addFile(AString path)
Add a single object file to be observed.
- Arguments
path
Path to the object file to watch for changes.
Adds a single object file to the hot code reload system's watch list. When changes are detected in this file, it will be automatically reloaded.
This method will log errors if file watching fails rather than throwing exceptions.
addFiles#
void AHotCodeReload::addFiles(AStringView paths)
Add object files to be observed.
- Arguments
paths
paths to object files. Multiple paths can be specified by separating them with a semicolon.
Object files are generated by the compiler and picked up by the linker.
Example:
Normally, you do not need to call this method directly. It is called automatically by aui_enable_hotswap
CMake
command.
inst#
Gets the singleton instance of AHotCodeReload.
- Returns
- Reference to the singleton instance.
This method implements the singleton pattern, ensuring only one instance of AHotCodeReload exists. The instance is created on first access and persists throughout the application lifetime.
Example:
loadBinary#
void AHotCodeReload::loadBinary(const APath& path)
Load and patch a binary object file at runtime.
- Arguments
path
Path to the object file to load.
This method loads a binary object file and patches the running application with the new code. It's typically used internally by the hot code reload system but can be called manually if needed.
The method is thread-safe and will schedule the reload on the main thread.