Git Product home page Git Product logo

squirrel-debug-server's Introduction

Squirrel (and Quirrel) Debugger

CMake Build

This project contains libraries that will give your application the ability to remote debug a Squirrel (or Quirrel) VM. It does so using the standard Squirrel Debug Hooks, but provides a threadsafe & easy to use interface to set breakpoints, query the current state of the stack or local/global variables, redirect output, etc.

Also included (but optional) is an HTTP server that provides remote-debug capability. This is via an HTTP REST API, and output redirection/status notifications can be subscribed to via websockets. The REST API started by the embedded server is designed to be used by the companion Visual Studio Code extension, but you can also call them manually via something like POSTman, or the Swagger UI that is started by the embedded server on the provided port (e.g. http://localhost:8000/swagger/ui).

Components:

  • interfaces Contains 2 pure-virtual interfaces that are implemented by the following 2 projects.
    • MessageEventInterface, allowing the Debugger to send messages to the debug user interface.
    • MessageCommandInterface, which handles debug commands from the debug user interface.
  • embedded_server
    • uses OATPP to host an HTTP server. This acts as an endpoint for debug user interfaces to control the application.
    • Provides an implementation of MessageEventInterface.
    • Exposes a "Swagger" interface that's accessible via the browser. Located by default at http://localhost:8000/swagger/ui.
    • Swagger can be disabled by setting the cmake option SDB_ENABLE_OATPP_SWAGGER=OFF. This will save ~200KB binary size in release builds.
  • squirrel_debugger
    • Implementation of the Squirrel Debug API. Uses semaphores to lock the squirrel execution thread at breakpoints, and provides access to VM stack & variables.
    • Provides an implementation of MessageCommandInterface.
  • sample_app
    • Shows an example of how to embed the debugger in an application that runs a Quirrel script.

Release Notes

v0.2

[x] Improved output of variables in inspector [x] Evaluation of arbitrary variable strings (eg foo['bar']) to enable watch-window & variable hover functionality in VSCode

v0.1

First versioned release, 'MVP'

[x] Websocket listener for server state changes [x] HTTP Command interface [x] Stack-Local variables [x] Global Variables [x] Simple Breakpoints [x] Output redirection & capture [x] Disablement of the swagger UI on startup [x] Modification of variable values (int, bool, float and string only.)

Not Currently Supported

[ ] Multiple VM's (threads) [ ] Conditional breakpoints [ ] Immediate window for execution [ ] MacOS / Linux support [ ] squirrel unicode builds [ ] Modification of local & free variables. (No need to support modification of globals)

Building Sample from source using CMake

Currently, only support building on windows using CMake. This requires that you have Visual Studio 2019 installed.

To build: open a "Developer Command Prompt for VS 2019" (via start menu) and change to the repository directory.

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release --target "sample_app"

sample_app.exe will now exist in the build/

Embedding the debugger in your application

The provided sample_app source code shows fleshed out examples; but a detailed list of steps you need to take are:

Build using CMake

To use the debugger in your application, you will need to take a static library dependency on the following CMake targets: sdb::embedded_server and sdb::squirrel_debugger. The easiest way to do this is with CMake FetchContent. In your CMakeLists.txt:

include(FetchContent)

FetchContent_Declare(
    sdb
    GIT_REPOSITORY https://github.com/leweaver/squirrel-debug-server.git
    # Optionally pin to a specific version
    # GIT_TAG v0.1.0
    GIT_TAG origin/main
)
FetchContent_MakeAvailable(sdb)

target_link_libraries(${PROJECT_NAME}
        sdb::embedded_server
        sdb::squirrel_debugger)

Or, Build using your own method

If you do not use CMake to build your own project, you can directly link to the libraries generated by building the sample project.

  1. follow the instructions in the previous Building Sample from source using CMake section to build the libraries.
  2. Add the following include directories:
    1. interfaces/include
    2. embedded_server/include
    3. squirrel_debugger/include
    4. cmake-build-debug/_deps/oatpp-src
    5. cmake-build-debug/_deps/oatpp-src/src
    6. cmake-build-debug/_deps/oatpp-swagger-src/src
    7. cmake-build-debug/_deps/oatpp-websocket-src/src
  3. Add linker dependencies to the following (you may want to copy them to a convenient directory):
    1. cmake-build-debug/embedded_server/embedded_server.lib
    2. cmake-build-debug/squirrel_debugger/squirrel_debugger.lib
    3. cmake-build-debug/_deps/oatpp-build/src/oatpp.lib
    4. cmake-build-debug/_deps/oatpp-websocket-build/src/oatpp-websocket.lib
    5. cmake-build-debug/_deps/oatpp-swagger-build/src/oatpp-swagger.lib

Define logging hooks

In order to compile, you need to create implementations of logging functions. These are used to capture any logging output that this library generates, and route it to your own logging system.

Place the following code in any C++ file in your project.

namespace sdb::log
{
  void LogFormatted(const char* tag, size_t line, Level level, const char* message, ...)
  {  
    // OPTIONAL define this function body to hook into your logging system.
  }

  void LogString(const char* tag, size_t line, Level level, const char* str)
  {
    // OPTIONAL define this function body to hook into your logging system.
  }
}// namespace sdb::log

Create Instances

  1. Initialize the global environment for the embedded server (EmbeddedServer::InitEnvironment())
  2. Create an EmbeddedServer instance (embeddedServer_), giving it a port number to listen to network requests on (e.g. 8000).
  3. Create an SquirrelDebugger instance (squirrelDebugger_)
  4. Set the MessageCommandInterface member of the EmbeddedServer to the SquirrelDebugger instance (embeddedServer_->SetCommandInterface(squirrelDebugger))
  5. Set the MessageEventInterface member of the SquirrelDebugger to the EmbeddedServer instance. (squirrelDebugger->SetEventInterface(embeddedServer_->GetEventInterface()))
  6. Start the EmbeddedServer so it listens to network requests. (embeddedServer_->Start())

Create Squirrel VM

  1. Create your squirrel VM
  2. Add your Squirrel VM to the debugger: squirrelDebugger_->AddVm
  3. Optional: Tell the debugger to pause execution as soon as it is attached: debugger_->PauseExecution
    1. This is important. Most debug functionality will not work unless the squirrel VM is running a script, but execution is paused.
  4. call sq_setprintfunc with a function pointer that can redirect print calls to the squirrelDebugger_->SquirrelPrintCallback method.
  5. call sq_setnativedebughook with a function pointer that can redirect VM debug calls to the squirrelDebugger_->SquirrelNativeDebugHook method.
  6. call sq_enabledebuginfo with SQTrue to turn on native debugging
  7. You can now execute and debug squirrel code.

Teardown

  1. Call embeddedServer_->Stop(true) to request shutdown and join the network thread to wait for completion
  2. Call EmbeddedServer::ShutdownEnvironment() to cleanup global resources.

Checking things work

Once you have compiled & run your application, you can try connecting to the debug interface via an HTTP GET request.

The simplest way to do this is in your favorite web browser: http://localhost:8000/DebugCommand/Variables/Global?path

You should see a JSON blob, representing all the global variables defined in the current Squirrel.

  • If the connection to this page fails, the OATPP server is not running inside your application properly.
  • If you get a valid HTTP response, but it contains an error; that will guide you to what may be wrong.

You can also check the Swagger page in your browser (http://localhost:8000/swagger/ui), to try out more advanced functionality. This HTTP API is what the visual studio code extension uses to communicate with the debug engine.

squirrel-debug-server's People

Contributors

leweaver avatar

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.