How to debug node.js addons in Visual Studio
While working on CloudCV I encountered problems in node.js addon written in native code. For CloudCV I use node.js with C++ Addon to separate high-performance algorithms (C++) from high-level networking API which node provides.
In this tutorial I’m going to reveal best practices on debugging C++ Addons for Node.js (0.12) using Visual Studio 2013.
Continue reading if you want to read in details why this works.
This article is valid for Node.js version 0.12. It should also works fine for further releases, however few things may change. I will try to keep this post up to date. Please, feel free to drop a comment for this article or write me on @cvtalks if you have troubles following this tutorial.
Before we start
You will need a Visual Studio 2013 (Express edition should be enough). Also, please come and grab Node.js source] code. We will use it later to build Debug configuration of Node.js. I assume you already have production (Release) version of Node and NPM as we will need node-gyp to generate and build C++ Addon project. So please ensure you’ve installed them before going to next step:
|
|
Build Debug configuration of node.js
This is very straighforward step.
- Download Node.js source] code.
- Extract it somewhere to your filesystem. For demonstration, I assume it will be in
c:\Develop\node-v0.12.0
- Navigate to
c:\Develop\node-v0.12.0
and runvcbuild.bat debug nosign x64
. This batch script will build Debug configuration of node.js for 64-bit architecture (if you’re on 32-bit platform omit this flag). Anosign
flag tells to skip executable signing which is ok since we’re not going to distribute it, and finallydebug
forces compiler to generate debug symbols for node executable.
If everything goes fine, you should see the following output:
|
|
If you have problems on this step, please refer to building node.js official documentation.
Building Debug configuration of C++ Addon
A C++ Addon for nodejs is nothing but ordinary DLL. Therefore Visual Studio can load it and let you do step-by-step debugging inside node.js app. Let’s start with simple scenario. I will use Pi estimation example from NaN project.
Your C++ Addon code can look as follows:
|
|
And you also should have gyp file which tells node-gyp how to build your addon:
|
|
Assuming you’re in root C++ addon directory, you can now generate a solution for Visual Studio to build your addon:
|
|
What is really important here, is --nodedir="c:\Develop\node-v0.12.0"
flag, which indicates to link against node in specified
folder rather than system wide available.
This is very important to match Debug node with Debug C++ Addon, otherwise you will have linker issues caused by inconsistent CRT's.
After node-gyp finishes, a .node file (this is .dll, don’t be misleaded by .node extension) will be generated in /build/Debug/ folder.
Now it’s time to write a small node.js script that utilizes our addon:
|
|
You may wonder now, how to debug it. Patience, we’re almost there.
- Navigate to
build/
directory of your C++ Addon and open solution file. - Ensure that you have active Debug configuration.
- Navigate to project properties and open Debugging tab there.
- Modify command name to “c:\Develop\node-v0.12.0\Node.exe” (Change this path if you extracted node somewhere else)
- Set a command argument to full name of your node.js script.
- Change working directory to a place where your script is. This step important when you have complex nodej.js application with dependencies.
- Set breakpoint somewhere in your C++ Addon code.
- Now hit ‘Debug’ (F5) and enjoy!
How it works
When building Debug builds, Visual Studio trades speed for easy debugging. This means not only slower code, but it also preserves debug symbols (a table of function addresses/names/file locations). When you start a debugger on process, VS attachs to it and tries to load symbols for this binary and all dynamically loaded libraries it uses.
As a consequence, debug symbols for C++ addon is being loaded which allows you to see program execution location in your IDE, do step-by-step debugging and change/rebuild/debug as usual.
Conclusion
I hope you find this post useful. From my experience debugging node.js <-> C++ interop can be nasty. Personally I follow this scenario for debugging CloudCV C++ backend. This saves a lot of time and nerves. Unleash your node.js with C++ and happy debugging!