我想在Rust中嵌入node.js。我不有兴趣使用NAPI编写node.js插件或从rust内部广泛控制node.js。我所需要的仅仅是node.js的
为什么?我正在构建一个自包含的单文件二进制桌面应用程序,希望在其中运行具有嵌入式node.js运行时的node.js脚本。不能保证终端用户计算机上安装了Node.js,并且启动时间很敏感,因此从二进制文件中提取一个自包含的node.js zip文件到文件系统是不可取的。
我认为我在我的Rust(二进制)项目中静态链接node.js时遇到了问题。
我下载了nodejs源代码。
并将
然后我将 Node.js 构建为静态库。
我有一个c++封装文件
此时,我已经能够成功构建 C++ 封装作为二进制文件,并在静态链接 node.js 库并成功从 C++ 运行 node.js。然而,从 Rust 中...
main.rs:
请注意,
当我运行
我不确定连接顺序是否重要,但我尝试了一些不同的排序组合,并没有成功。我还尝试从node/out/Release链接所有的.lib文件,但没有任何区别。我还尝试将node/out/Release中的所有.lib文件合并成一个.lib文件,但出现了重复符号错误。我尝试了不同版本的node.js(如v11.15.0),但没有任何区别。 我在MacOS 10.14.5上进行此操作。
如果有好的想法,我愿意尝试更好的将node.js嵌入到Rust中。
main()
启动方法 - 相当于执行node myscript.js
。为什么?我正在构建一个自包含的单文件二进制桌面应用程序,希望在其中运行具有嵌入式node.js运行时的node.js脚本。不能保证终端用户计算机上安装了Node.js,并且启动时间很敏感,因此从二进制文件中提取一个自包含的node.js zip文件到文件系统是不可取的。
我认为我在我的Rust(二进制)项目中静态链接node.js时遇到了问题。
我下载了nodejs源代码。
git clone https://github.com/nodejs/node
并将
node_main.cc
中的主方法重命名。sed -i .bak "s/int main(/int node_main(/g" ./src/node_main.cc
然后我将 Node.js 构建为静态库。
./configure --enable-static
make -j4
我有一个c++封装文件
wrapper.cpp
,通过extern c
暴露node_main()
方法。
:#include <string>
#include <iostream>
using namespace std;
int node_main(int argc, char **argv);
extern "C" {
void run_node() {
cout << "hello there! general kenobi..." << endl;
char *args[] = { (char*)"tester.js", NULL };
node_main(1, args);
}
}
此时,我已经能够成功构建 C++ 封装作为二进制文件,并在静态链接 node.js 库并成功从 C++ 运行 node.js。然而,从 Rust 中...
main.rs:
extern {
fn run_node();
}
fn main() {
println!("hey there this is RUST");
unsafe { run_node(); }
}
build.rs:
extern crate cc;
fn main() {
println!("cargo:rustc-link-search=native=../node/out/Release");
println!("cargo:rustc-link-lib=static=node");
println!("cargo:rustc-link-lib=static=uv");
println!("cargo:rustc-link-lib=static=v8_base");
println!("cargo:rustc-link-lib=static=v8_libbase");
println!("cargo:rustc-link-lib=static=v8_snapshot");
println!("cargo:rustc-link-lib=static=v8_libplatform");
println!("cargo:rustc-link-lib=static=icuucx");
println!("cargo:rustc-link-lib=static=icui18n");
println!("cargo:rustc-link-lib=static=icudata");
println!("cargo:rustc-link-lib=static=icustubdata");
println!("cargo:rustc-link-lib=static=brotli");
println!("cargo:rustc-link-lib=static=nghttp2");
cc::Build::new()
.cpp(true)
.file("wrapper.cpp")
.compile("libwrapper.a");
}
请注意,
rustc-link-search
路径是相对于上级目录的。当我运行
cargo build
时,会出现以下错误:= note: Undefined symbols for architecture x86_64:
"node_main(int, char**)", referenced from:
_run_node in libwrapper.a(wrapper.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我不确定连接顺序是否重要,但我尝试了一些不同的排序组合,并没有成功。我还尝试从node/out/Release链接所有的.lib文件,但没有任何区别。我还尝试将node/out/Release中的所有.lib文件合并成一个.lib文件,但出现了重复符号错误。我尝试了不同版本的node.js(如v11.15.0),但没有任何区别。 我在MacOS 10.14.5上进行此操作。
$ rustc --version
rustc 1.36.0 (a53f9df32 2019-07-03)
$ cargo --version
cargo 1.36.0 (c4fcfb725 2019-05-15)
$ g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Devel
oper/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Cargo.toml:
[build-dependencies]
cc = "1.0"
如果有好的想法,我愿意尝试更好的将node.js嵌入到Rust中。