使用节点启动应用程序有效,但不是yarn或npm

And*_*erg 7 node.js npm node-gyp yarnpkg

对于比我更熟悉NodeJS的人,可能会有一个明显的答案,但:

运行使用node-gyp程序包的应用程序时,使用以下程序可以正常运行 node ./src/index.js

但是,使用非常简单的package.json开始脚本来运行它:

"scripts": {
    "start": "node ./src/index.js"
  }
Run Code Online (Sandbox Code Playgroud)

在npm中:

npm start

npm info it worked if it ends with ok
npm info using npm@6.9.0
npm info using node@v11.10.1
npm info lifecycle rosbag2@0.1.0~prestart: rosbag2@0.1.0
npm info lifecycle rosbag2@0.1.0~start: rosbag2@0.1.0

> rosbag2@0.1.0 start /Users/andreasklintberg/personal/xviz/examples/converters/rosbag2
> node ./src/index.js "./src/index.js"

internal/modules/cjs/loader.js:779
  return process.dlopen(module, path.toNamespacedPath(filename));
                 ^

Error: dlopen(/Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node, 1): Library not loaded: @rpath/librosidl_typesupport_cpp.dylib
  Referenced from: /Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node
  Reason: image not found
Run Code Online (Sandbox Code Playgroud)

同样在纱线中 yarn start

yarn run v1.13.0
warning package.json: No license field
$ node ./src/index.js ./src/index.js -d ../../../data/rosbag2/rosbag2_2019_03_09-21_54_44 -o ../../xviz-data/rosbag2/rosbag2_2019_03_09-21_54_44/
internal/modules/cjs/loader.js:779
  return process.dlopen(module, path.toNamespacedPath(filename));
                 ^

Error: dlopen(/Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node, 1): Library not loaded: @rpath/librosidl_typesupport_cpp.dylib
  Referenced from: /Users/andreasklintberg/personal/xviz/examples/converters/rosbag2/node_modules/rosbags2_nodejs/build/Release/rosbags2_nodejs.node
  Reason: image not found

Run Code Online (Sandbox Code Playgroud)

我知道错误是因为动态链接/ @ rpath被弄乱了,我当时想这是因为npm/yarn弄乱了env变量或其他东西,但是运行yarn env它似乎一切都是正确的。

所以我想我想知道是否有人知道在本机节点中运行它并使用npm/yarn脚本来包装开始有什么区别?为什么这种区别弄乱了@ rpath / dynamic链接?

编辑:

我的index.js文件非常简单,只需导入内置的node-gyp包:

let RosbagDeserializer = require('../build/Release/rosbags2_nodejs.node');


const deserializer = new RosbagDeserializer.Rosbag2Wrapper();
Run Code Online (Sandbox Code Playgroud)

这是有问题的项目,https://github.com/klintan/rosbag2_nodejs

And*_*erg 1

我希望有一个更全面的答案,但至少我在很多精彩评论者的帮助下解决了这个问题:

@rpath 没有在 Mac 上设置,但使用 DYLD_LIBRARY_PATH 它可以工作,因为那是运行时搜索路径之一,看起来(https://superuser.com/questions/282450/where-do-i-set-dyld- mac-os-x-and-is-it-a-good-idea 上的库路径)。然而,由于某种原因,NPM 删除了这个,我猜测它与 Mac 上的 SIP 有关,或者可能是其他一些删除此环境变量的安全措施。

如果您运行,则 DYLD_LIBRARY_PATH 可用node index.js,但如果您使用 npm start (启动脚本)运行它,则不可用node index.js

@Michal Kapracki 和 @Avik 都暗示了这一点(第一次比较时我错过了缺少的环境变量)

我解决这个问题的方法与dyld: Library not returned ... Reason: Image not find question as @Avik linked 类似,我必须添加一堆依赖的库(之前已自动解析)和 post_install .sh 脚本,它使用install_name_tool将 @rpaths 更改为正确的路径。

这是一个非常丑陋的解决方案https://github.com/klintan/rosbag2_nodejs/blob/master/post_install.sh但它有效。但仅适用于 Mac,因此需要概括。

综上所述,我认为问题是:

由于某种原因,NPM 无法使用或删除DYLD_LIBRARY_PATH用于在运行时搜索动态链接库的 env 变量。这使得有必要使用 mac 工具手动链接这些install_name_tool