vscode 里混合调试 c++ 和 nodejs

因为业务里涉及到 js 和 c++ 互相调用,为了调试方便,研究下如何在 vscode 里混合调试 c++ 和 js 代码。node

效果以下, 代码见 github.com/hardfist/cp…ios

在讲混合调试以前,先简单介绍下 vscode 下 c++ 的开发和调试, 后续全部都是在 Mac OS 环境下操做的。c++

前置条件

建立项目

$ mkdir helloworld && cd helloworld && code .

复制代码

添加 helloworld

#include  <iostream>
#include  <vector>
#include  <string>


using  namespace  std;


int  main()
{
 vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"};


 for (const  string& word : msg)
    {
 cout << word << " ";
    }
 cout << endl;
}

复制代码

此时借助 c++ 插件的 intellisense 功能咱们就能够自动补全了chrome

编译 helloworld

手动编译

$ clang++ helloworld.cpp -o helloworld --std=c++11  // 由于使用了c++11语法,所以须要--std=c++11

复制代码

建立 task 进行编译

为了不每次修改代码都须要手动输入编译指令,咱们能够建立编译 task 经过 Terminal > Configure Default Build Task 就能够新建编译 task,此时会有一些备选项,咱们这里选择 C/C++ clang++ build active fileshell

默认生成以下配置json

{
     "version": "2.0.0",
     "tasks": [
        {
     "type": "shell",
     "label": "C/C++: clang++ build active file",
     "command": "/usr/bin/clang++",
     "args": [
     "-std=c++11", // 本身配置,支持c++11
     "-g",
     "${file}",
     "-o",
     "${fileDirname}/${fileBasenameNoExtension}"
          ],
     "options": {
     "cwd": "${workspaceFolder}"
          },
     "problemMatcher": [
     "$gcc"
          ],
     "group": {
     "kind": "build",
     "isDefault": true
          }
        }
      ]
    }

复制代码

默认生成的配置不支持 c++11,须要咱们自行配置 - std=c++11, 支持 c++11 的编译。websocket

调试

支持完编译后咱们就能够继续进行调试,建立 launch.json,添加配置,选择 c++ 启动 (或者使用 lldb)

修改 program 为当前文件对应的 bin 文件, 修改后配置以下

{
     // 使用 IntelliSense 了解相关属性。 
     // 悬停以查看现有属性的描述。
     // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
     "version": "0.2.0",
     "configurations": [
        {
     "name": "(lldb) 启动",
     "type": "cppdbg",
     "request": "launch",
     "program": "${fileDirname}/${fileBasenameNoExtension}",
     "args": [],
     "stopAtEntry": false,
     "cwd": "${workspaceFolder}",
     "environment": [],
     "externalConsole": false,
     "MIMode": "lldb"
        }


      ]
    }

复制代码

此时在 helloworld.cpp 里添加断点,点击 debug 按钮既能够进入调试

js 的调试

相比于 c++ 的调试,js 就简单不少, 添加一个 launch.json 便可,选择 Node.js: Launch Program

修改 programe 为当前文件,修改后配置以下

{
 "name": "Launch Program",
 "program": "${fileDirname}", // 调试当前选中的文件
 "request": "launch",
 "skipFiles": [
 "<node_internals>/**"  // 默认跳过node内部的js文件
      ],
 "type": "pwa-node"
    },

复制代码

混合调试

由于 c++ 和 nodejs 走的是不一样的调试协议,所以很难经过一个 configuration 来调试二者。 咱们以 node 官方的 example github.com/nodejs/node… 看看如何进行混合调试

addon 编译

建立 addon 的编译 script

"scripts": {
 "start": "node index.js",
 "build:dev": "node-gyp -j 16 build --debug", // 编译带上debug信息
 "build": "node-gyp -j 16 build",
 "rebuild:dev": "node-gyp -j 16 rebuild --debug",
 "rebuild": "node-gyp -j 16 rebuild",
 "clean": "node-gyp clean"
  },

复制代码

建立 preLaunchTask

调试程序前,咱们须要预先编译好能够 debug 的 addon,所以咱们建立一个 preLaunchTask,选择 rebuild:dev, 其负责编译一个能够 debug 的 addon 版本

建立 launch.json

咱们新建立一个启动 node 的 launch,不过咱们这里使用 lldb 来启动 node, 配置以下

{
     "type": "lldb",
     "request": "launch",
     "name": "lldb:node",
     "program": "/Users/yj/.nvm/versions/node/v12.16.1/bin/node", // 指向node入科
     "args": ["examples/addon/index.js"], // 指向js入口
     "cwd": "${workspaceFolder}"
        },

复制代码

此时咱们启动 lldb:node 就能够进入 node 的 addon 进行 debug

这里存在的问题在于,咱们这里其实是使用 lldb 来调试 node 程序 (此时的 addon 其实是一个动态库),lldb 实际上对 js 的调试是无感知的,所以咱们这样实际是没法调试 js 的,在 js 里打下的断点也没法进入。

nodejs 调试

实际上 node 的 js 里的调试功能其实是经过 chrome debugger protocol 协议来实现的,所以咱们只须要启动 js 的时候,开启 inspector 协议就而后就能够 attach 到 js 上进行调试。 修改配置,开启 inspector 协议

{
     "type": "lldb",
     "request": "launch",
     "name": "lldb:node",
     "program": "/Users/yj/.nvm/versions/node/v12.16.1/bin/node",
     "args": ["--inspect-brk","examples/addon/index.js"], // 开启inspector协议
     "cwd": "${workspaceFolder}"
        },

复制代码

此时咱们从新启动 lldb:node, 发如今终端出来个 websocket 地址

此时有实际上有两种方式来调试 js 了

在 chrome 里开个 ws 的地址进行调试

此时咱们虽然能够在 chrome 里调试 js,在 vscode 里调试 c++,可是来回穿梭仍然不够方便

在 vscode 里调试 js

实际上当 node 开启 inspector 协议的时候,不只能够经过 ws attach 到 node 的 js 上,实际上也能够经过 http:port attach 到 js 上。实际上咱们的 ws 地址也是从这个 http:port 获取来的 nodejs 在开启 inspect 的时候默认会启动一个 inspect server,其地址为​http:127.0.0.1:${inspect\_port}​, 其 inspect_port 默认为 9229,固然也能够经过 node --inspect-brk --port:${inspect_port} 来指定其端口。 其暴露了一个接口​/json​, 经过该接口便可得到其对应的 websocket 地址

下面咱们来经过 vscode 来调试 js,首先建立一个 launch 任务,此时咱们选择 Node.js: attach

咱们选择经过 port 来 attach 到 js 上,配置以下

{
     "type": "node",
     "request": "attach",
     "name": "node:attach",
     "port": 9229, // 绑定到node.js默认的inspect的端口
     "skipFiles": [
     "<node_internals>/**"
          ]
     },

复制代码

此时咱们只须要启动 lldb:node 启动调试,其会自动的中止在第一行 js 代码上。这样咱们就实现了在 vscode 里混合调试 c++ 和 js

compound 模式

借助于 vscode 的 launch 的 compound 功能,咱们甚至能够避免手动的切换 debugger,达到真正的一键调试,配置以下

"compounds": [
    {
 "name": "node_c++",
 "configurations": ["lldb:node","node:attach"]
    }
  ]

复制代码

这样咱们点击 node_c++ 功能就能够实现一键调试

相关文章
相关标签/搜索