我如何使用 Cargo 将库构建为 rlib 和 dylib 但内容不同?
How can I use Cargo to build a library as both an rlib and a dylib but with different contents?
我想制作一个包含以下内容的项目:
- 图书馆
- C 的绑定
- 使用库的可执行文件
目录结构,不包括临时文件和其他垃圾:
.
├── Cargo.toml
├── src
│ ├── c_bindings.rs // contains C bindings for library
│ ├── compression.rs
│ ├── const_data.rs
│ ├── hash.rs
│ ├── lib.rs // library
│ └── main.rs // simple executable that uses library
└── target
└── debug
├── gost_stribog
├── libgost_stribog.rlib
我想要cargo build
这样做:
- 构建将忽略
c_bindings.rs
的 Rust 库 (rlib)
- 将使用
c_bindings.rs
的 C 库 (dylib)
- 可执行
调试目录应该是:
└── target
└── debug
├── gost_stribog
├── libgost_stribog.rlib
├── libgost_stribog.so
我的 Cargo.toml
应该是什么样子?
自以为是的答案:不要。
相反,将您的代码分成两个或三个单独的箱子:
- 核心库。
- 库的 C 绑定。
- (可选)可执行文件。
然后,将您的 c_bindings.rs
移动到绑定箱,就像 lib.rs
一样。它可以依赖于核心库。您还可以将 main.rs
移动到另一个也依赖于核心库的板条箱中。
这三个 crate 可以在同一个源代码存储库中,但将通过单独的调用构建。
A Cargo workspace 可能有用;事实上,它被列为一个明确的原因 ("An FFI crate with a sub-crate for FFI bindings")。
事实上,你可以。这是如何做的。
$PROJECT_ROOT/.cargo/config.rs
[build]
rustflags = ["-C", "prefer-dynamic"]
请记住,您还需要使用 Rust 标准库来分发您的应用程序。
$ ls $(rustc --print=sysroot)/lib
libLLVM-13-rust-1.57.0-beta.so librustc_driver-3aebdc12af579500.so libstd-c8bc39dac3997df6.so libtest-4d997b51b1a49b1f.so rustlib
在我的例子中它被命名为 libstd-c8bc39dac3997df6.so,因为我在 linux,如果你在 windows,它应该在 bin 文件夹而不是 lib文件夹。
此外,您还需要一个脚本来 运行 linux 和 MacOS 上的程序。在 linux 和 macOS 上,您不只是将库放在与您的应用程序相同的目录中并期望它能够工作,而是您有 2 个选项。
- 将库放入
/usr/lib
文件夹,然后 运行 它。
- 制作一个脚本:
exec LD_LIBRARY_PATH=$PWD ./YOU_APPLICATION $@ # this last commands tells sh to get the command line arguments.
仅此而已。 :)
我想制作一个包含以下内容的项目:
- 图书馆
- C 的绑定
- 使用库的可执行文件
目录结构,不包括临时文件和其他垃圾:
.
├── Cargo.toml
├── src
│ ├── c_bindings.rs // contains C bindings for library
│ ├── compression.rs
│ ├── const_data.rs
│ ├── hash.rs
│ ├── lib.rs // library
│ └── main.rs // simple executable that uses library
└── target
└── debug
├── gost_stribog
├── libgost_stribog.rlib
我想要cargo build
这样做:
- 构建将忽略
c_bindings.rs
的 Rust 库 (rlib)
- 将使用
c_bindings.rs
的 C 库 (dylib)
- 可执行
调试目录应该是:
└── target
└── debug
├── gost_stribog
├── libgost_stribog.rlib
├── libgost_stribog.so
我的 Cargo.toml
应该是什么样子?
自以为是的答案:不要。
相反,将您的代码分成两个或三个单独的箱子:
- 核心库。
- 库的 C 绑定。
- (可选)可执行文件。
然后,将您的 c_bindings.rs
移动到绑定箱,就像 lib.rs
一样。它可以依赖于核心库。您还可以将 main.rs
移动到另一个也依赖于核心库的板条箱中。
这三个 crate 可以在同一个源代码存储库中,但将通过单独的调用构建。
A Cargo workspace 可能有用;事实上,它被列为一个明确的原因 ("An FFI crate with a sub-crate for FFI bindings")。
事实上,你可以。这是如何做的。
$PROJECT_ROOT/.cargo/config.rs
[build]
rustflags = ["-C", "prefer-dynamic"]
请记住,您还需要使用 Rust 标准库来分发您的应用程序。
$ ls $(rustc --print=sysroot)/lib
libLLVM-13-rust-1.57.0-beta.so librustc_driver-3aebdc12af579500.so libstd-c8bc39dac3997df6.so libtest-4d997b51b1a49b1f.so rustlib
在我的例子中它被命名为 libstd-c8bc39dac3997df6.so,因为我在 linux,如果你在 windows,它应该在 bin 文件夹而不是 lib文件夹。
此外,您还需要一个脚本来 运行 linux 和 MacOS 上的程序。在 linux 和 macOS 上,您不只是将库放在与您的应用程序相同的目录中并期望它能够工作,而是您有 2 个选项。
- 将库放入
/usr/lib
文件夹,然后 运行 它。 - 制作一个脚本:
exec LD_LIBRARY_PATH=$PWD ./YOU_APPLICATION $@ # this last commands tells sh to get the command line arguments.
仅此而已。 :)