question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Compiling NAN Module with MinGW in an electron app

See original GitHub issue

Hey guys,

I have been looking around a lot for an awnser or a similar issue, I was able to use the MinGW generators with cmake-js try to compile a NAN module to be loaded in my electron app. Cmake-js is able to compile my node module. But when it comes to the linking phase it keeps telling me this error:

g++.exe: error: /DELAYLOAD:NODE.EXE: No such file or directory

I tried to set a fullpath to node. I have also read on the /DELAYLOAD feature and how people seem to go around it but without success. It works with vscompiler.

Here is the output of my compilation:

> cmake-js --debug -G "MinGW Makefiles" rebuild --target mag_calibration

[ 'C:\\Program Files\\nodejs\\node.exe',
  'C:\\Users\\ARA BaseStation\\Documents\\Code\\skycontrol-react\\boomerang\\node_modules\\cmake-js\\bin\\cmake-js',
  '--debug',
  '-G',
  'MinGW Makefiles',
  'rebuild',
  '--target',
  'mag_calibration' ]
info TOOL Using MinGW Makefiles generator, as specified from commandline.
info CMD CLEAN
info RUN cmake -E remove_directory "C:\Users\ARA BaseStation\Documents\Code\skycontrol-react\boomerang\build"
info CMD CONFIGURE
info RUN cmake "C:\Users\ARA BaseStation\Documents\Code\skycontrol-react\boomerang" --no-warn-unused-cli -G"MinGW Makefiles" -DCMAKE_JS_VERSION="5.3.2" -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_RUNTIME_OUTPUT_DIRECTORY="C:\Users\ARA BaseStation\Documents\Code\skycontrol-react\boomerang\build" -DCMAKE_JS_INC="C:\Users\ARA BaseStation\.cmake-js\electron-x64\v5.0.6\include\node;C:\Users\ARA BaseStation\Documents\Code\skycontrol-react\boomerang\node_modules\nan" -DCMAKE_JS_SRC="C:/Users/ARA BaseStation/Documents/Code/skycontrol-react/boomerang/node_modules/cmake-js/lib/cpp/win_delay_load_hook.cc" -DNODE_RUNTIME="electron" -DNODE_RUNTIMEVERSION="5.0.6" -DNODE_ARCH="x64" -DCMAKE_JS_LIB="C:\Users\ARA BaseStation\.cmake-js\electron-x64\v5.0.6\x64\node.lib" -DCMAKE_SHARED_LINKER_FLAGS="/DELAYLOAD:NODE.EXE"
Not searching for unused variables given on the command line.
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: C:/MinGW/bin/gcc.exe
-- Check for working C compiler: C:/MinGW/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/ARA BaseStation/Documents/Code/skycontrol-react/boomerang/build
info CMD BUILD
info RUN cmake --build "C:\Users\ARA BaseStation\Documents\Code\skycontrol-react\boomerang\build" --config Debug --target mag_calibration
Scanning dependencies of target mag_calibration
[ 50%] Building CXX object mag-calibration/CMakeFiles/mag_calibration.dir/src/NativeExtension.cpp.obj
[ 50%] Building CXX object mag-calibration/CMakeFiles/mag_calibration.dir/src/mag_calibration_wrapper.cpp.obj
[ 50%] Building CXX object mag-calibration/CMakeFiles/mag_calibration.dir/src/mag_calibration.cpp.obj
[ 50%] Building CXX object mag-calibration/CMakeFiles/mag_calibration.dir/__/node_modules/cmake-js/lib/cpp/win_delay_load_hook.cc.obj
[100%] Linking CXX shared library ..\mag_calibration.node
g++.exe: error: /DELAYLOAD:NODE.EXE: No such file or directory
g++.exe: error: C:UsersARA BaseStation.cmake-jselectron-x64v5.0.6x64node.lib: No such file or directory
mag-calibration\CMakeFiles\mag_calibration.dir\build.make:134: recipe for target 'mag_calibration.node' failed
mingw32-make.exe[3]: *** [mag_calibration.node] Error 1
CMakeFiles\Makefile2:410: recipe for target 'mag-calibration/CMakeFiles/mag_calibration.dir/all' failed
mingw32-make.exe[2]: *** [mag-calibration/CMakeFiles/mag_calibration.dir/all] Error 2
CMakeFiles\Makefile2:417: recipe for target 'mag-calibration/CMakeFiles/mag_calibration.dir/rule' failed
mingw32-make.exe[1]: *** [mag-calibration/CMakeFiles/mag_calibration.dir/rule] Error 2
Makefile:254: recipe for target 'mag_calibration' failed
mingw32-make.exe: *** [mag_calibration] Error 2
ERR! OMG Process terminated: 2
npm ERR! code ELIFECYCLE
npm ERR! errno 1

Here is my CMakeList.txt:

PROJECT(mag_calibration)

# BOOMERANG
add_library(${PROJECT_NAME}
                  SHARED
                  src/NativeExtension.cpp
                  src/mag_calibration_wrapper.cpp
                  src/mag_calibration.cpp
                  ${CMAKE_JS_SRC})


include_directories(
        ${CMAKE_CURRENT_SOURCE_DIR}/../boomerang/boomerang-lib/src
        ${CMAKE_CURRENT_SOURCE_DIR}/../boomerang/boomerang-lib/src-pc
        ${CMAKE_CURRENT_SOURCE_DIR}/../boomerang/include/
        ${CMAKE_CURRENT_SOURCE_DIR}/../boomerang/common-library-cpp/src/
        ${CMAKE_CURRENT_SOURCE_DIR}/../boomerang/common-library-cpp/src-stm32/
        ${CMAKE_CURRENT_SOURCE_DIR}/../boomerang/common-library-cpp/src-pc/
        ${CMAKE_CURRENT_SOURCE_DIR}/../boomerang/common-library-cpp/
        ${CMAKE_JS_INC} ../nan
)

set_target_properties(${PROJECT_NAME}
    PROPERTIES
    PREFIX ""
    SUFFIX ".node"
    CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../targets/mag-calibration"
    LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/../targets/mag-calibration"
    RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/../targets/mag-calibration"
)

target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC})

TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${CMAKE_JS_LIB})

Here is the call i invoke for compilation: cmake-js --debug -G "MinGW Makefiles" rebuild --target mag_calibration

Thanks a mega bunch.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:2
  • Comments:9

github_iconTop GitHub Comments

4reactions
riccardo89commented, Jul 11, 2020

hi!

with the insights of @mjmacleod (thanks a lot!!!) I have been able to compile a n-api node module (using node-addon-api) that links statically a few C libraries compiled on linux for windows with mingw compiler without dependencies on the MSVC toolchain, some advices here:

  1. it is paramount to use n-api, otherwise there would be problems down the line, for instance while linking the generated .a file (from the .def), this will also make your modules node and electron version independent.

  2. for windows app packaging I use electronuserland/builder:wine and here you find my CMakeLists.txt file for one of my libs:

cmake_minimum_required(VERSION 3.9)
cmake_policy(SET CMP0042 NEW)
set (CMAKE_CXX_STANDARD 11)
add_definitions(-std=c++11)

# N-API DEFINITIONS
add_definitions(-DNAPI_VERSION=2)

project (mylib VERSION 1.0.0)

# check if wine is installed, in that case we are on linux
# but we are building for windows
execute_process(COMMAND wine --version
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
        OUTPUT_VARIABLE IS_WINE
        )

# CROSS PLATFORM
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    option(USE_CLANG "build application with clang" ON)
    set(MAC TRUE)
    set(LIB_NAME ${PROJECT_NAME}-darwin-10.6-amd64.a)
    set(LIB_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mac)
    add_definitions(-DDARWIN=1)
endif()

if ((${CMAKE_SYSTEM_NAME} MATCHES "Windows") OR (NOT IS_WINE STREQUAL ""))
    set(WIN TRUE)
    set(LIB_NAME ${PROJECT_NAME}-windows-7.0-amd64.lib)
    set(LIB_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/windows)

    # link windows specific delay load hook and node symbols definition lib
    set(WIN_DELAY_LOAD_HOOK ${CMAKE_CURRENT_SOURCE_DIR}/hook/win_delay_load_hook.cc)
    set(LIBNODE ${CMAKE_CURRENT_SOURCE_DIR}/libnode.a)
    
    # use win32 compiler otherwise in the final product the pthread library for windows will be missing 
    # and the electron app won't be able to load the addon. Furthermore, you should also link libgcc and libstdc++
    # if your electron app uses an installer (e.g NSIS) to reduce you lib size you may also dynamically install 
    # these dlls on windows during electron app installation, your choice
    set(CMAKE_CXX_COMPILER "/usr/bin/x86_64-w64-mingw32-g++-win32")
    set(CMAKE_C_COMPILER "/usr/bin/x86_64-w64-mingw32-gcc-win32")
    set(CMAKE_CXX_STANDARD_LIBRARIES "-static-libgcc -static-libstdc++ ${CMAKE_CXX_STANDARD_LIBRARIES}")

    add_definitions(-DWIN=1)
endif()

if (${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND (IS_WINE STREQUAL ""))
    option(USE_CLANG "build application with clang" ON)
    set(LINUX TRUE)
    set(LIB_NAME ${PROJECT_NAME}-linux-amd64.a)
    set(LIB_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/linux)
    add_definitions(-DLINUX=1)
endif()

# BUILD
file(GLOB SOURCE_FILES *.cc)

include_directories(${LIB_DIRECTORY})
link_directories(${LIB_DIRECTORY})

add_library(
  ${PROJECT_NAME} SHARED
  ${LIB_DIRECTORY}/${LIB_NAME}
  ${SOURCE_FILES}
  ${WIN_DELAY_LOAD_HOOK}
)

# INCLUDE N-API WRAPPERS
execute_process(COMMAND node -p "require('node-addon-api').include"
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
        OUTPUT_VARIABLE NODE_ADDON_API_DIR
        )
string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})

# FINALIZE
set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC})
target_link_libraries(${PROJECT_NAME} ${LIB_DIRECTORY}/${LIB_NAME} ${LIBNODE} ${CMAKE_JS_LIB})
  1. then in your .cc file you could use compiler directives to import the proper library based on the os:
#ifdef LINUX
extern "C" {
	#include "linux/mylib-linux-amd64.h"
}
#endif

#ifdef DARWIN
extern "C" {
	#include "mac/mylib-darwin-10.6-amd64.h"
}
#endif

#ifdef WIN
extern "C" {
	#include "windows/mylib-windows-7.0-amd64.h"
}
#endif

Hope this will help!!! 😉

2reactions
riccardo89commented, Aug 3, 2020

Hi @gdorionara, you are welcome 😃!!!

So as far as I have understood the def file is guaranteed to be pretty stable (hence the motivation for using n-api) so you may always use the same one, I have actually had a confirmation of this by updating my node version from node.js 10 to node.js 14 and by updating the NAPI version from 2 to 3, and the libraries kept working flawlessly without any update to the libnode.a (so by using the same .def file).

By no means I am saying that there won’t be situations where you may need an updated version of the def file (for instance use new features added to a newer node version), but in my case it was not needed, please if anyone knows more about it or it has automated it with CMAKE let us know!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Running Native Code in Electron and the Case for ... - PSPDFKit
Electron has first-class support for native Node.js modules (also called ... a cross-platform command-line tool for compiling native modules using the GYP ...
Read more >
Create a node.js native extension on Windows - Stack Overflow
I'm fine with compiling through g++ on mingw, I don't need to use Visual Studio. Also, where do I find the header files...
Read more >
cmake-js - Bountysource
CMake.js - a Node.js/io.js native addon build tool ... use the MinGW generators with cmake-js try to compile a NAN module to be...
Read more >
Building Qt 5 from Git - Qt Wiki
All desktop platforms. Git (>= 1.6.x); Perl (>=5.14); Python (>=2.6.x); A working C++ compiler. For more detailed information, see Building ...
Read more >
Native Node Modules | Electron
Native Node.js modules are supported by Electron, but since Electron has a different application ... was compiled against a different Node.js version using...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found