是否可以通过安装依赖的cdylib dll来安装货物



我在windows上,有

a Rust cdylib

[package]
name = "test1dll"
[lib]
crate-type = ["cdylib"]

和依赖于dll 的Rust二进制文件

[package]
name = "test1"
[dependencies]
test1dll = { path = "..." }

我正在寻找一种制造的方法

cargo install

同时安装test1.exetest1dll.dll,或者,如果货物无法安装,则安装一个不太复杂的替代方案。

这个库需要是一个dll,这样我才能LoadLibrary它。静态库不起作用

我可以在目标/*/deps目录中看到二进制文件和dll,但cargo install只安装可执行文件。

从dll项目本身运行cargo install会产生

错误:未找到包含二进制文件或示例的包。

与文档匹配

此命令管理Cargo本地安装的二进制板条箱集。只有具有可执行[[bin]]或[[example]]目标的包才能安装

但由于在windows上部署二进制文件和dll是一种有用的场景,Rust甚至提供了将cdylib目标编译到dll中的可能性,我想知道是否有一种方法可以用cargo实现这一点。不幸的是,我是Rust的新手,可能使用了错误的关键字进行搜索。

我认为这可能很接近,但运行时被明确排除在外:

请注意,在构建大木箱如果您的程序或库在运行时需要工件仍然需要通过其他方式自己处理。

要么我用错了,要么cdylib插件也无助于安装dll。

Rust旨在编译成一个程序,这是C++用户针对Rust使用的参数之一。Rust二进制文件要大得多,因为所有库都是静态链接的,而不是动态链接的。是否有特定的原因需要动态链接而不是静态链接?

target/*/deps文件夹包含静态链接到二进制文件的已编译库。

将dll与带有货物的exe一起安装确实是不可能的。但也可以将dll二进制流作为blob添加到exe中,并在第一次运行时重新创建dll。有两个缺点:

  1. 货物卸载不会卸载dll
  2. 在生成期间使用子包创建dll时,无法发布该包,因为

无论指定了exclude还是include文件总是被排除在外:任何子包都将被跳过(任何包含Cargo.toml文件的子目录(。

这可以通过在主包的build.rs期间创建子包的Cargo.toml来解决。货物将向投诉

错误:无法验证包tarball原因:源目录在货物发布期间被build.rs修改。生成脚本应该不修改OUT_DIR之外的任何内容。

但也暗示

要继续,请传递--no-verify标志。

所以这很好。

基本流程如下:

  1. 创建一个子包,定义cdylib
  2. 在主包中创建一个build.rs
  • 调用子包的货物构建

:

std::process::Command::new("cargo")
.stdout(std::process::Stdio::inherit())
.current_dir(sub_package_dir)
.arg("build")
.arg("--release")
.arg("-vv")
.status()
.unwrap();
  • ,然后动态创建一个包含dll字节流和访问它的函数的rust源

:

let dll_src_str = format!(
"const DLL_BIN: &[u8] = include_bytes!(r"{}");
pub fn dll_bin() -> &'static [u8] {{ DLL_BIN }}",
dll_path);
let mut dll_src_file =
std::fs::File::create(dll_src_path).unwrap();
use std::io::prelude::*;
let write_ok = dll_src_file.write_all(dll_src_str.as_bytes());

在build.rs完成执行后,构建过程将找到并编译创建的附加源。

  1. 在程序执行期间创建dll文件

:

pub fn create_dll() -> std::io::Result<()> {
let dll_bytes = dll_contents::dll_bytes();
let mut dll_file = std::fs::File::create(dll_path).unwrap();
use std::io::prelude::*;
return dll_file.write_all(dll_bytes);
}

最新更新