Symbol not found: _libintl_gettext - c++

I am trying to create a NodeJS module using C++ and node-gyp. The package depends on GNU's Gettext library. I am currently using Mac OS X Mountain Lion. I have tried installing the package myself via manual efforts, via Homebrew, and even via Fink.
The program works via Terminal.app and the package compiles. I can use the .node module just fine, except until I use a method in the library that uses gettext. I get the following errors in REPL and then REPL exits.
dyld: lazy symbol binding failed: Symbol not found: _libintl_gettext
Referenced from: /Users/KevinMartin/Dropbox/www/node-locale/build/Release/locale.node
Expected in: dynamic lookup
dyld: Symbol not found: _libintl_gettext
Referenced from: /Users/KevinMartin/Dropbox/www/node-locale/build/Release/locale.node
Expected in: dynamic lookup
Trace/BPT trap: 5
Thanks in advance.

This is probably happening because you are not listing libintl as a library to be dynamically linked. You need to add something like:
{
"targets": [
{
"target_name": "...",
"sources": ["..."],
"libraries": ["/path/to/gettext/lib/libintl.a"]
}
}
to your binding.gyp file. libintl isn't being linked in your app, statically or dynamically, that is why you get the symbol error.
Edit:
You can probably also do something like:
{
"targets": [{
"target_name": "...",
"sources": [
"..."
],
"link_settings": {
"libraries": ["libintl.8.dylib"]
}
}]
}

Related

dyld[49745] missing symbol called using c++ swig with node.js by calling a function out of the library

I try to create an example using SWIG and NodeJS on my M1 (arm64) Mac,
but I want to mention this as early as possible:
this issue appears also on an Intel (x64) Mac.
I create my simple example Files like this:
example.h
#pragma once
class Die
{
public:
Die();
~Die();
int foo(int a);
};
Die* getDie();
//to test if the issue also appears getting a simple functiom without any class context.
extern "C"
{
bool getFoo();
}
here is the implementation.
example.cpp
#include <iostream>
#include "example.h"
int Die::foo(int a)
{
std::cout << "foo: running fact from simple_ex" << std::endl;
return 1;
}
Die::Die()
{
}
Die::~Die()
{
}
// out of Class Context
Die* getDie()
{
return new Die();
}
extern "C"
{
bool getFoo()
{
return true;
}
}
my Swig interface is as follows:
example.i
%module example
%{
#include "example.h"
%}
%include "example.h"
then i create my example_warp.cxx file. But as actually the 4.0.2 Version of Swig is not compatible with NodeJs v16.0.0 (read SWIG support for NodeJS v12 #1520 and Prepare SWIG for Node.js v12 #1746).
Therefore i needed to build swig from source using master branch with the current version (4.1.0). Please keep that in mind.
Swig Command:
swig -Wall -c++ -javascript -node example.i
Here now some files preparing to create the .node file
package.json
{
"name": "SwigJS",
"version": "0.0.1",
"scripts": {
"start": "node index.js",
"install": "node-gyp clean configure build"
},
"dependencies": {
"nan": "^2.16.0",
"node-gyp": "^9.0.0"
},
"devDependencies": {
"electron-rebuild": "^3.2.7"
}
}
the package.json i got from a mate as an example an edited it to work with my project so there may be some lines not really needed by me.
binding.gyp
{
"targets": [
{
"target_name": "SwigJS",
"sources": [ "example_wrap.cxx" ],
"include_dirs" : [ "<!(node -e \"require('nan')\")" ]
}
]
}
now i build my SwigJS.node file using:
node-gyp configure
node-gyp build
it runs through without any errors.
Now i try to access the node-file in my JavaScript but i always get the error message:
missing symbol called
index.js
const Swigjs = require("./build/Release/SwigJS.node");
console.log("exports :", Swigjs); //show exports
die = Swigjs.getDie(); //try to get the Class
console.log(die.foo(5)); //call a function from the class
the output looks like this:
[Running] node "/Users/rolf/Documents/SwigJS/index.js"
exports : {
getDie: [Function (anonymous)],
getFoo: [Function (anonymous)],
Die: [Function: Die]
}
dyld[49745]: missing symbol called
[Done] exited with code=null in 0.12 seconds
What i have tried to find the error:
tried to build the .node file on an x64 architecture to check if it is an arm topic with NodeJS v16:17 on an Intel x64 Mac from a mate.
installed NodeJS 16.0.0 (first version supporting arm64 on mac)
as the Github Issues suggest NodeJS version 12 tried to build and run this on an x64 Intel Mac with NodeJS v12.13.0
tried to force x64 architecture leading to different error but because of incompatible library (x64) using a arm64 mac
all of it (except last mentioned) ended with the same result "missing symbol called"
help would be appreciated big.
Your question is an interesting take on a FAQ on this site: What is an undefined reference/unresolved external symbol error and how do I fix it?.
The role of SWIG is indeed to generate glue code between Node.js and C++ code. But it does only that. If you inspect the .dylib file that is associated with your NodeJS module using the nm command, you will see that it has Undefined references to the C++ functions it wraps.
This is by design. SWIG expects that the code it wraps is somehow already loaded into memory.
There are three approaches to do so:
Compile example.cpp directly into the SWIG wrapper. Or compile it to a static library first (example.a) and link that statically into the wrapper. I think it suffices to add example.cpp to the sources section of binding.gyp
Compile example.cpp into a library (example.dylib) and dynamically link it to the SWIG wrapper. I have not used GYP myself yet, but I think it means adding the following to your targets entry in bindings.gyp:
'link_settings': {
'libraries': [
'-lexample',
],
},
Compile example.cpp into a library (example.dylib) and use dlopen to load it explicitly. This puts a tremendous burden on your users and is very hard to debug. Do not do this.

Node-gyp Library not loaded: /usr/local/lib/libmtp.9.dylib

I have been attempting to make a nodejs-native-addon which uses libmtp to carry out certain functions. I have been successful in the building the app but the app is throwing Library not loaded: /usr/local/lib/libmtp.9.dylib. Referenced from: /path/build/Debug/nbind.node. Reason: image not found error when I try to run it on another macbook where the libmtp isn't installed.
This is my binding.gyp file:
{
"targets": [
{
"includes": [
"auto.gypi"
],
"sources": [
"src/native/mtp.cc"
],
"link_settings": {
"libraries": [
"-lmtp"
],
},
}
],
"includes": [
"auto-top.gypi"
],
}
I even attempted to include the dylib file in the libraries option
"link_settings": {
"libraries": [
"<(module_root_dir)/src/native/lib/libmtp.9.dylib"
]
}
but the app fails to start with the Library not loaded: /usr/local/lib/libmtp.9.dylib. Referenced from: /path/build/Debug/nbind.node. Reason: image not found error.
Any help will be appreciated.
The error is indicating that the library libmtp.9.dylib cannot be found in the standard library include path /usr/local/lib
Try setting the environment variable LD_LIBRARY_PATH to point to the location where you have the libmtp.9.dylib before running the node.
One solution would be to create a symlink in a known rpath like /usr/local/lib manually to your built library. Not ideal but it may provide a workaround for at least having successful builds in development.
ln -s <absolute_path>/src/native/lib/libmtp.9.dylib /usr/local/lib/libmtp.9.dylib
This allows the binding.gyp file to find the library without it needing to configure an rpath with whatever process is throwing the error. This is easier in my opinion than tracking down the binding.gyp trace.

Using node-gyp Predefined Variable PRODUCT_DIR

In binding.gyp I want to set like this:
"libraries": [ "-Wl,-rpath,<working directory>/build/Release/" ]
I am using the following configuration to do the same:
"libraries": [ "-Wl,-rpath,<!(pwd)/build/Release/" ]
This works but the problem with this is that, it would not work on Windows or wherever pwd is not available and also this is not the best option as there is already a predefined variable PRODUCT_DIR available in node-gyp to achieve this. Strangely I am not able to use this variable PRODUCT_DIR.
I tried following options but no luck. error says Library not loaded: #rpath/<lib>.dylib (rpath is not getting set):
"libraries": [ "-Wl,-rpath,>(PRODUCT_DIR)/build/Release/" ]
"libraries": [ "-Wl,-rpath,<(PRODUCT_DIR)/build/Release/" ]
"libraries": [ "-Wl,-rpath,>(PRODUCT_DIR)"]
"libraries": [ "-Wl,-rpath,<(PRODUCT_DIR)"]
When i tried printing by "<!(echo <(PRODUCT_DIR) 1>&2)" it says builddir: command not found. Looks like variable has value builddir.
Shouldn't it print the target directory instead of builddir ? or builddir means something for compiler ?
Am I not using this variable properly or is there any other variable available that I should be using ?
PRODUCT_DIR behaves really weird, I got to say. I avoid it wherever possible. Often by writing external build scripts with plain node.
The reason why you can't "<!(echo <(PRODUCT_DIR) 1>&2)" is that is some kind of special variable to node-gyp.
However you are using the right format, like here...
{
'files': [ '<(PRODUCT_DIR)/libzip.dll' ],
'destination': '<(module_path)'
}
My guess though is that you need to...
"variables": {
"YOUR_DIR: "<(PRODUCT_DIR)/build/Release/"",
"your_libs": "-Wl,-rpath,<(CURRENT_DIR) ]"
}
You know, it's Python, we don't know about :)

Derelict3 D bindings on OS X

I just want to make a little test with GLFW3 D binding.
I create a new package using
dub init glfw3Test
Then I wrote a little test in glfw3Test\source\app.d
import derelict.glfw3.glfw3;
void main()
{
// Load the GLFW 3 library.
DerelictGLFW3.load();
if(DerelictGLFW3.isLoaded)
{
// Do something cool!
}
}
And I modified the default JSON with:
{
"name": "glfw3Test",
"dependencies":
{
"derelict-glfw3": "~master"
},
"configurations": [
{
"name": "glfw3Test",
"targetType": "executable"
}
]
}
I built with dub build, everything went fine, but when I tred to launch the executable I got the following errors:
derelict.util.exception.SharedLibLoadException#../../../.dub/packages/derelict-util-1.0.2/source/derelict/util/exception.d(35): Failed to load one or more shared libraries:
libglfw.3.dylib - dlopen(libglfw.3.dylib, 2): image not found
libglfw3.dylib - dlopen(libglfw3.dylib, 2): image not found
I have also tried to compile my application manually without using DUB, but I got always the same problem.
It seems to look for the GLFW3 shared library, but I was thinking that the lib is statically linked by the built process.
I am on OS X 10.10 with Xcode 6 installed (DMD compiler 2.065)
I've noticed that the default make process of GLFW3 (using cmake) does not create the dylib files. So I rebuilt GLFW with the following option:
cmake -D BUILD_SHARED_LIBS=ON
And then I made a make install, so now the file libglfw.dylib is correctly installed in /usr/local/lib
Thank to #duselbaer for make me noticed this problem.

node c++ addon / v8 / custom dependency

I am trying to build a node c++ addon on ubuntu using code::blocks. I have build a addon.node shared library that depends on another shared library dep.so . When creating my basid js file with
var addon = require(./addon.node);
it gives
Error: dep.so: cannot open shared object file: No such file or directory
at Error (native)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:367:17)
at require (module.js:386:17)
at repl:1:13
at REPLServer.defaultEval (repl.js:130:27)
at bound (domain.js:254:14)
at REPLServer.runBound [as eval] (domain.js:267:12)
at REPLServer.<anonymous> (repl.js:277:12)
My dep.so file is included while building addon.node and exists in the same build directory as addon.node
running ld addon.node it gives (among other things)
ld: warning: dep.so, needed by addon.node, not found (try using -rpath or -rpath-link)
ld: warning: cannot find entry symbol _start; not setting start address
addon.node: undefined reference to `v8::ObjectTemplate::SetInternalFieldCount(int)'
so, it seems I have two problems:
1) it can't find my own created dep.so library
2) it can't find v8 library (I guess this needs to be build somehow)
Any suggestions how to get this to work?
Cheers, Mike
nbind makes it easy in general to write Node.js bindings for libraries and libui-node is a practical example of using it, to create a cross-platform native UI. Its binding.gyp file shows how to successfully link with a library called libui placed in the root directory of the module (not the build directory).
On Windows:
"libraries": [
"<(module_root_dir)/libui.lib"
]
Linux:
'ldflags': [
'-Wl,-rpath,<(module_root_dir)',
],
"libraries": [
"<(module_root_dir)/libui.so"
]
OS X:
"xcode_settings": {
"OTHER_LDFLAGS": [
"-L<(module_root_dir)",
"-lui",
"-rpath",
"<(module_root_dir)"
]
}