cargo_concat/
lib.rs

1pub mod extract;
2pub mod metadata;
3pub mod module;
4pub mod target;
5
6use anyhow::Result;
7use cargo_metadata::{CargoOpt, MetadataCommand};
8use std::fs::read_to_string;
9
10pub fn concat_source(cargo_toml: &str, target: Option<&String>) -> Result<String> {
11    let metadata = MetadataCommand::new()
12        .manifest_path(cargo_toml)
13        .features(CargoOpt::AllFeatures)
14        .exec()?;
15    let source_path = target::get_target_source_path(&metadata, target)?;
16    log::info!("Target found: {:?}", source_path);
17
18    let source_code = read_to_string(&source_path)?;
19    let source_file = syn::parse_file(&source_code)?;
20
21    let libs = extract::extract_modules(&source_file)
22        .into_iter()
23        .map(|ident| ident.to_string())
24        .collect::<Vec<_>>();
25    log::info!("Extracted modules: {:?}", libs);
26    let mut paths = vec![];
27    for lib_name in libs {
28        if lib_name.as_str() == "std" || lib_name.as_str() == "crate" {
29            continue;
30        }
31
32        match metadata::get_module_lib_file(&metadata, &lib_name) {
33            Ok(lib_path) => paths.push((lib_name, lib_path)),
34            Err(e) => log::warn!("{:?}", e),
35        }
36    }
37
38    let mut file_content = quote::quote!(#source_file).to_string();
39
40    for (lib_name, lib_path) in paths {
41        let ident = quote::format_ident!("{}", lib_name);
42        let file = module::concat_module(lib_path, true)?;
43        file_content.push_str(quote::quote! {mod #ident {#file}}.to_string().as_str());
44    }
45    Ok(file_content)
46}