Coder Social home page Coder Social logo

ddovod / jet-live Goto Github PK

View Code? Open in Web Editor NEW
400.0 23.0 23.0 867 KB

c++ hot code reload for linux and macos

License: MIT License

CMake 0.62% C++ 90.44% C 8.14% Shell 0.01% Python 0.78% Emacs Lisp 0.01%
hot-reload hot-reloading cpp live-coding livereload live-reload linux macos livecoding livecode

jet-live's Introduction

Demo

Build Status

Important: starting from macOS 10.14 the approach used in the library doesn't work anymore, looks like Apple have restricted some of the low level routines. On Linux at least on Ubuntu 20.04 it still works fine.

jet-live is a library for c++ "hot code reloading". It works on linux and modern macOS (10.12+ I guess) on 64 bit systems powered by cpu with x86-64 instruction set. Apart from reloading of functions it is able to keep apps' static and global state unchanged after code was reload (please refer to "How it works" for what is it and why it is important). Tested on Ubuntu 18.04 with clang 6.0.1/7.0.1, lld-7, gcc 6.4.0/7.3.0, GNU ld 2.30, cmake 3.10.2, ninja 1.8.2, make 4.1 and macOS 10.13.6 with Xcode 8.3.3, cmake 3.8.2, make 3.81.

Important: this library doesn't force you to organize your code in some special way (like in RCCPP or cr), you don't need to separate reloadable code into some shared library, jet-live should work with any project in the least intrusive way.

If you need something similar for windows, please try blink, I have no plans to support windows.

Prerequisites

You need c++11 compliant compiler. Also there're several dependencies which are bundled in, most of them are header-only or single h/cpp pair library. Please refer to the lib directory for details.

Getting started

This library is best suited for projects based on cmake and make or ninja build systems, defaults are fine-tuned for these tools. The CMakeLists.txt will add set(CMAKE_EXPORT_COMPILE_COMMANDS ON) option for compile_commands.json and alter compiler and linker flags. This is important and not avoidable. For details please see CMakeLists.txt. if you use ninja, add -d keepdepfile ninja flag when running ninja, this is needed to track dependencies between source and header files

  1. In your project CMakeLists.txt file:
include(path/to/jet-live/cmake/jet_live_setup.cmake) # setup needed compiler and linker flags, include this file in your root CMakeLists.txt
set(JET_LIVE_BUILD_EXAMPLE OFF)
set(JET_LIVE_SHARED ON) # if you want to
add_subdirectory(path/to/jet-live)
target_link_libraries(your-app-target jet-live)
  1. Create an instance of jet::Live class
  2. In your app runloop call liveInstance->update()
  3. When you need to reload code, call liveInstance->tryReload()

Important: This library is not thread safe. It uses threads under the hood to run compiler, but you should call all library methods from the same thread.

Also I use this library only with debug builds (-O0, not stripped, without -fvisibility=hidden and things like that) to not deal with optimized and inlined functions and variables. I don't know how it works on highly optimized stripped builds, most likely it will not work at all.

Personally I use it like this. I have a Ctrl+r shortcut to which tryReload is assigned in my application. Also my app app calls update in the main runloop and listens for onCodePreLoad and onCodePostLoad events to recreate some objects or re-evaluate some functions:

  1. I start my application
  2. I edit some files, save it, and now I know that I'm ready to reload new code (here previously I recompiled application)
  3. I press Ctrl+r
  4. I'm watching for output of my application to see if there're any compilation/linkage errors (see "Customizations")
  5. Both for success or fail, go to 2

jet-live will monitor for file changes, recompile changed files and only when tryReload is called it will wait for all current compilation processes to finish and reload new code. Please don't call tryReload on each update, it will not work as you're expecting, call it only when your source code is ready to be reloaded.

If you don't want to switch back and forth between your code editor and app, you can configure a keyboard shortcut which runs a shell command kill -s USR1 $(pgrep <your_app_name>), the library will trigger code reload when SIGUSR1 signal is received. It works at least in emacs, Xcode, CLion and VSCode, but I'm sure it is achievable in other editors and IDEs, just google it. If your debugger is lldb and it catches this signal and stops the app, add this commands to the ~/.lldbinit file:

breakpoint set --name main
breakpoint command add
process handle -n true -p true -s false SIGUSR1
continue
DONE

On macOS you can use cmake -G Xcode generator apart from make and ninja. In this case please install xcpretty gem:

gem install xcpretty

Example

There's a simple example app, just run:

git clone https://github.com/ddovod/jet-live.git && cd jet-live
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Debug .. && make
./example/example

and try hello command. Don't forget to run reload command after fixing the function.

Tests

There's a not very comprehensive, but constantly updating test suite. To run it:

git clone https://github.com/ddovod/jet-live.git && cd jet-live
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DJET_LIVE_BUILD_TESTS=ON .. && make
../tools/tests/test_runner.py -b . -s ../tests/src/

Features

Implemented:

  • Reloading functions
  • Relocating static and global state
  • Tracking dependencies
  • Working with code from this executable and loaded shared libraries
  • Linux and macOS implementation
  • Ability to add new compilations units on the fly (just invoke cmake to recreate compile_commands.json file after new .cpp file was created)

Will be implemented:

  • Code reload in multithreaded app (right now reloading of code in multithreaded app is not reliable)

Will not be implemented at all:

  • Reliable reload of lambda functions with non-empty captures. Lambdas with empty capture list are ok since they are just a plain functions at the lowest level (at least they are implemented this way). There's only 1 case where we can handle lambdas with non-empty capture list properly - if old and new code has lambda with exactly same signature and exactly same lambdas before this lambda within this file, in other cases the reload of lambdas is not reliable. The reason for this is mangled name of lambda type depends on the arguments and position of this lambda relative to another lambdas in this compilation unit. Moreover different compilers use different name mangling of lambda types. Please refer to tests to see good and bad cases.

Customizations

jet-live is fine-tuned to work with cmake and make/ninja tools, but if you want to adopt it to another build tool, there's a way to customize its' behaviour in some aspects. Please refer to sources and documentation. Also it is a good idea to create your own listener to receive events from the library. Please refer to documentation of ILiveListener and LiveConfig.

Important: it is highly recommended to log all messages from the library using ILiveListener::onLog to see if something went wrong.

How it works (for curious ones)

The library reads elf headers and sections of this executable and all loaded shared libraries, finds all symbols and tries to find out which of them can either be hooked (functions) or should be transferred/relocated (static/global variables). Also it finds symbols size and "real" address.

Apart from that jet-live tries to find compile_commands.json near your executable or in its' parent directories recursively. Using this file it distinguishes:

  • compilation command
  • source file path
  • .o (object) file path
  • .d (depfile) files path
  • compiler path
  • working directory - directory from which the compiler was run
  • some compiler flags for further processing.

When all compilation units are parsed, it distinguishes the most common directory for all source files and starts watching for all directories with source files, their dependencies and some service files like compile_commands.json.

Apart from that the library tries to find all dependencies for each compilation unit. By default it will read depfiles near the object files (see -MD compiler option). Suppose the object file is located at:

/home/coolhazker/projects/some_project/build/main.cpp.o

jet-live will try to find depfile at:

/home/coolhazker/projects/some_project/build/main.cpp.o.d
or
/home/coolhazker/projects/some_project/build/main.cpp.d

It will pick up all dependencies which are under the watching directories, so things like /usr/include/elf.h will not be treated as dependency even if this file is really included in some of your .cpp files.

Now the library is initialized.

Next, when you edit some source file and save it, jet-live immediately starts compilation of all dependent files in the background. By default the number of simultaneous compilation processes is 4, but you can configure it. It will write to log about successes and errors using ILiveListener::onLog method of listener. If you trigger compilation of some file when it is already compiling (or waiting in the queue), old compilation process will be killed and new one will be added to the queue, so its kinda safe to not wait for compilation to finish and make new changes of the code. Also after each file was compiled, it will update dependencies for compiled file since compiler can recreate depfile for it if new version of compilation unit has new dependencies.

When you call Live::tryReload, the library will wait for unfinished compilation processes and then all accumulated new object files will be linked together in shared library and placed near your executable with name lib_reloadXXX.so, where XXX is a number of "reloads" during this session. So lib_reloadXXX.so contains all new code.

jet-live loads this library using dlopen, reads elf/mach-o headers and sections and finds all symbols. Also it loads relocation info from the object files which was used to construct this new library. After that:

  • For all hookable functions it transfers the control flow from old version to new one
  • For all link-time relocations it fixes new shared library in a way where new code is pointing to old already living static/global variables
  • For all local static variables that were not relocated it just memcpy memory from old location to new one

Important: ILiveListener::onCodePreLoad event is fired right before lib_reloadXXX.so is loaded into the process memory. ILiveListener::onCodePostLoad event is fired right after all code-reloading-machinery is finished.

About functions hooking

You can read more about function hooking here. This library uses awesome subhook library to redirect function flow from old to new ones. You can see that on 32 bit platforms your functions should be at least 5 bytes long to be hookable. On 64 bit you need at least 14 bytes which is a lot, and for example empty stub function will probably not fit into 14 bytes. From my observations, clang by default produces code with 16-byte functions alignment. GCC don't do this by default, so for GCC the -falign-functions=16 flag is used. That means the spacing between begins of any 2 functions is not less that 16 bytes, which makes possible to hook any function.

About state transfer

New versions of functions should use statics and globals which are already living in the application. Why is it important? Suppose you have (a bit synthetic example, but anyway):

// Singleton.hpp
class Singleton
{
public:
    static Singleton& instance();
};

int veryUsefulFunction(int value);

// Singleton.cpp
Singleton& Singleton::instance()
{
    static Singleton ins;
    return ins;
}

int veryUsefulFunction(int value)
{
    return value * 2;
}

Then you want to update veryUsefulFunction to smth like this:

int veryUsefulFunction(int value)
{
    return value * 3;
}

Great, now it multiplies argument by 3. But since whole Singleton.cpp will be reloaded and Singleton::instance function will be hooked to call new version, lib_reloadXXX.so will contain new static variable static Singleton ins, which is not initialized, and if you call Singleton::instance() after code was reloaded, it will initialize this variable again which is not good cause we don't want to call its constructor again. Thats why we need to relocate all statics and globals to the new code and transfer the guard variables of statics. Most of the link-time relocations related to statics and globals are 32-bit. So if the shared library with new code will be loaded too far in memory from the application, it will be not possible to relocate variables in this way. To solve this, new shared library is linked using special linker flags which allows us to load it into specific pre-calculated location in the virtual memory (see -image_base in Apple ld, --image-base in LLVM lld and -Ttext-segment + -z max-page-size in GNU ld linker flags).

Also your app will probably crash if you try to change memory layout of your data types in reloadable code.

Suppose you have an instance of this class allocated somewhere in the heap or on the stack:

class SomeClass
{
public:
    void calledEachUpdate() {
        m_someVar1++;
    }
private:
    int m_someVar1 = 0;
}

You edit it and now it looks like:

class SomeClass
{
public:
    void calledEachUpdate() {
        m_someVar1++;
        m_someVar2++;
    }
private:
    int m_someVar1 = 0;
    int m_someVar2 = 0;
}

After code is reloaded, you'll probably observe a crash because already allocated object has different data layout, it has no m_someVar2 instance variable, but new version of calledEachUpdate will try to modify it actually modifying random data. In such cases you should delete this instance in onCodePreLoad callback and recreate it in onCodePostLoad callback. Correct transfer of its state is up to you. The same effect will take place if you'll try to change static data structures layout. The same also correct for polymorphic classes (vtable) and lambdas with captures (captures are stored inside lambdas' data fields).

Licence

MIT

For licences of used libraries please refer to their directories and source code.

jet-live's People

Contributors

abergard avatar ddovod avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jet-live's Issues

[Newbie Question] Why wrap in std::unique_ptr?

What is the purpose behind using ::make_unique so much?
For example:

Why
auto live = jet::make_uniquejet::Live(std::move(listener), config);
Instead of something like.
jet::Live live(listener,config);

Cool project by the way.

Symbols with the same names

If there're several internal variables with the same names in different compilation units, only one of them is reloaded. Probably this is because of unordered_map with symbol names as keys.

macOS 11 Support

Any chance of adding support for macOS 11? At the moment jet-live doesn't work. This is what is output by the logger:

[I]: Initializing...
[I]: Load CUs: done
[I]: Load dependencies: done
[I]: Setup file watcher: done
[W]: Image doesn't exist: /usr/lib/libSystem.B.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
[W]: Image doesn't exist: /usr/lib/libc++.1.dylib
[W]: Image doesn't exist: /usr/lib/system/libcache.dylib
[W]: Image doesn't exist: /usr/lib/system/libcommonCrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libcompiler_rt.dylib
[W]: Image doesn't exist: /usr/lib/system/libcopyfile.dylib
[W]: Image doesn't exist: /usr/lib/system/libcorecrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libdispatch.dylib
[W]: Image doesn't exist: /usr/lib/system/libdyld.dylib
[W]: Image doesn't exist: /usr/lib/system/libkeymgr.dylib
[W]: Image doesn't exist: /usr/lib/system/liblaunch.dylib
[W]: Image doesn't exist: /usr/lib/system/libmacho.dylib
[W]: Image doesn't exist: /usr/lib/system/libquarantine.dylib
[W]: Image doesn't exist: /usr/lib/system/libremovefile.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_asl.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_blocks.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_c.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_collections.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_configuration.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_containermanager.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_coreservices.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_darwin.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_dnssd.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_featureflags.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_info.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_m.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_malloc.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_networkextension.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_notify.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_product_info_filter.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_sandbox.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_secinit.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_symptoms.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_trace.dylib
[W]: Image doesn't exist: /usr/lib/system/libunwind.dylib
[W]: Image doesn't exist: /usr/lib/system/libxpc.dylib
[W]: Image doesn't exist: /usr/lib/libc++abi.dylib
[W]: Image doesn't exist: /usr/lib/libobjc.A.dylib
[W]: Image doesn't exist: /usr/lib/liboah.dylib
[W]: Image doesn't exist: /usr/lib/libfakelink.dylib
[W]: Image doesn't exist: /usr/lib/libicucore.A.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/SoftLinking.framework/Versions/A/SoftLinking
[W]: Image doesn't exist: /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SharedFileList.framework/Versions/A/SharedFileList
[W]: Image doesn't exist: /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
[W]: Image doesn't exist: /System/Library/Frameworks/Security.framework/Versions/A/Security
[W]: Image doesn't exist: /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
[W]: Image doesn't exist: /usr/lib/libapple_nghttp2.dylib
[W]: Image doesn't exist: /usr/lib/libnetwork.dylib
[W]: Image doesn't exist: /usr/lib/libsqlite3.dylib
[W]: Image doesn't exist: /usr/lib/libz.1.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
[W]: Image doesn't exist: /usr/lib/libDiagnosticMessagesClient.dylib
[W]: Image doesn't exist: /usr/lib/libenergytrace.dylib
[W]: Image doesn't exist: /usr/lib/libbsm.0.dylib
[W]: Image doesn't exist: /usr/lib/system/libkxld.dylib
[W]: Image doesn't exist: /usr/lib/libMobileGestalt.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression
[W]: Image doesn't exist: /usr/lib/libcoretls.dylib
[W]: Image doesn't exist: /usr/lib/libcoretls_cfhelpers.dylib
[W]: Image doesn't exist: /usr/lib/libpam.2.dylib
[W]: Image doesn't exist: /usr/lib/libxar.1.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/CoreAutoLayout.framework/Versions/A/CoreAutoLayout
[W]: Image doesn't exist: /usr/lib/libcompression.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
[W]: Image doesn't exist: /usr/lib/libarchive.2.dylib
[W]: Image doesn't exist: /usr/lib/libxml2.2.dylib
[W]: Image doesn't exist: /usr/lib/liblangid.dylib
[W]: Image doesn't exist: /usr/lib/libCRFSuite.dylib
[W]: Image doesn't exist: /usr/lib/libpcap.A.dylib
[W]: Image doesn't exist: /usr/lib/libdns_services.dylib
[W]: Image doesn't exist: /usr/lib/liblzma.5.dylib
[W]: Image doesn't exist: /usr/lib/libbz2.1.0.dylib
[W]: Image doesn't exist: /usr/lib/libiconv.2.dylib
[W]: Image doesn't exist: /usr/lib/libcharset.1.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/AppleSystemInfo
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/IOMobileFramebuffer.framework/Versions/A/IOMobileFramebuffer
[W]: Image doesn't exist: /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface
[W]: Image doesn't exist: /usr/lib/libCheckFix.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/CoreNLP.framework/Versions/A/CoreNLP
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/MetadataUtilities.framework/Versions/A/MetadataUtilities
[W]: Image doesn't exist: /usr/lib/libmecabra.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/MLCompute.framework/Versions/A/MLCompute
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
[W]: Image doesn't exist: /usr/lib/libmecab.dylib
[W]: Image doesn't exist: /usr/lib/libgermantok.dylib
[W]: Image doesn't exist: /usr/lib/libThaiTokenizer.dylib
[W]: Image doesn't exist: /usr/lib/libChineseTokenizer.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders
[W]: Image doesn't exist: /System/Library/Frameworks/Metal.framework/Versions/A/Metal
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBNNS.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparse.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSCore.framework/Versions/A/MPSCore
[W]: Image doesn't exist: /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSImage.framework/Versions/A/MPSImage
[W]: Image doesn't exist: /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSNeuralNetwork.framework/Versions/A/MPSNeuralNetwork
[W]: Image doesn't exist: /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSMatrix.framework/Versions/A/MPSMatrix
[W]: Image doesn't exist: /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSRayIntersector.framework/Versions/A/MPSRayIntersector
[W]: Image doesn't exist: /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/Frameworks/MPSNDArray.framework/Versions/A/MPSNDArray
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/MetalTools.framework/Versions/A/MetalTools
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/AggregateDictionary.framework/Versions/A/AggregateDictionary
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/CoreAnalytics.framework/Versions/A/CoreAnalytics
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/AppleSauce.framework/Versions/A/AppleSauce
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/IOAccelerator.framework/Versions/A/IOAccelerator
[W]: Image doesn't exist: /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreFSCache.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/LinguisticData.framework/Versions/A/LinguisticData
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/Lexicon.framework/Versions/A/Lexicon
[W]: Image doesn't exist: /usr/lib/libcmph.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory
[W]: Image doesn't exist: /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/APFS.framework/Versions/A/APFS
[W]: Image doesn't exist: /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation
[W]: Image doesn't exist: /usr/lib/libutil.dylib
[W]: Image doesn't exist: /usr/lib/libapp_launch_measurement.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/CoreServicesStore.framework/Versions/A/CoreServicesStore
[W]: Image doesn't exist: /System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
[W]: Image doesn't exist: /usr/lib/libxslt.1.dylib
[W]: Image doesn't exist: /System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement
[W]: Image doesn't exist: /usr/lib/libSystem.B.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
[W]: Image doesn't exist: /usr/lib/libc++.1.dylib
[W]: Image doesn't exist: /usr/lib/system/libcache.dylib
[W]: Image doesn't exist: /usr/lib/system/libcommonCrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libcompiler_rt.dylib
[W]: Image doesn't exist: /usr/lib/system/libcopyfile.dylib
[W]: Image doesn't exist: /usr/lib/system/libcorecrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libdispatch.dylib
[W]: Image doesn't exist: /usr/lib/system/libdyld.dylib
[W]: Image doesn't exist: /usr/lib/system/libkeymgr.dylib
[W]: Image doesn't exist: /usr/lib/system/liblaunch.dylib
[W]: Image doesn't exist: /usr/lib/system/libmacho.dylib
[W]: Image doesn't exist: /usr/lib/system/libquarantine.dylib
[W]: Image doesn't exist: /usr/lib/system/libremovefile.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_asl.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_blocks.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_c.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_collections.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_configuration.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_containermanager.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_coreservices.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_darwin.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_dnssd.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_featureflags.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_info.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_m.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_malloc.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_networkextension.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_notify.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_product_info_filter.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_sandbox.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_secinit.dylib
[W]: Image doesn't exist: /usr/lib/libSystem.B.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
[W]: Image doesn't exist: /usr/lib/libc++.1.dylib
[W]: Image doesn't exist: /usr/lib/system/libcache.dylib
[W]: Image doesn't exist: /usr/lib/system/libcommonCrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libcompiler_rt.dylib
[W]: Image doesn't exist: /usr/lib/system/libcopyfile.dylib
[W]: Image doesn't exist: /usr/lib/system/libcorecrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libdispatch.dylib
[W]: Image doesn't exist: /usr/lib/system/libdyld.dylib
[W]: Image doesn't exist: /usr/lib/system/libkeymgr.dylib
[W]: Image doesn't exist: /usr/lib/system/liblaunch.dylib
[W]: Image doesn't exist: /usr/lib/system/libmacho.dylib
[W]: Image doesn't exist: /usr/lib/system/libquarantine.dylib
[W]: Image doesn't exist: /usr/lib/system/libremovefile.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_asl.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_blocks.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_c.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_collections.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_configuration.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_containermanager.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_coreservices.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_darwin.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_dnssd.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_featureflags.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_info.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_m.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_malloc.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_networkextension.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_notify.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_product_info_filter.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_sandbox.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_secinit.dylib
[W]: Image doesn't exist: /usr/lib/libSystem.B.dylib
[W]: Image doesn't exist: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
[W]: Image doesn't exist: /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
[W]: Image doesn't exist: /usr/lib/libc++.1.dylib
[W]: Image doesn't exist: /usr/lib/system/libcache.dylib
[W]: Image doesn't exist: /usr/lib/system/libcommonCrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libcompiler_rt.dylib
[W]: Image doesn't exist: /usr/lib/system/libcopyfile.dylib
[W]: Image doesn't exist: /usr/lib/system/libcorecrypto.dylib
[W]: Image doesn't exist: /usr/lib/system/libdispatch.dylib
[W]: Image doesn't exist: /usr/lib/system/libdyld.dylib
[W]: Image doesn't exist: /usr/lib/system/libkeymgr.dylib
[W]: Image doesn't exist: /usr/lib/system/liblaunch.dylib
[W]: Image doesn't exist: /usr/lib/system/libmacho.dylib
[W]: Image doesn't exist: /usr/lib/system/libquarantine.dylib
[W]: Image doesn't exist: /usr/lib/system/libremovefile.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_asl.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_blocks.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_c.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_collections.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_configuration.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_containermanager.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_coreservices.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_darwin.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_dnssd.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_featureflags.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_info.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_m.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_malloc.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_networkextension.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_notify.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_product_info_filter.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_sandbox.dylib
[W]: Image doesn't exist: /usr/lib/system/libsystem_secinit.dylib
[I]: Load symbols: done
[I]: Load exported symbols: done
[I]: Ready
Enter command
Available commands: 'exit', 'reload', 'hello'
reload
[I]: Trying to reload code...
[I]: Nothing to reload.
[I]: Compiling: SimpleCommandInterpreter.cpp
[I]: Success: SimpleCommandInterpreter.cpp
reload
[I]: Trying to reload code...
[I]: Linking...
[W]: Link failed: /Users/cmendoza/Documents/developer/GitHub/jet-live/cmake-build-debug/lib_reload1.so
ld: warning: -seg1addr not 16384 byte aligned, rounding up
ld: library not found for -lc++
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Thanks in advance!

macOS crash

I just stepped a bit jet live and now I gott an error on reload:

Capture d’écran 2019-12-05 à 12 28 58

There is the following code:

#include <imgui.h>
#include <antara/gaming/graphics/component.canvas.hpp>
#include <antara/gaming/event/quit.game.hpp>
#include <antara/gaming/event/key.pressed.hpp>
#include "atomic.dex.gui.hpp"

namespace {
    void gui_menubar() noexcept {
        if (ImGui::BeginMenuBar()) {
            if (ImGui::MenuItem("Open", "Ctrl+O")) { /* Do stuff */ }
            ImGui::EndMenuBar();
        }
    }
}

namespace atomic_dex {
    void gui::on_key_pressed(const ag::event::key_pressed &evt) noexcept {
        if (evt.key == ag::input::r && evt.control) {
#if defined(__APPLE__) || defined(__linux__)
            live_.tryReload();
#endif
        }
    }

    gui::gui(entt::registry &registry) noexcept : system(registry) {
#if defined(__APPLE__) || defined(__linux__)
        while (!live_.isInitialized()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            live_.update();
        }
        live_.update();
#endif
        this->dispatcher_.sink<ag::event::key_pressed>().connect<&gui::on_key_pressed>(*this);
    }

    void gui::update() noexcept {
#if defined(__APPLE__) || defined(__linux__)
        live_.update();
#endif
        //! Menu bar
        auto &canvas = entity_registry_.ctx<ag::graphics::canvas_2d>();
        auto[x, y] = canvas.canvas.size;
        auto[pos_x, pos_y] = canvas.canvas.position;

        ImGui::SetNextWindowSize(ImVec2(x, y));
        ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y));
        ImGui::SetNextWindowFocus();
        bool active = true;
        ImGui::Begin("Atomic Dex", &active, ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoCollapse);
        if (not active) { this->dispatcher_.trigger<ag::event::quit_game>(0); }
        gui_menubar();
        ImGui::End();
    }
}

(I modify the function in the anonymous namespace and I reload)

(instant crash)

(Apple Clang 11.0) (clang-8)

Inconsistent behaviour

  1. Edit some File1.cpp
  2. Add new file File2.hpp/cpp with dummy function
  3. Use dummy function in File1.cpp
  4. Do not rerun cmake
  5. Reload code
  6. Observe load time error about missing dummy function
  7. Run cmake
  8. Reload

Here only code from File2.cpp will be reloaded, File1.cpp stuff is lost until new modification in this file

Build failure on gcc 8.2

Jet-live fails to build with gcc 8.2.

The first problem is straightforward: -Wvexing-parse is not supported on gcc 8.2.

The second problem I don't know how to fix; I get the following link errors when building the example:

CMakeFiles/example.dir/src/main.cpp.o: In function `std::thread::thread<main::{lambda()#1}>(main::{lambda()#1}&&)':
main.cpp:(.text+0x38c): undefined reference to `pthread_create'
main.cpp:(.text+0x3d4): undefined reference to `std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)())'
CMakeFiles/example.dir/src/main.cpp.o: In function `std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::~_State_impl()':
main.cpp:(.text+0x648): undefined reference to `std::thread::_State::~_State()'
CMakeFiles/example.dir/src/main.cpp.o: In function `std::thread::_State::_State()':
main.cpp:(.text._ZNSt6thread6_StateC2Ev[_ZNSt6thread6_StateC5Ev]+0x9): undefined reference to `vtable for std::thread::_State'
../liblib_efsw.a(MutexImpl.cpp.o): In function `efsw::Platform::MutexImpl::MutexImpl()':
MutexImpl.cpp:(.text+0x14): undefined reference to `pthread_mutexattr_init'
MutexImpl.cpp:(.text+0x25): undefined reference to `pthread_mutexattr_settype'
../liblib_efsw.a(ThreadImpl.cpp.o): In function `efsw::Platform::ThreadImpl::ThreadImpl(efsw::Thread*)':
ThreadImpl.cpp:(.text+0x31): undefined reference to `pthread_create'
../liblib_efsw.a(ThreadImpl.cpp.o): In function `efsw::Platform::ThreadImpl::wait()':
ThreadImpl.cpp:(.text+0xa1): undefined reference to `pthread_join'
../liblib_efsw.a(ThreadImpl.cpp.o): In function `efsw::Platform::ThreadImpl::terminate()':
ThreadImpl.cpp:(.text+0xd9): undefined reference to `pthread_cancel'
../liblib_tiny-process-library.a(process_unix.cpp.o): In function `std::thread::thread<TinyProcessLib::Process::async_read()::{lambda()#1}>(TinyProcessLib::Process::async_read()::{lam
bda()#1}&&)':
process_unix.cpp:(.text+0x1781): undefined reference to `pthread_create'
process_unix.cpp:(.text+0x17c9): undefined reference to `std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)())'
../liblib_tiny-process-library.a(process_unix.cpp.o): In function `std::thread::thread<TinyProcessLib::Process::async_read()::{lambda()#2}>(TinyProcessLib::Process::async_read()::{lam
bda()#2}&&)':
process_unix.cpp:(.text+0x1841): undefined reference to `pthread_create'
process_unix.cpp:(.text+0x1889): undefined reference to `std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)())'
../liblib_tiny-process-library.a(process_unix.cpp.o): In function `std::thread::_State_impl<std::thread::_Invoker<std::tuple<TinyProcessLib::Process::async_read()::{lambda()#2}> > >::
~_State_impl()':
process_unix.cpp:(.text+0x222e): undefined reference to `std::thread::_State::~_State()'
../liblib_tiny-process-library.a(process_unix.cpp.o): In function `std::thread::_State_impl<std::thread::_Invoker<std::tuple<TinyProcessLib::Process::async_read()::{lambda()#1}> > >::
~_State_impl()':
process_unix.cpp:(.text+0x227c): undefined reference to `std::thread::_State::~_State()'
../liblib_tiny-process-library.a(process_unix.cpp.o):(.rodata+0x178): undefined reference to `typeinfo for std::thread::_State'
../liblib_tiny-process-library.a(process_unix.cpp.o):(.rodata+0x1f8): undefined reference to `typeinfo for std::thread::_State'

Constructors of "old" statics in the library with new code should not be called

Since we don't use "old" statics from the library with new code (statics that are already living in the app), we should somehow prevent double initialization, but keep new statics constructors. This is not important for primitive types, but for complex structures with non-trivial constructors it is essential. This is related only to global variables cause their constructors are called before dlopen returns and so have no chance to fix relocations for them.

Functions which is weak symbol will be hooked, is it nessasary?

Some functions, like template member functions, or normal member functions defined in a header file, would be as weak symbol.

When we write something like std::vector<std::string> , it will generate some code from compiler. If we hook these functions, is there any thread safe issue?

`reload` command from example code `cannot hook functions` on Fedora 30

I'm experiencing a problem with jet-live on Fedora 30. The library is identifying changes to the files correctly, but it is not reloading the code as expected.

The error occurred while trying to follow the example of README.md

I assigned severityString.append("[D]") to the jet::LogSeverity::kDebug on onLog method from ExampleListerner to make the output easier to understand.

Running the code for the first time it was the output:

[I]: Initializing...
[D]: Parsing compilation commands...
[D]: Reading `compile_commands.json` from /home/username/jet-live/build/compile_commands.json
[D]: Success parsing compilation commands, total 48 compilation units
[I]: Load CUs: done
[D]: Root directory: /home/username/jet-live/
[D]: Parsing dependencies...
[D]: Success parsing dependencies
[I]: Load dependencies: done
[I]: Setup file watcher: done
[D]: Loading symbols for  ...
[D]: Symbols loaded: funcs 9541, vars 33, Self
[D]: Loading symbols for linux-vdso.so.1 ...
[E]: Cannot load linux-vdso.so.1 file
[D]: linux-vdso.so.1 has no symbols, skipping
[D]: Loading symbols for /lib64/libpthread.so.0 ...
[D]: Symbols loaded: funcs 497, vars 45, /lib64/libpthread.so.0
[D]: Loading symbols for /lib64/libdl.so.2 ...
[D]: Symbols loaded: funcs 32, vars 8, /lib64/libdl.so.2
[D]: Loading symbols for /lib64/libstdc++.so.6 ...
[D]: /lib64/libstdc++.so.6 has no symbols, skipping
[D]: Loading symbols for /lib64/libm.so.6 ...
[D]: Symbols loaded: funcs 1910, vars 3, /lib64/libm.so.6
[D]: Loading symbols for /lib64/libgcc_s.so.1 ...
[D]: /lib64/libgcc_s.so.1 has no symbols, skipping
[D]: Loading symbols for /lib64/libc.so.6 ...
[D]: Symbols loaded: funcs 5248, vars 468, /lib64/libc.so.6
[D]: Loading symbols for /lib64/ld-linux-x86-64.so.2 ...
[D]: Symbols loaded: funcs 310, vars 40, /lib64/ld-linux-x86-64.so.2
[I]: Load symbols: done
[D]: Loading exported symbols list...
[D]: Done, total exported symbols: 12528 in 48 files
[I]: Load exported symbols: done
[I]: Ready
Enter command
Available commands: 'exit', 'reload', 'hello'
Hello
ttl: 2 > Hi there!

So I added an exclamation mark to the end of the phrase "Hi there!" that is displayed at the output of the command Hello.

[I]: Compiling: SimpleCommandInterpreter.cpp
[I]: Success: SimpleCommandInterpreter.cpp

Jet-live was able to interpret the change correctly, but when I ran the command again, the output had not been changed.

Hello
ttl: 3 > Hi there!

Then I ran the command reload and the errors below appeared (with status -22):

reload
[I]: Trying to reload code...
[I]: Linking...
[D]: Link command:
/usr/bin/g++ -fPIC -shared -g -Wl,-Ttext-segment,0xa42000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/username/jet-live/build/example/CMakeFiles/example.dir/src/SimpleCommandInterpreter.cpp.o" 
[I]: Linked successfully
[D]: Opening /home/username/jet-live/build/lib_reload1.so...
[D]: Library opened successfully
[D]: Loading symbols from /home/username/jet-live/build/lib_reload1.so...
[D]: Symbols loaded
[D]: Loading exported symbols list...
[D]: Done, total exported symbols: 21 in 1 files
[D]: Loading link-time relocations...
[D]: Done, relocated: 0/0
[D]: Hooking functions...
[E]: Cannot hook function: _ZSteqIcSt11char_traitsIcESaIcEEbRKNSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_, status -22
[E]: Cannot hook function: _ZN9__gnu_cxx12__to_xstringINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEcEET_PFiPT0_mPKS8_P13__va_list_tagEmSB_z, status -22
[E]: Cannot hook function: _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEOS8_RKS8_, status -22
[E]: Cannot hook function: _ZNSt11char_traitsIcE6lengthEPKc, status -22
[E]: Cannot hook function: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE16_M_construct_auxIPcEEvT_S7_St12__false_type, status -22
[E]: Cannot hook function: _ZN24SimpleCommandInterpreterC2Ei, status -22
[E]: Cannot hook function: _ZNSt7__cxx119to_stringEi, status -22
[E]: Cannot hook function: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPcEEvT_S7_, status -22
[E]: Cannot hook function: _ZSt4moveIRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEONSt16remove_referenceIT_E4typeEOS8_, status -22
[E]: Cannot hook function: _ZSt8distanceIPcENSt15iterator_traitsIT_E15difference_typeES2_S2_, status -22
[E]: Cannot hook function: _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEOS8_PKS5_, status -22
[E]: Cannot hook function: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1IPcvEET_S7_RKS3_, status -22
[E]: Cannot hook function: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2IPcvEET_S7_RKS3_, status -22
[E]: Cannot hook function: _ZSt19__iterator_categoryIPcENSt15iterator_traitsIT_E17iterator_categoryERKS2_, status -22
[E]: Cannot hook function: _ZN24SimpleCommandInterpreter10runCommandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE, status -22
[E]: Cannot hook function: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPcEEvT_S7_St20forward_iterator_tag, status -22
[E]: Cannot hook function: _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_, status -22
[E]: Cannot hook function: _ZNK24SimpleCommandInterpreter25getCurrentCommandsCounterEv, status -22
[E]: Cannot hook function: _ZN9__gnu_cxx17__is_null_pointerIcEEbPT_, status -22
[E]: Cannot hook function: _ZSt10__distanceIPcENSt15iterator_traitsIT_E15difference_typeES2_S2_St26random_access_iterator_tag, status -22
[E]: Cannot hook function: _ZN24SimpleCommandInterpreterC1Ei, status -22
[D]: Done, hooked: 0/21
[D]: Copying statics from old code to new one...
[D]: Done, copied: 1/1
[I]: Code reloaded

I'm using Cmake 3.14.5 and g++ 9.2.1.

Statics transfer in macos implementation

In linux, there's st_size field in the Elf64_Sym structure.
In macos, there's no size field in nlist_64 entry, so we need to distinguish symbol size somehow. Probably by sorting symbols and calculating distance between their addresses.

[CMake] The compilation flags and configuration is not applied to the "main" project when adding this library via add_subdirectory()

update: The actual problem here was that the complilation and link flags that should be changed by the CMakeList.txt flag inside this reposiotry were not applied to the code built by the project that included it via add_subdirectory()

Hi, I'm currently trying to implement jet-live inside a little SDL/OpenGL framework. I'm using a bunch of libraries, some of them are header only. One compilation unit #define a token that makes the header spits out the whole implementation there.

The compiled symbols from that library ends up inside the executable of the program.

When I attempt to modify one of the files of this project following the README, it is compiled without any error into a .so file.

When jet-live tries to load that .so file, I get an error like this :

all of this is on Linux x86_64, using GCC 8.2.0, CMake 3.14.2 and ninja 1.9.2.

jet-live  Ready
jet-live  Compiling: application.cpp
jet-live  Success: application.cpp
jet-live  Trying to reload code...
jet-live  Linking...
jet-live  Link command:
/usr/bin/c++ -fPIC -shared -g -Wl,-Ttext-segment,0x406ad000 -Wl,-z,max-page-size=0x1000 -Wl,-export-dynamic -Wl,-soname,lib_reload1.so -o lib_reload1.so "/home/ybalrid/Programming/opengl_sdl_base/build_debug_ninja/CMakeFiles/test_project_exe.dir/src/application.cpp.o" 
jet-live  Linked successfully
jet-live  Opening /home/ybalrid/Programming/opengl_sdl_base/build_debug_ninja/lib_reload1.so...
jet-live  Cannot open library /home/ybalrid/Programming/opengl_sdl_base/build_debug_ninja/lib_reload1.so
/home/ybalrid/Programming/opengl_sdl_base/build_debug_ninja/lib_reload1.so: undefined symbol: _ZN8tinygltf14WriteWholeFileEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKS5_RKSt6vectorIhSaIhEEPv

Here are some info about that symbol found with objdump:

ybalrid:build_debug_ninja/ (jet-live✗) $ objdump -x lib_reload1.so | grep _ZN8tinygltf14WriteWholeFileEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKS5_RKSt6vectorIhSaIhEEPv                                    
0000000000000000         *UND*  0000000000000000              _ZN8tinygltf14WriteWholeFileEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKS5_RKSt6vectorIhSaIhEEPv
ybalrid:build_debug_ninja/ (jet-live✗) $ objdump -x test_project_exe | grep _ZN8tinygltf14WriteWholeFileEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKS5_RKSt6vectorIhSaIhEEPv                                  
00000000000af5fd g     F .text  0000000000000297              _ZN8tinygltf14WriteWholeFileEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKS5_RKSt6vectorIhSaIhEEPv
ybalrid:build_debug_ninja/ (jet-live✗) $    

I do not understand how this symbol can be unresolved at this point. The executable image running has this symbol defined. I don't know enough about the dynamic loader on Linux to see anything obviously wrong with what's going on.

I've been digging for an hour or so, but I cannot find the cause of my problem. 😅

Source of Imgui demo.

Hey, I was wondering if you could post the source of your IMGUI demo.
I made my own version ( terribly hacked together ) and was wondering how you implemented it so I could learn from it.
output

Issues with fuse/gocryptfs

Jet Live stopped working with a project I used to work on months ago and so did the included example.

I made a fresh clone of this repository. Built it using cmake -DCMAKE_BUILD_TYPE=Debug ..; make and ran example/example. Then I made some changes in example/src/SimpleCommandInterpreter.cpp
and typed reload but it always says Nothing to reload.

Arch Linux x86_64
cmake 3.16.2
make 4.2.1
most recent git revision.

global object may cause double free or corruption

If we add some global object like "std::vectorstd::string v = { "1", "2", "3" };" in our cpp file, which will be compiled later at runtime. Now we reload the project, everything is ok.

Then, our program exit normally(not by signal), it will be crashed with some message like:

*** Error in `./main': double free or corruption (fasttop): 0x00000000019aeac0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81329)[0x7ff37cb07329]
/root/jet-live_test/build/lib_reload1.so(_ZN9__gnu_cxx13new_allocatorISsE10deallocateEPSsm+0x20)[0xc269f0]
/root/jet-live_test/build/lib_reload1.so(_ZNSt16allocator_traitsISaISsEE10deallocateERS0_PSsm+0x2b)[0xc268db]
.....

Premake support?

Hi, i was wondering if you can shed light for projects using premake (genie), the compile_commands is not a problem since we can use "bear" to create one when running make that is generated by premake.

Thanks!

Sent from my HUAWEI GR5 2017 using FastHub

strange behaviour

I've integrated your lib into my own toy-project and have a really strange behavior:
I compile and start my program in the original state and it runs.
Now I modify a small parameter (call if mod1)
jet runs and recognizes my filechange and recompiles the file
I reload the application and get 2 messages "[E]: WTF" coming from the elf loader
the program gets reloaded and some functions are relocated
now the program runs, but still in the original state (without mod1!)
now I again change something (mod2)
it gets recompiled
I reload and get again 2 times the WTF message
now the program runs in the mod1 state and not with my latest modifications, so it seems it is always one step behind?!

I understand if it works (of course) or if it does not work (not so nice), but beeing one step behind is strange. Anything I can dig into to find out what is going on?

my environment is linux 64bit, clang 7.1.0 x86_64-pc-linux-gnu

bugfix for using bear

Hi, when using bear (https://github.com/rizsotto/Bear) you get compile_commands.jsons without the command json object but with an "arguments" array. this patch will check if the command object is available and if not create it out of the arguments array:

CompileCommandsCompilationUnitsParser.cpp: (Line 116):
CompilationUnit cu;

        if(cmdJson.find("command") == cmdJson.end()) {
            //no command object available, create one from the arguments object
            auto args = cmdJson["arguments"];
            bool firstRun = true;
            for(json::iterator it = args.begin(); it != args.end(); ++it) {
                if(!firstRun) {
                    cu.compilationCommandStr += " ";
                }
                firstRun = false;
                cu.compilationCommandStr += *it;
            }
        } else {
            cu.compilationCommandStr = cmdJson["command"];
        }

        auto dirPath = TeenyPath::path(cmdJson["directory"].get<std::string>());
        if (dirPath.exists()) {
            dirPath = dirPath.resolve_absolute();

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.