Wednesday, November 5, 2014

Hot reloading C++

 Here is one approach to hot reloading of C++ that I use on my side project.
It is specific to Visual Studio.

This is useful if you want to rapidly iterate on some code, and don't enjoy continually restarting and navigating the program to whatever state it needs to be in to test the change.

It is based upon swapping DLL's and requires the ability to serialize state.

1. User modifies a C++ source file
2. File monitoring detects the change
3. Determines which projects are effected by the change.
4. Moves the existing DLL/PDB for those projects(they cannot be deleted as they are in use).
5. Fires up MSBuild to compile projects
6. Once Build Completes:
  • Build Fails:(
    • Build errors are propagated into the Visual Studio IDE
      • Have MSBuild dump out a text file containing the error msg
      • I use this command: /fl2 /fl3 /flp2:logfile=JustErrors.log;errorsonly /flp3:logfile=JustWarnings.log;warningsonly"
      • The msg is formated in a way that VS understands:)
      • Load the file in your game(JustErrors.log)
      • Use OutputDebugStringA to print it, this propagates it to VS, the error is now visible in the errors view
    • Old DLL/PDB moved back
  • Build Success:
    • Serialize state contained within relevant DLLs(into process owned memory)
      • Serializing and then unserializing the entire game state is the simplest route and avoids any potential conflicts with mixed state between DLL's. 
    • Destroy state associated with DLLs, and then unload the DLLs
    • Load new DLLs, create new state
    • Unserialize old state into the new state
    • Resume game
Rebuilds triggered by this process generally take about 1-2 seconds for my application, the exact time will depend your code.

**Visual Studio has a bug where it keeps the PDB loaded even if you unload the associated DLL.  So you can't delete the old PDB for any DLL you previously loaded, at least not while your game is running. Hopefully they fix this at some point.