8 ms·
C and C++ Hot-Reload/Live Coding
- deleted 3y ago[deleted]
- yagkasha 3y agoReminds me of this[0] post on NullProgram about how to apply hot reloading to C. [0]: https://nullprogram.com/blog/2014/12/23/ https://nullprogram.com/blog/2014/12/23/
- vidarh 3y agoI'm reminded of an old project called Entity that sadly disappeared (I may have an old snapshot from before their site went down somewhere), where someone had built a GUI designer where you linked GUI events to code live. One of the supported languages was C, in which case on change the code was passed to GCC and compiled into an .so and swapped into the process the same way as here (it also supported Perl and JS, I think; it was an odd beast... And you could edit the code of the GUI designer from within the GUI designer itself)
- papruapap 3y agoWell... this sure looks better than my powershell script for hotreloading lol
- delta_p_delta_x 3y agoWow—a commercial offering exclusively targeting Windows, C++, and game development, and yet showcased on Hacker News. A rare combination indeed! :P EDIT: The deep dive[1] on their webpage is absolutely worth a read. [1]: https://liveplusplus.tech/downloads/THQ_Nordic_Dev_Summit_2023_Live++_Behind_the_Scenes.pptx https://liveplusplus.tech/downloads/THQ_Nordic_Dev_Summit_20...
- tivolo 3y agoNote that it's not exclusively targeted to game development, it's just that most companies using Live++ are in the gamedev space. There's no reason not to use Live++ on other non-games Windows applications, and we do in fact have customers outside the games industry.
- jasonjmcghee 3y agoFwiw, I would guess, after unity, C++ targeting windows is the dominate approach to game development by a margin. And I see game engines on HN pretty often. Doesn't seem that strange
- mjburgess 3y agofyi, "hot reload" is a native part of every operating system (consider, even trivially, forking or https://en.wikipedia.org/wiki/Dynamic_loading https://en.wikipedia.org/wiki/Dynamic_loading). It's a sign of how bad developer tooling has been that live reload is sold as an add-on feature. DX seems always to see-saw between bill gate's c. 1990 demo of VB, and the compile-time speeds of a N' Wirth. At a guess, when the internet happened, all DX had to be thrown away and we still arent back to where we were 30+ y ago. I support being paid for your work, but live reload is a fairly trivial thing to write for yourself -- I spent one day this gone weekend writing a debugger in C which does it. (consider also, https://github.com/tsoding/musializer https://github.com/tsoding/musializer which has live rebuild via the nobuild system in nob.c)
- agentultra 3y agoI was also suspicious but I think this system does have advantages over the OS interfaces for this: incremental compilation and binary patching. If this goes down to the function or block level definitions and is fast that's pretty sweet. The only time I've enjoyed that kind of DX is with Common Lisp/CLOS. Update: there's a "deep dive" power-point that goes into a bit more detail: https://liveplusplus.tech/downloads/THQ_Nordic_Dev_Summit_2023_Live++_Behind_the_Scenes.pptx https://liveplusplus.tech/downloads/THQ_Nordic_Dev_Summit_20...
- benwaffle 3y ago> fyi, "hot reload" is a native part of every operating system (consider, even trivially, forking & reforking). Can you expand on this?
- hoten 3y agoDoes this have any further benefit than what Visual Studio's hot code reloading provides?
- ur-whale 3y agoYeah, I was wondering the exact same thing.
- tivolo 3y agoThere is a comparison between Live++ and Visual Studio's Edit-and-Continue here: https://liveplusplus.tech/faq.html https://liveplusplus.tech/faq.html In our (and many of our customers') experience, E&C doesn't work for anything larger than simple toy projects. It just isn't reliable. On top of that, I think its biggest shortcoming is that E&C doesn't work with optimizations at all (this is documented), and is tied to the Visual Studio IDE, which not everybody uses.
- Pesthuf 3y agoThe World of Warcraft Server emulator TrinityCore has a hot reload system for its Scripting (Boss AI, Spells etc.). AFAIK when it's enabled, those modules are compiled into their own shared library and when you make a change to one of the script .cpp files, it triggers a compilation and then unloads and reloads the shared library (I think the process is more complicated than that so it doesn't crash for scripts that are currently active and different operating systems behaving differently). Made developing those scripts much, much more comfortable when it was introduce. You no longer needed to manually compile, stop and start the server, wait for all the database stuff to be loaded, switch to the client, log back in, wait and then retry on every single tiny change. To me, it was like magic. Today, I wonder why they didn't just use a proper scripting language.
- reactordev 3y agoThis is how RunUO/ServeUO was designed as well. I'm pretty sure it's a common design practice that came from muds. The server is only responsible for network and communications - everything is then orchestrated through plugins/scripts/systems that can be compiled and reloaded while the server is running. The more modern way is now to separate your "server" from your "modules" in distributed-systems architecture (just deploy the new module to the farm) but the idea still permeates. Still, RunUO was C# and like java, recompiling and loading is trivial. Doing it in C/C++ land is heroic.
- throwup238 3y ago> Doing it in C/C++ land is heroic. Not to diminish the accomplishment or anything but is it that much easier in C# and Java? It was always really easy to use the libloaderapi in Windows. Throw a vtable on it and baby, you got a stew going!
- adra 3y agoAt least for java, you can spin out a new class loader which intercepts all class loading tasks and basically shim the dynamic module from the permanent runtime platform very trivially. For unloading, you'll likely need conventions on how to shut it down cleanly to not leave a ton of garbage around. Want a new version? Spin up a new class loader, rinse and repeat. If you need stateful between versions, you clearly need to mindfully build a facade for that outside of the dynamic parts. This is all not hard, but not introductory either. That said, I basically wrote similar DLL loaders in my first year writing c so many decades ago, so shrugs.
- davidzweig 3y agoI really liked the product video, can someone advise how to make something similar for our project? EDIT: Oh, I guess After Effects with some stock background video and audio track mostly. Burning logo effect: https://www.youtube.com/watch?v=wkP-IYmPzpI https://www.youtube.com/watch?v=wkP-IYmPzpI Glitch effect: https://www.youtube.com/watch?v=7eOMSuPdbok https://www.youtube.com/watch?v=7eOMSuPdbok Simulated monitor recording (this doesn't show the monitor border though..) https://www.youtube.com/watch?v=JOYdGtyxMkI https://www.youtube.com/watch?v=JOYdGtyxMkI Animated font effects - surely these are possible if the rest is. At 1:04, I think they made a custom graphic to that overlays the stock video below.
- jryan49 3y agoProbably Adobe After Effects
- kleiba 3y agoYes!!! Finally we're off ukulele soundtracks! https://www.youtube.com/watch?v=o5vUzS9EGUU https://www.youtube.com/watch?v=o5vUzS9EGUU
- kleiba 3y agoIn one of the earlier episodes of the Handmade Hero series, Casey Muratori writes a hot-reloading functionality for C from scratch in about an hour (while giving detailed explanations of what he's doing). The following two episodes then improve upon the initial results. https://www.youtube.com/watch?v=WMSBRk5WG58 https://www.youtube.com/watch?v=WMSBRk5WG58
- jasonlotito 3y agoI was thinking the same thing when I saw this. Thanks for finding the video! His early stuff is especially good.
- mananaysiempre 3y agoOn one hand, I appreciate Muratori showing that loading code into your program dynamically isn’t actually difficult. On the other, the hard part of general hot reloading on systems that have tried it (from Smalltalk to VC++ Edit-and-Continue) is migrating obsolete state—or at least reliably telling the user when you can’t, so as to avoid leaving them to debug a mad world that could never be encountered in a fresh run. As far as I remember, Muratori basically does not touch on that at all.
- el_oni 3y agoThere is a tsoding daily video with hot code reloading in C [0]. He dicusses techniques for this. one of which is a "migration" approach, similar to database migrations. Where, for example, you have a version number in your struct. and a function for migrating from an old version to a new version. I don't think he implements it in that video though. [0] https://www.youtube.com/watch?v=Y57ruDOwH1g&t=15s https://www.youtube.com/watch?v=Y57ruDOwH1g&t=15s
- jheruty 3y agoI experimented with hot-reloadable C++ a while back. https://github.com/jheruty/hscpp.git https://github.com/jheruty/hscpp.git Video for how it works: https://www.youtube.com/watch?v=pjGngeKgni8 https://www.youtube.com/watch?v=pjGngeKgni8 To migrate from one class version to another, I found the easiest way was to provide a callback method in the constructor where one could save the state from the old class, and read it into the new class. For example: https://github.com/jheruty/hscpp/blob/master/examples/simple-demo/src/Printer.cpp https://github.com/jheruty/hscpp/blob/master/examples/simple... Ultimately though the limitations of hot-swapping this way limits its usefulness. My understanding is that liveplusplus is much more full-featured.
- vodou 3y agoMaybe I'm just old and grumpy, but the subscription business model just puts me off. Nowadays when I read about some development tool (or just any product), I start with the price page. If there are only subscriptions available I stop reading and go on with my life.
- hyperhopper 3y agoNo, totally reasonable not wanting to spend your whole life financially beholden to everybody you've ever done business with. "you will own nothing and be happy" is sadly becoming true, as you have pretty much no Rights for any digital and more of the world is becoming digital. When people ask why I don't like copilot and want a worse alternative when copilot "pays for itself", it's not because I don't want to pay, I just want to buy something and have it.
- mananaysiempre 3y ago> I don't like copilot and want a worse alternative [that can be used in perpetuity] There’s replit-code[1], which is pretty much that I think. [1] https://huggingface.co/replit/replit-code-v1_5-3b/ https://huggingface.co/replit/replit-code-v1_5-3b/
- CamperBob2 3y agoI just want to buy something and have it. You are buying time. Never pass up an opportunity to do that.
- funcDropShadow 3y agoBut, if the subscription provider goes out of business or changes the product, I have to be prepared to spend more time to find an alternative. So, if I want to keep a project long term, I'd avoid subscriptions.
- thrtythreeforty 3y agoA good way to detect these kinds of subscription-only tools is that they all call it "Pricing." (Not "Cost" or "Store" or "Purchase," all of which imply that you might own something after you pay.) I get very disinterested when I see that heading on a webpage now.
- miniupuchaty 3y agoIt's pretty good. Epic added it as part of Unreal Engine to replace their previous hot reload system, which was more similar to the alternatives that people are mentioning here. That previous hot-reload didn't work as well as live coding, was less stable. Simple dll reloading can work great if you separate state from logic, like shown in handmade hero. If you cannot enforce that then live++ is a good alternative. Too bad there's no linux support.
- rezonant 3y agoUnreal's original Hot Reload system is despised by Unreal developers, and it is a constant source of headaches for new developers using C++ with Unreal, as it can corrupt the (in memory, but also serialized and persistent) UObjects that your game relies on to run. Live++ ("Live Coding" in Unreal) can still cause these problems if you leave the Reinstancing option on. For anyone doing C++ in Unreal, please please please read this [1] and at the very least make sure to not use the older Hot Reload. [1] https://landelare.github.io/2023/01/07/cpp-speedrun.html#compiling https://landelare.github.io/2023/01/07/cpp-speedrun.html#com...
- PhilipRoman 3y agoI'm a fan of the opposite approach - serializing the program's state and launching a new instance which reads it. For one particular application I just had it keep all of it's useful state in /dev/shm (mmapped as a struct), double buffering it on every iteration of the main event loop. Of course that doesn't scale too well if you have dynamic allocations. This also has the advantage of not requiring platform specific code and being able to create checkpoints and time travel.
- donadigo 3y agoInteresting approach. Was it enough for your use case despite being quite cumbersome if you end up needing to save a bunch of different more complex instances? I mean, I imagine most dynamic objects that are the real state you'd care about will probably be allocated somewhere on the heap and be referenced from lists or pointer types. I guess this would work best for POD types like program settings and the like, so I'm curious about your setup there.
- PhilipRoman 3y agoYeah it worked fairly well. IIRC there wasn't any kind of dynamically allocated data at all as is common in embedded projects. All strings were stored as fixed size, basically char[64]. Instead of storing pointers, I stored offsets within the memory file, since the base address changes from run to run. (rant incoming) This is actually something that bothers me with contemporary programming languages - the huge amount of implicit state due to function calls on the stack and the way the heap is organized. I'm much more in favor of a data-oriented design where you don't get to freely allocate objects, but need to strictly organize them according to a model. I imagine this would also make formal verification a lot easier, since you have a single global coherent view of the program state, kind of like being forced to store all important program state in a database (except more efficient since it's just memory). Ironically I've become a big fan of global variables. In my experience the classic criticism of "anything could modify anything" doesn't really hold - using globals enables me to statically analyze all usages, not to mention setting memory breakpoints becomes much easier as well - I always know what I want to watch, instead of it being some pointer that will be allocated at some unknown time, 20 stack frames away from the actual usage.
- Jeaye 3y agoFolks interested in this should absolutely look at the open source Cling project, which uses Clang/LLVM to JIT compile C++ in-process. https://github.com/root-project/cling https://github.com/root-project/cling I'm using Cling, as part of jank, a native Clojure dialect on LLVM, with C++ interop. This allows me to have truly interactive, dynamic programming, while still reaching into native code. jank source compiles to C++, which is then JIT compiled by Cling. In recent benchmarks, it can be several times faster than Clojure JVM. https://jank-lang.org/ https://jank-lang.org/
- moelf 3y agoMy personal experience with ROOT REPL is that it's quite stateful, some error may make you want to restart the session I avoid it for anything longer than a few minutes of use
- sigmoid10 3y agoThis. I haven't used it for a while, but my experience is that this whole idea is not worth the trouble. If you want to rapidly design and test algorithms in a JIT environment, just use Python. It's designed for that. You can always port it to c++ in the end if performance is an issue.
- Jeaye 3y agoI understand that frustration. Fortunately, Clojure (and jank) gets around this entirely. Functions can be redefined at any time, even with different signatures, globals as well. References to the will stay intact and will use the latest value; this is also thread-safe. Ultimately, this isn't something Cling needs to worry about. You can have your cake and eat it, too. If that sounds too good to be true, know that it's how Clojure devs write all programs. We spin up the process and then send code to it from our editors, without needing to tear it down. jank gives you this, in C++ land, including support for inline C++ within your Clojure code. I'll have a lot more demos coming out this year, but you can also check out the jank blog or my talks at ROOT's compiler research group and Clojure Conj 2023.
- Micaellyfelx 3y ago[flagged]
- tsmeets 3y agoYou don't need anything complicated for this. All you need is to compile your code to a shared library that exports an 'update' method. See https://github.com/TomSmeets/quest-for-nothing/blob/master/app/hot.c https://github.com/TomSmeets/quest-for-nothing/blob/master/a... You have to be careful with global variables however, they will get cleared to zero when the code is reloaded. To solve this either don't use globals or just restore them on reload.
- tivolo 3y agoNot having globals at all or restoring them on reload isn't exactly "don't need anything complicated for this", especially considering using a generic hot-reload tool on AAA 5M+ LOC projects. There's no easy way to retrofit hot-reload into these large codebases. Sure, it's easier if you design everything up-front with hot-reloading in mind, but it's still going to be hard to convince developers that they cannot use globals, thread-local storage, function statics, or other inherently stateful things that just won't work with DLL reloading.
- MuffinFlavored 3y agoAny other "stateful" issues you've ran into?
- Diederich 3y agoBack in the early 90s when I was writing https://en.wikipedia.org/wiki/Multi-user_dungeon https://en.wikipedia.org/wiki/Multi-user_dungeon 's, and for a while had quite a few players, I was always keen to move as much functionality as possible into unloadable/loadable libraries, since restarting the game was quite invasive. To my surprise, this was seen as a pretty amazing feature at the time. I never understood why many/most of the other MUDs at the time didn't utilize this.
- emmelaich 3y agoSee also "Liberating the Smalltalk lurking in C and Unix" by Stephen Kell https://www.youtube.com/watch?v=LwicN2u6Dro https://www.youtube.com/watch?v=LwicN2u6Dro
- justinl33 3y agoCould this somehow be adapted into a Jupyter Notebook-type technology for C/C++?
- rurban 3y agoIt is Windows only, so no.
- masfoobar 3y agoA few years ago I wrote a 'plugin' feature of various sections that allowed changes to me modifed, compiled and reloaded while the game/editor was running. It was a C project and it really is not that hard to do (once you get over the thought process and tinkering) Once I got the hang of it I could whip something together within a few hours. There was sections for- input, motion, renderer, sound, and frontend/gui. Some allowed to loading multiple things.. others a single instance. The input one was a good example. I had keyboard using SDL2. One day, someone had a XBox controller in their bag and asked to borrow it while watching a movie. I added support for that. So, when the game loaded, you could specify you are using Keyboard and XBox controller.. so it loads them. If there was a bug, I could modify, recompile and reload. For the renderer, I had opengl by default... and never got round to doing a Vulkan version. Would have been interesting to have them 'swap' during a live play to compare and tinker. (the motion was for the mouse. Without really looking into it, I was kinda hoping that would have been a nice setup for VR support but never owned one. Might be something in 2024) This Live++ looks cool and maybe useful for companies that are spending a bit of cash on decent tools (Unreal, etc) but for small projects, I dont think this is needed. To be honest, I did not think what I was doing was called 'hot reloading' until, a few years later, I came across Casey Muratori's Handmade hero series. Atleast, I believe it was from there - or other variants at that time. There are lessons learned, though. I was creating header and src files (with makefiles) for each implementation. If I had to revisit this sort of this, would keep it header only... keeping the build minimal. Might not work.. something I would try, anyway.
- ur-whale 3y agoI am very glad to see something like this is finally reaching mainstream consciousness. Not being able to do this on Linux (and it unfortunately looks like this is also Windows only) has been a major source of frustration for me when writing C++, especially given that something like it (edit and continue) has been available in Visual C++ for near on 20 years.
- tivolo 3y agoI would really like to make Live++ available for Linux one day - it's been asked for a few times already.
- v1ne 3y agoFirst, I'm really happy about all those solutions for the gaming industry! They solve real-world problems and work with software at scale, with great pragmatism. But I would have liked to see a comparison of this solution to others on the market, like the readily-available "Hot Reload" in Microsoft Visual Studio. For a multi-MLOC codebase, VS "Hot Reload" required some patience, and it mostly worked only for simple cases like changing "if" statements or constants. But that's actually all I needed at that time, and considering that I was using VS anyway, I was happy with not having to pay extra. So, did somebody try out the Live++ hot-reloading technology and could share their experiences?
- Warwolt 3y agoWe're using Live++ at Mojang. For very large complicated software, we never had any success with VS Hot Reload. Live++ works like a dream and has had noticeable productivity improvements for the devs that've tried it.
- tivolo 3y agoThere is a comparison between Live++ and Visual Studio's Edit-and-Continue here: https://liveplusplus.tech/faq.html https://liveplusplus.tech/faq.html In our (and many of our customers') experience, E&C doesn't work for anything larger than simple toy projects. It just isn't reliably. On top of that, I think its biggest shortcoming is that E&C doesn't work with optimizations at all (this is documented), and is tied to the Visual Studio IDE, which not everybody uses.