Я бы создал сценарий сборки , который выполняет итерацию по каталогу, создавая массив кортежей, содержащих имя и еще один вызов макроса для включения необработанных данных:
use std::{
env, error::Error, fs::{self, File}, io::Write, path::Path,
};
const SOURCE_DIR: &str = "some/path/to/include";
fn main() -> Result<(), Box<Error>> {
let out_dir = env::var("OUT_DIR")?;
let dest_path = Path::new(&out_dir).join("all_the_files.rs");
let mut all_the_files = File::create(&dest_path)?;
writeln!(&mut all_the_files, r#"["#,)?;
for f in fs::read_dir(SOURCE_DIR)? {
let f = f?;
if !f.file_type()?.is_file() {
continue;
}
writeln!(
&mut all_the_files,
r#"("{name}", include_bytes!("{name}")),"#,
name = f.path().display(),
)?;
}
writeln!(&mut all_the_files, r#"];"#,)?;
Ok(())
}
У этого есть некоторые недостатки, а именно, что он требует, чтобы путь был выражен как &str
.Поскольку вы уже использовали include_string!
, я не думаю, что это требование extra .
Поскольку мы включаем файлы, я использовал include_bytes!
вместо include_str!
, но если вам это действительно нужно, вы можете переключиться обратно.Необработанные байты пропускают выполнение проверки UTF-8 во время компиляции, поэтому это небольшой выигрыш.
Использование его включает импорт сгенерированного значения:
const ALL_THE_FILES: &[(&str, &[u8])] = &include!(concat!(env!("OUT_DIR"), "/all_the_files.rs"));
fn main() {
for (name, data) in ALL_THE_FILES {
println!("File {} is {} bytes", name, data.len());
}
}