Search code examples
javascriptc++node.jsvisual-studionode-gyp

Auto-update path to node-gyp include files in a Visual Studio C++ project


I'm trying to convert a project that compiles just fine on MacOS and Linux (Raspbian in particular) so that it will compile on Windows. (Full code here: https://github.com/kshetline/rpi-acu-rite-temperature)

After much grief (Like somehow the Node 12 I'd installed going away and getting replaced by Node 8 without my knowledge, and on Windows C++ long and int are both 32-bit? Really!?) I've finally made the code to compile using both node-gyp and Visual Studio 2019, but the Visual Studio set-up is fixed to a specific version of Node in a way that I don't like.

Here's my CppProperties.json file:

{
  "configurations": [
    {
      "inheritEnvironments": [
        "msvc_x86"
      ],
      "name": "x86-Debug",
      "includePath": [
        "${env.INCLUDE}",
        "${env.LOCALAPPDATA}\\node-gyp\\Cache\\12.16.1\\include\\node\\**",
        "${workspaceRoot}\\**"
      ],
      "defines": [
        "WIN32",
        "_DEBUG",
        "NAPI_CPP_EXCEPTIONS",
        "UNICODE",
        "_UNICODE",
        "USE_FAKE_PIGPIO"
      ],
      "intelliSenseMode": "windows-msvc-x86"
    }
  ]
}

I don't want to have to put a specific version of Node in my include path, but I don't know how to make this work without it. I can't even make it work for a specific major version of Node by using 12.* or 12.** -- wildcards don't seem to work for me there.

I see no Windows environment variable that would let me use something like, say, ${env.NODE_VERSION}, and AFAIK there's no VS pre-defined variable that would handle this either.

I could use my own environment variable, but that would have to be manually updated, which is what I'm trying to avoid.

Does Visual Studio have a way that I could script an update, like somehow doing the command node --version, stripping off the leading letter 'v' from the output, and then putting the result into an environment variable?

Any other possible solutions?

Update:

I changed the set-up of my Visual Studio project by starting with a generic command-line app, and the configuration works totally differently, with no CppProperties.json file at all, but the issue is still basically the same -- I now have $(LOCALAPPDATA)\node-gyp\Cache\12.16.1\include\node entered into a config dialog instead.


Solution

  • An addon using node-addon-api must, at compile time, target a precise version of node.

    That's because N-API is itself "versioned", (with a single digit macro, NAPI_VERSION, currently from 1 to 5, plus the special value NAPI_VERSION_EXPERIMENTAL=2147483647)

    As you can see, for example, in the N-API Version Matrix the version 4 is available in node v10.16.0 but NOT in some older v10 releases.

    The addon is "retro-linked" (I don't know the name of that technique) to node.exe, and that link is a "delay load" one. That trick allows the addon to use the N-APIfunctions that are in the host executable, even if it's not "node.exe" (hence the use of win_delay_load_hook.cc).

    As for CppProperties.json file, it is my understanding that it's only used by Intellisence and is not related to headers used at compile time.

    You can force node-gyp to use a specific version of node, unrelated to the current version installed on the machine, with the --target option to the configure command.

    Another useful option is --devdir, which allows to get rid of the infamous (afaic) %localappdata%\node-gyp\Cache root directory.

    All the node-gyp command options are here

    Please, dear node/node_gyp/N-API experts reading this, don't hesitate to signal/fix errors in that answer.