DEV Community

David Velho
David Velho

Posted on • Edited on

Stop-gap measure to debug a Native Node Addon on Windows

While working on building a project that includes a NodeJs addon using N-API for Windows (and *nix), I found that binaries built on my machine work but the same binaries do not work on another machine.

loading libtorrent on my machine

loading libtorrent on another machine

But the file(s) are all present. What is happening? The same behaviour was observed on Linux and MacOS machines other than mine.

I would have switched to Linux and used strace to see what was happening, but I wanted to see if Windows has any good alternatives. After some quick Google searching, I realized that I could use the built-in Visual Studio debugger.

Note: I assume that you have the Visual Studio environment setup for C++ development on windows, along with the required SDKs installed

The commands I used to load and test the libtorrent build are (in a NodeJs shell) -

const lib = require('./libtorrent.node');
Enter fullscreen mode Exit fullscreen mode

So I tried to find a Debug target (using the CMake extension that populates Visual Studio with stuff)

Debug targets

No luck. Next, I opened Visual Studio and tried to start a NodeJs process using the debugger -

Visual Studio debug menu

But the "Start Debugging" option was greyed out. However, the "Attach to Process" option is available. Choosing that option opens the following menu -

Attach to process menu

The Module window will be of interest to us

Visual Studio Module window

Notice the timestamp column. Lets sort the list by timestamp and focus on the rows with a timestamp -

Close-up of module window last few rows

This makes sense as we haven't loaded the addon yet. Let's load the addon through Node and check the window again

loading libtorrent

We see a few more entries. On observing them, we see the following:

  • libcrypto-3-x64.dll
  • libssl-3-x64.dll

Going through the dependencies, we see that our project's main dependency libtorrent depends on OpenSSL. Finally it clicked that I installed OpenSSL through choco

Solution 1: Bundle and distribute required DLLs

Let's try to bundle the required DLLs with the project

libtorrent with additional DLLs

And we see that libtorrent is successfully loaded

successfully loading libtorrent

But that's not a feasible solution. There might be scenarios where one cannot bundle multiple DLLs due to some restriction. How do we proceed?

Solution 2: If it works, it ain't stupid

We know that the project depends on libcrypto and libssl, but probably uses a few functions or items from them. To test this theory out, I modified my project's CMakeLists.txt file to fetch openssl from Github using CMake's built in (version 3.11 and later) FetchContent

The following is an extract of the CMakeLists.txt file:

include(FetchContent)
FetchContent_Declare(
    openssl
    GIT_REPOSITORY https://github.com/janbar/openssl-cmake.git
    SOURCE_DIR ${CMAKE_SOURCE_DIR}/lib/openssl
    GIT_TAG 392d455cd0b0fe992b312c9648eb5ea87e3afcea
)

FetchContent_MakeAvailable(openssl)
set(OPENSSL_ROOT_DIR ${CMAKE_SOURCE_DIR}/lib/openssl/*)

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(OPENSSL_CRYPTO_LIBRARY ${CMAKE_SOURCE_DIR}/build/_deps/openssl-build/crypto/Debug)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
    set(OPENSSL_CRYPTO_LIBRARY ${CMAKE_SOURCE_DIR}/build/_deps/openssl-build/crypto/Release)
endif()
Enter fullscreen mode Exit fullscreen mode

The statement to set OPENSSL_CRYPTO_LIBRARY can be optimised further

This resulted in the following files being generated -

Image description

the openssl binary is built as default behaviour that can be customized

libtorrent with statically linked openssl

Shaky cam courtesy of a friend

Top comments (0)