代码之家  ›  专栏  ›  技术社区  ›  Jeremy Meo

如果包含字节,则返回到可选值!(缺少目标)

  •  0
  • Jeremy Meo  · 技术社区  · 7 年前

    我的包有一个二进制目标,它使用 include_bytes!(…) 将一些预计算值的副本绑定到编译的二进制文件中。这是一个优化,但并非绝对必要:如果捆绑的数据片 .is_empty()

    程序需要能够在没有这些数据的情况下构建。然而, include_bytes!("data/computed.bin") 如果目标文件不存在,则导致生成错误。

    error: couldn't read src/data/computed.bin: No such file or directory (os error 2)
    

    目前,我有一个Bash构建脚本,它使用 touch data/computed.bin 以确保文件在生成之前存在。但是,我不希望依赖于特定于平台的解决方案,比如Bash;我希望能够使用 cargo build .

    我的生锈程序 包括字节!() include_str!(…) 从一个文件中退出,但如果该文件不存在,则优雅地返回到另一个值或行为,而只使用标准的Cargo构建工具?

    0 回复  |  直到 7 年前
        1
  •  3
  •   Jeremy Meo    7 年前

    我们可以用 build script 以确保包含的文件在out包尝试包含它之前存在。但是,生成脚本只能写入当前生成的唯一输出目录,因此我们不能直接在源目录中创建缺少的输入文件。

    错误:无法验证包tarball

    原因:
    源目录修改者 build.rs 在期间 cargo publish . 生成脚本不应修改 OUT_DIR .

    相反,我们的生成脚本可以创建要包含在生成目录中的文件,复制源数据(如果存在),并且我们可以更新包代码,以便从生成目录而不是源目录中包含此数据。生成路径将在 输出目录 在生成过程中使用环境变量,因此我们可以从 std::env::var("OUT_DIR") 在我们的构建脚本中 env!("OUT_DIR")

    //! build.rs
    
    use std::{fs, io};
    
    fn main() {
        let out_dir = std::env::var("OUT_DIR").unwrap();
    
        fs::create_dir_all(&format!("{}/src/data", out_dir))
            .expect("unable to create data directory");
    
        let path = format!("src/data/computed.bin", name);
        let out_path = format!("{}/{}", out_dir, path);
    
        let mut out_file = fs::OpenOptions::new()
            .append(true)
            .create(true)
            .open(&out_path)
            .expect("unable to open/create data file");
    
        if let Ok(mut source_file) = fs::File::open(&path) {
            io::copy(&mut source_file, &mut out_file).expect("failed to copy data after opening");
        }
    }
    
    //! src/foo.rs
    
    fn precomputed_data() -> Option<&'static [u8]> {
        let data = include_bytes!(concat!(env!("OUT_DIR"), "/src/data/computed.bin")).as_ref();
        if !data.is_empty() {
            Some(data)
        } else {
            None
        }
    }
    
    推荐文章