简体   繁体   中英

Linking Boost within Node.js Module with node-gyp

I'm trying to create a node.js add-on that is a simple wrapper to access perl regular expressions from the Boost library project.

I'm running running OSX 10.9.2, and i'm also not a c++ developer at all so the tooling is not familiar.

My project looks as follows

boost.cc

#include <node.h>
#include <v8.h>

#include <boost/regex.hpp>

using namespace v8;

Handle<Value> Match(const Arguments& args) {
  HandleScope scope;

  if (args.Length() < 2) {
    ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
    return scope.Close(Undefined());
  }

  if (!args[0]->IsString())
  {
    ThrowException(Exception::TypeError(String::New("Regex agrument 1 must be a string")));
    return scope.Close(Undefined());
  }

  if (!args[1]->IsString())
  {
    ThrowException(Exception::TypeError(String::New("Target agrument 2 must be a string")));
    return scope.Close(Undefined());
  }

  v8::String::Utf8Value param0(args[0]->ToString());
  v8::String::Utf8Value param1(args[1]->ToString());

  std::string sre = std::string(*param0);
  std::string s = std::string(*param1); 

  try
  {
    boost::cmatch matches;
    boost::regex re(sre, boost::regex::icase);

    if (boost::regex_match(s.c_str(), matches, re))
    {
      return scope.Close(Boolean::New(true));
    } 
    else
    {
      return scope.Close(Boolean::New(false));
    } 
  }
  catch (boost::regex_error& e)
  {
    ThrowException(Exception::TypeError(String::New("Regex is not a valid regular expression")));
    return scope.Close(Undefined());
  }

  return scope.Close(Boolean::New(false));
}

void init(Handle<Object> exports) {
  exports->Set(String::NewSymbol("match"),
      FunctionTemplate::New(Match)->GetFunction());
}

NODE_MODULE(boost, init)

binding.gyp

{
  "targets": [
    {
      "target_name": "boost",
      "sources": [ "boost.cc" ],
      "include_dirs": [
              "/usr/local/include/boost",
            ],
            "libraries": [
                "/usr/local/lib/libboost_regex.dylib"
            ]
        }
    ]
}

app.coffee

addon = require('../addons/boost/build/Release/boost')
console.log(addon.match("(?<!street)name", "StreetName"))

Running node-gyp rebuild --verbose results in a successful build of the add-on. When run the app though i receive the following error:

dyld: lazy symbol binding failed: Symbol not found: __ZN5boost9re_detail12perl_matcherIPKcSaINS_9sub_matchIS3_EEENS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEE14construct_initERKNS_11basic_regexIcSA_EENS_15regex_constants12_match_flagsE
  Referenced from: <projects dir>/addons/boost/build/Release/boost.node
  Expected in: dynamic lookup

dyld: Symbol not found: __ZN5boost9re_detail12perl_matcherIPKcSaINS_9sub_matchIS3_EEENS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEE14construct_initERKNS_11basic_regexIcSA_EENS_15regex_constants12_match_flagsE
  Referenced from: <projects dir>/addons/boost/build/Release/boost.node
  Expected in: dynamic lookup

I've played around with the binding.gyp and otool for a few hours but i'm clearly out of my depth here.

otool on the output gives me the following:

otool -L build/Release/boost.node
build/Release/boost.node:
    /usr/local/lib/libboost_regex.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 60.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
    /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 2577.0.0)

I installed the boost library with brew (brew install --without-python boost) and all the dynamic libraries seem to be there.

My issue i guess is similar to this one: node-gyp on OSX 10.7.5 -- dyld: lazy symbol binding failed: Symbol not found - but i had no luck with that fix.

I can get a basic add-on running with no dependencies, it just appears i can't link the Boost libs properly using node-gyp etc.

Any help would be much appreciated!

The answer was to compile the node add-on using c++11. A couple of tweaks to the binding.gyp was all that was required.

binding.gyp

{
  "targets": [
    {
      "target_name": "boost",
      "sources": [ "boost.cc" ],
      "include_dirs": [
              "/usr/local/include/boost",
            ],
            "libraries": [
                "/usr/local/lib/libboost_regex.dylib"
            ],
            "cflags_cc!": [ "-fno-rtti", "-fno-exceptions" ],
            "cflags!": [ "-fno-exceptions" ],
            "conditions": [
                [ 'OS=="mac"', {
                    "xcode_settings": {
                        'OTHER_CPLUSPLUSFLAGS' : ['-std=c++11','-stdlib=libc++', '-v'],
                        'OTHER_LDFLAGS': ['-stdlib=libc++'],
                        'MACOSX_DEPLOYMENT_TARGET': '10.7',
                        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
                    }
                }]
            ]
        }
    ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM