LoginSignup
22
22

More than 5 years have passed since last update.

RustでNode.jsのネイティブモジュールが作れるやつを試した

Last updated at Posted at 2015-12-26

背景


なんて、ツイートをたまたま見かけ、

なぜ原理的に無理そうなのか

やってみた

Rustがある時から、「attribute((constructor))」をサポートしたのかもと思い、調べるも見当たらず。

wc-demoのコードをたどり、依存モジュールのリポジトリのpackage.jsonをたどるも
node-ffiすら見当たらず、これは俺が知らない未知のテクノロジーを使って解決したのか!

と、期待を膨らませて実際に動かしてみた。

rustのアップデート

1.5以上とwc-demoに書いてあるので、

curl -sSf https://static.rust-lang.org/rustup.sh | sh

OSXではPkgも用意されているので、そこらへんはお好みで。

wc-demoをクローンして試す

$ nodebrew ls
v0.10.35
v0.12.0
v4.2.1
v5.1.1
v5.2.0
v5.3.0

current: v5.3.0

$ npm install
npm WARN prefer global node-gyp@3.0.3 should be installed with -g

> wc-demo@0.0.0 postinstall /Users/kjw_junichi/work/rust/neon/wc-demo
> neon build

  ACTION binding_gyp_wc_demo_target_generate Release/obj.target/wc_demo/geni/binding.cc
  ACTION binding_gyp_wc_demo_target_cargo ../target/release/libwc_demo.a
Unable to update file:///Users/kjw_junichi/work/rust/neon/wc-demo

Caused by:
  Could not find `Cargo.toml` in `/Users/kjunichi/work/rust/neon/neon`
make: *** [../target/release/libwc_demo.a] Error 101
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/Users/kjunichi/work/rust/neon/wc-demo/node_modules/node-gyp/lib/build.js:270:23)
gyp ERR! stack     at emitTwo (events.js:87:13)
gyp ERR! stack     at ChildProcess.emit (events.js:172:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Darwin 15.2.0
gyp ERR! command "/Users/kjunichi/.nodebrew/node/v5.3.0/bin/node" "/Users/kjunichi/work/rust/neon/wc-demo/node_modules/.bin/node-gyp" "rebuild"
gyp ERR! cwd /Users/kjunichi/work/rust/neon/wc-demo
gyp ERR! node -v v5.3.0
gyp ERR! node-gyp -v v3.0.3
gyp ERR! not ok 

npm ERR! Darwin 15.2.0
npm ERR! argv "/Users/kjunichi/.nodebrew/node/v5.3.0/bin/node" "/Users/kjunichi/.nodebrew/current/bin/npm" "install"
npm ERR! node v5.3.0
npm ERR! npm  v3.3.12
npm ERR! code ELIFECYCLE
npm ERR! wc-demo@0.0.0 postinstall: `neon build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the wc-demo@0.0.0 postinstall script 'neon build'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the wc-demo package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     neon build
npm ERR! You can get their info via:
npm ERR!     npm owner ls wc-demo
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/kjunichi/work/rust/neon/wc-demo/npm-debug.log

動かすには

cd ..
git clone https://github.com/dherman/neon.git
npm install -g neon-cli
cd wc-demo
cargo update
npm install
$ node -e 'require("./")'
node -e 'require("./")'
3092 [280ms, 914μs, 751ns]
3092 [40ms, 930μs, 825ns]

動きました!

$ cat binding.gyp
# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.

{
    "target_defaults": {
        "default_configuration": "Release"
    },

    "targets": [{
        "target_name": "wc_demo",

        "variables": {
            "rust_inputs": ["src/lib.rs"],
            "static_lib": "target/release/<(STATIC_LIB_PREFIX)wc_demo<(STATIC_LIB_SUFFIX)",
            "shared_lib": "target/release/<(SHARED_LIB_PREFIX)wc_demo<(SHARED_LIB_SUFFIX)"
        },

        "sources": ["<(INTERMEDIATE_DIR)/binding.cc"],

        "include_dirs": ["<!(neon include-path)"],

        "libraries": ["../<(shared_lib)"],

        "actions": [{
            "action_name": "cargo",
            "inputs": ["<@(rust_inputs)"],
            "outputs": ["../<(static_lib)"],
            "action": ["cargo", "rustc", "--release", "--", "--crate-type", "staticlib"]
        }, {
            "action_name": "shared_lib",
            "inputs": ["<(static_lib)"],
            "outputs": ["../<(shared_lib)"],
            # FIXME: OSX-specific
            "action": ["gcc", "-dynamiclib", "-Wl,-undefined,dynamic_lookup", "-Wl,-force_load,<(static_lib)", "-o", "<(shared_lib)"]
        }, {
            "action_name": "generate",
            "inputs": [],
            "outputs": ["<(INTERMEDIATE_DIR)/binding.cc"],
            "action": ["neon", "generate", "<(INTERMEDIATE_DIR)/binding.cc"]
        }]
    }]

}

ということで、biding.ccをエントリポイントにして、その先がRustで記述されたモジュールとなっているようです。

関連

22
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
22