Skip to content

C C Rust (via codelldb)

Lasse Haffke edited this page Oct 4, 2021 · 19 revisions

C/C++/Rust (via codelldb)

Configuration examples are in Lua. See :help lua-commands if your Neovim setup so far uses a init.vim file.

Installation

Install codelldb:

  • Download the VS Code extension.
  • Unpack it. .vsix is a zip file and you can use unzip to extract the contents.

Adapter definition

The codelldb binary starts the debug process as a server type. Therefore you need to configure nvim-dap to attach to it.

nvim-dap does not automatically start the server upon calling require'dap'.continue().

You have multiple options here:

  • Start the server externally (e.g. upon entering a file of certain type, per keymap or some other way) and attach to it via a specified port.
./codelldb --port your_port 
local dap = require('dap')
dap.adapters.codelldb = function(callback, config)
-- specify in your configuration host = your_host , port = your_port
    callback({ type = "server", host = config.host, port = config.port })
end
  • Use the adapter definition below, which spawns the server on every debug request, parses the used port from it and attaches to it.
local dap = require('dap')
dap.adapters.codelldb = function(on_adapter)
  local stdout = vim.loop.new_pipe(false)
  local stderr = vim.loop.new_pipe(false)

  -- CHANGE THIS!
  local cmd = '/absolute/path/to/codelldb/extension/adapter/codelldb'

  local handle, pid_or_err
  local opts = {
    stdio = {nil, stdout, stderr},
    detached = true,
  }
  handle, pid_or_err = vim.loop.spawn(cmd, opts, function(code)
    stdout:close()
    stderr:close()
    handle:close()
    if code ~= 0 then
      print("codelldb exited with code", code)
    end
  end)
  assert(handle, "Error running codelldb: " .. tostring(pid_or_err))
  stdout:read_start(function(err, chunk)
    assert(not err, err)
    if chunk then
      local port = chunk:match('Listening on port (%d+)')
      if port then
        vim.schedule(function()
          on_adapter({
            type = 'server',
            host = '127.0.0.1',
            port = port
          })
        end)
      else
        vim.schedule(function()
          require("dap.repl").append(chunk)
        end)
      end
    end
  end)
  stderr:read_start(function(err, chunk)
    assert(not err, err)
    if chunk then
      vim.schedule(function()
        require("dap.repl").append(chunk)
      end)
    end
  end)
end
  • Rust-Tools only If you are using this adapter for debugging Rust and are using the rust-tools extension, there is a helper function defined for setting up CodeLLDB. This helper function works the same way as the function defined in the point above. Set it up as defined here.

Have a look at this issue for more information on CodeLLDB definition.

Configuration

The codelldb manual contains a full reference for all options supported by the debug adapter.

A common configuration example:

local dap = require('dap')
dap.configurations.cpp = {
  {
    name = "Launch file",
    type = "codelldb",
    request = "launch",
    program = function()
      return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
    end,
    cwd = '${workspaceFolder}',
    stopOnEntry = true,
  },
}

If you want to use this debug adapter for other languages, you can re-use the configurations:

dap.configurations.c = dap.configurations.cpp
dap.configurations.rust = dap.configurations.cpp

The executables that you want to debug need to be compiled with debug symbols.