kshetline
kshetline

Reputation: 13700

Working with node-gyp and C++, is there a way to make a dependency on a particular library optional?

Automatically optional too, simply by testing for the presence of the library, avoiding making the user pass arguments or define environment variables or the like.

I'm working on making a Raspberry Pi project of mine, a project that depends on GPIO, compatible with the Raspberry Pi 5. (The Raspberry Pi 5, in general, has caused a lot of grief due to a new GPIO chipset.)

Having reached the point where I'd solved all of my own GPIO issues, I had left to handle one library of someone else's in need of upgrade. I could, of course, just take my own fork of their project and go my own merry way now that I have working code, but I'd like to offer what I've done as a pull request.

There's one thing now that could be a sticking point, however, which I'd like to avoid if possible. I've introduced a new dependency on the libgpiod library.

I'm pretty sure the original author wouldn't want to deal with that. I'd like for this new code to compile on a Raspberry Pi 3 or 4 without libgpiod having been installed, but take full advantage of libgpiod if present.

Here's my binding.gyp file:

{
  "targets": [
    {
      "variables": {
        "dht_verbose%": "false"
      },
      "target_name": "node_dht_sensor",
      "sources": [
        "src/bcm2835/bcm2835.c",
        "src/node-dht-sensor.cpp",
        "src/dht-sensor.cpp",
        "src/util.cpp",
        "src/abstract-gpio.cpp", // <-- My code to handle GPIO using either bcm2835 or libgpiod
      ],
      "include_dirs": [
        "<!@(node -p \"require('node-addon-api').include\")"
      ],
      "dependencies": [
        "<!(node -p \"require('node-addon-api').gyp\")"
      ],
      'libraries': [
        '-lgpiod' // <-- New dependency
      ],
      "defines": [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
      "conditions": [
        ["dht_verbose=='true'", {
          "defines": [ "VERBOSE" ]
        }]
      ]
    }
  ]
}

Here's the start of my abstract-gpio.cpp:

#include "abstract-gpio.h"

#include <algorithm>
#include "bcm2835/bcm2835.h"
#include <fstream>
#include <gpiod.h> // <-- What to do here to make this optional? Can node-gyp
#include <regex>   //     conditionally create a symbol for #ifndef-ing here?
#include <stdio.h>
#include <string>

My C++ skills are rusty at best. Until now I hadn't touched my own C++ code for five years, and five years ago I hadn't touched C++ for well over a decade.

node-gyp? I've merely followed examples and simple recipes at this point.

The big trick is that consumers of this library will use this library via npm install node-dht-sensor. I don't want the user to have to worry about libgpiod unless they're using a Raspberry Pi and have a good reason to install it.

Is there some combination of node-gyp options and perhaps, if needed, dummy libgpiod C++ stubs (that won't interfere with the real libgpiod if present) that can solve this problem for me?

Update:

Here's a somewhat, but not fully satisfactory solution, which requires a user to install the module like this:

npm install node-dht-sensor --use_libgpiod=true

...if they need (or want... this does work on a RPi 4 too) to use libgpiod, allowing the standard installation without the extra parameter to impose no new library dependencies.

{
  "targets": [
    {
      "variables": {
        "dht_verbose%": "false",
        "use_libgpiod%" : "false"
      },
      "target_name": "node_dht_sensor",
      "sources": [
        "src/bcm2835/bcm2835.c",
        "src/node-dht-sensor.cpp",
        "src/dht-sensor.cpp",
        "src/util.cpp",
        "src/abstract-gpio.cpp",
      ],
      "include_dirs": [
        "<!@(node -p \"require('node-addon-api').include\")"
      ],
      "dependencies": [
        "<!(node -p \"require('node-addon-api').gyp\")"
      ],
      "defines": [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
      "conditions": [
        ["dht_verbose=='true'", {
          "defines": [ "VERBOSE" ]
        }],
        ["use_libgpiod=='true'", {
          "defines": [ "USE_LIBGPIOD" ],
          'libraries': [
            '-lgpiod'
          ]
        }]
      ]
    }
  ]
}

What I'd really like to do, however, if it's at all possible, is to replace "use_libgpiod=='true'" with something automatic, the moral equivalent of "available(libgpiod)" or "exists('/usr/include/gpiod.h')", in case any such node-gyp capability exists which simply can't be easily found in the documentation.

Upvotes: 0

Views: 44

Answers (0)

Related Questions