在使用本机节点插件时,如何自动下载外部(C ++)库?

时间:2017-08-19 23:49:43

标签: node.js node.js-addon

我想在我的原生Node插件中包含libpng。如何包含它,以便在安装我的库时,它会自动下载指定版本的libpng?是否可以使用npm的package.json?如果这不可能,那么在库中包含外部库源代码的可接受方式是什么?

2 个答案:

答案 0 :(得分:1)

对于跨平台解决方案,我建议您创建一个gyp文件来构建依赖库,并向package.json添加一个脚本以便为您下载。

我经常使用自己的原生插件模块来演示我给这些问题的答案。我自己的原生插件模块node-dvbtee演示了这一点。

您会在package.json内注意到以下内容:

  "scripts": {
    "preinstall": "npm install mkdirp && scripts/prepare-build.sh && node scripts/configure-build.js",
    "install": "node-gyp rebuild -j 8",
    "test": "mocha"
  },

这里重要的是preinstall部分的scripts部分。它调用scripts/prepare-build.sh,其中包含以下内容:

#!/bin/sh

cd "$(dirname "$0")"/..

if [ -e libdvbtee ]; then
    echo libdvbtee sources present
else
    git clone git://github.com/mkrufky/libdvbtee.git
fi

cd libdvbtee

if [ -e libdvbpsi/bootstrap ]; then
    echo libdvbpsi sources present
else
    rm -rf libdvbpsi
    git clone git://github.com/mkrufky/libdvbpsi.git
    cd libdvbpsi
    touch .dont_del
    cd ..
fi

如您所见,上面的脚本会检查libdvbtee目录是否存在。如果没有,它将从github克隆它。之后,它会检查是否存在完整的libdvbpsi来源。如果没有,它将从github克隆它们。

现在,对于gyp个文件:

我的项目将gyp文件存储在deps目录中。

libdvbpsi.gyp看起来像这样:

{
  'target_defaults': {
    'default_configuration': 'Debug',
    'configurations': {
      'Debug': {
        'defines': [ 'DEBUG', '_DEBUG' ],
        'msvs_settings': {
          'VCCLCompilerTool': {
            'RuntimeLibrary': 1, # static debug
          },
        },
      },
      'Release': {
        'defines': [ 'NDEBUG' ],
        'msvs_settings': {
          'VCCLCompilerTool': {
            'RuntimeLibrary': 0, # static release
          },
        },
      }
    },
    'msvs_settings': {
      'VCLinkerTool': {
        'GenerateDebugInformation': 'true',
      },
    },
    'include_dirs': [
      '../libdvbtee/libdvbpsi/src',
      '../libdvbtee/libdvbpsi/src/tables',
      '../libdvbtee/libdvbpsi/src/descriptors',
      '../libdvbtee/libdvbpsi'
    ],
    'defines': [
      'PIC',
      'HAVE_CONFIG_H'
    ],
  },

  'targets': [
    # libdvbpsi
    {
      'target_name': 'dvbpsi',
      'product_prefix': 'lib',
      'type': 'static_library',
      'sources': [
        '../libdvbtee/libdvbpsi/src/dvbpsi.c',
        '../libdvbtee/libdvbpsi/src/psi.c',
        '../libdvbtee/libdvbpsi/src/demux.c',
        '../libdvbtee/libdvbpsi/src/descriptor.c',
        '../libdvbtee/libdvbpsi/src/tables/pat.c',
        '../libdvbtee/libdvbpsi/src/tables/pmt.c',
        '../libdvbtee/libdvbpsi/src/tables/sdt.c',
        '../libdvbtee/libdvbpsi/src/tables/eit.c',
#       '../libdvbtee/libdvbpsi/src/tables/cat.c',
        '../libdvbtee/libdvbpsi/src/tables/nit.c',
        '../libdvbtee/libdvbpsi/src/tables/tot.c',
#       '../libdvbtee/libdvbpsi/src/tables/sis.c',
#       '../libdvbtee/libdvbpsi/src/tables/bat.c',
#       '../libdvbtee/libdvbpsi/src/tables/rst.c',
        '../libdvbtee/libdvbpsi/src/tables/atsc_vct.c',
        '../libdvbtee/libdvbpsi/src/tables/atsc_stt.c',
        '../libdvbtee/libdvbpsi/src/tables/atsc_eit.c',
        '../libdvbtee/libdvbpsi/src/tables/atsc_ett.c',
        '../libdvbtee/libdvbpsi/src/tables/atsc_mgt.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_02.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_03.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_04.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_05.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_06.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_07.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_08.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_09.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_0a.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_0b.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_0c.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_0d.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_0e.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_0f.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_10.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_11.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_12.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_13.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_14.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_1b.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_1c.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_24.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_40.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_41.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_42.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_43.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_44.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_45.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_47.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_48.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_49.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_4a.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_4b.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_4c.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_4d.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_4e.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_4f.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_50.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_52.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_53.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_54.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_55.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_56.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_58.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_59.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_5a.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_62.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_66.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_69.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_73.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_76.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_7c.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_81.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_83.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_86.c',
#       '../libdvbtee/libdvbpsi/src/descriptors/dr_8a.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_a0.c',
        '../libdvbtee/libdvbpsi/src/descriptors/dr_a1.c',
      ],
      'conditions': [
        ['OS=="mac"',
          {
            'xcode_settings': {
              'WARNING_CFLAGS': [
                '-Wno-deprecated-declarations'
              ]
            }
          }
        ]
      ],
      'cflags!': ['-Wdeprecated-declarations','-Wimplicit-function-declaration'],
      'cflags+': ['-Wno-deprecated-declarations','-Wno-implicit-function-declaration','-std=c99'],
    },
  ]
}

当然,此gyp文件中有许多特定于libdvbpsi和我的用例的细节。因此,您会注意到我们将为node.js addon模块构建的版本实际上并不需要库中的大量源文件。我们不打算构建的源文件通过在该行前面加上哈希#字符来注释掉。

我们将此库链接到我们当前正在构建的节点模块,方法是将其包含在node.js插件模块bindings.gyp的依赖关系部分中。这是我的插件模块中使用的那个:

{
  "targets": [
    {
      "target_name": "dvbtee",
      "sources": [
        "src/node-dvbtee.cc",
        "src/dvbtee-parser.cc"
      ],
      "dependencies": [
        'deps/libdvbtee.gyp:dvbtee_parser'
      ],
      "include_dirs": [
        "libdvbtee/usr/include",
        "libdvbtee/libdvbtee",
        "libdvbtee/libdvbtee/decode",
        "libdvbtee/libdvbtee/decode/table",
        "libdvbtee/libdvbtee/decode/descriptor",
        "<!(node -e \"require('nan')\")"
      ],
      'cflags': [ '-DDEBUG_CONSOLE=1' ],
      'cflags_cc': [ '-DDEBUG_CONSOLE=1', '-Wno-deprecated-declarations' ],
      'cflags!': [ '-fno-exceptions' ],
      'cflags_cc!': [ '-fno-exceptions', '-Wdeprecated-declarations' ],
      'conditions': [
        ['OS=="mac"', {
          'xcode_settings': {
            'WARNING_CFLAGS': [
              '-Wno-deprecated-declarations'
            ],
            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
          }
        }]
      ]
    }
  ]
}

如您所见,上面的deps/libdvbtee.gyp:dvbtee_parser部分列出了dependenciesdeps/libdvbtee.gyp:dvbtee_parser本身包含自己的dependencies部分:

  "dependencies": [
    'libdvbpsi.gyp:dvbpsi'
  ],

因此,当执行npm install时,npm将运行preinstall脚本来获取源,然后它将基于{{1}构建自定义libdvbpsi库然后,基于libdvbpsi.gyp构建自定义libdvbtee,这取决于该自定义libdvbtee.gyp库,最后它将构建并链接取决于{{}的node.js addon模块。 1}}库构建。

在我的特定情况下,在我们尝试构建库之前需要配置库。编写这些库所依赖的libdvbpsi头文件需要此步骤。我在下载源代码后运行的libdvbtee脚本中处理该步骤。在大多数情况下,您只需为每个库运行config.h,但这取决于您所包含的库。

这是一个跨平台的解决方案,前提是您正在构建的库本身就是跨平台的。

答案 1 :(得分:0)

您可以在package.json的scrips部分添加它。但是你必须要小心你的应用程序将被执行的所有设备。如ARM,Intel 32位或Intel 64位左右。你有选择,我只是在这里添加一些提示,你可以相应地放置你的代码。这里脚本将在npm install命令期间执行。  1.在脚本中,您必须检查机器类型并相应地下载库。

//package.json
{
      "scripts": {
          "preinstall": ""
          ,"install": ""
          ,"test" : ""
       }
}
  1. 在脚本中,您必须检查机器类型并相应地下载库,例如在脚本的安装部分中使用wget abc.so。你必须做一些脚本来为机器选择正确的lib并放在正确的位置。

  2. 如果您愿意,可以添加构建脚本,它将下载源代码并在运行中构建系统。
    git clone git://xyz/abc.git cd abc ./configure make make install

  3. 您还可以查找babel cli以进行源编译。 https://babeljs.io/docs/usage/cli/

  4. 所有这些都在脚本部分,预安装或安装或测试中。 在你的情况下,你更愿意选择第一种方式。