【问题标题】:is it possible to make cargo install installing dependent cdylib dlls是否可以让 cargo install 安装依赖的 cdylib dll
【发布时间】:2022-01-15 03:57:11
【问题描述】:

我在窗户上并且有

一个 Rust cdylib

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

以及依赖于该 dll 的 Rust 二进制文件

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

正在寻找制作方法

cargo install

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

库需要是一个 dll,所以我可以LoadLibrary 它。静态库不起作用。

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

从 dll 项目本身运行 cargo install 会给出一个

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

documentation匹配

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

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

我认为this 可能会接近但运行时被明确排除:

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

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

【问题讨论】:

    标签: windows installation rust rust-cargo rust-crates


    【解决方案1】:

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

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

    【讨论】:

    • 我不想支持或反对 Rust,但我需要一个 dll 才能将 inject 它放入进程中。
    【解决方案2】:

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

    1. cargo 卸载不会卸载 dll
    2. 构建时使用子包创建dll时,包无法发布because

    无论是否指定了排除或包含,以下 文件总是被排除在外:任何子包都将被跳过(任何 包含 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 2013-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多