pub fn generate_build_ninja(
    build_dir: PathBuf,
    ditto_bin: PathBuf,
    ditto_version: &semver::Version,
    compile_subcommand: &'static str,
    sources: Sources,
    package_sources: PackageSources,
) -> Result<(BuildNinja, GetWarnings)> {
    // TODO make this more concurrent!
    let config = read_config(&sources.config)?;

    // Initial build.ninja file, extended later
    let mut build_ninja = BuildNinja::new(&build_dir, &ditto_bin, compile_subcommand, &config);

    let js_dirs = if config.targets_js() {
        let dist_dir = config.codegen_js_config.dist_dir;
        let packages_dir = config.codegen_js_config.packages_dir;
        build_ninja
            .builds
            .extend(package_sources.iter().map(|(package_name, sources)| {
                let mut package_json_path = packages_dir.clone();
                package_json_path.push(package_name.as_str());
                package_json_path.push("package.json");
                Build::new_package_json(package_name, package_json_path, sources.config.clone())
            }));
        Some((dist_dir, packages_dir))
    } else {
        None
    };

    let (graph, graph_nodes) = prepare_build_graph(sources, package_sources, ditto_version)?;

    // Paths to serialized warnings, so the caller can replay them
    let mut checker_warnings_paths: Vec<PathBuf> = Vec::new();

    for (node_index, node) in graph_nodes.clone() {
        let node_string = node.to_string();
        let ast_path = mk_ast_path(
            build_dir.clone(),
            &node.package_name,
            &node.module_name,
            common::EXTENSION_AST,
        );

        let ast_exports_path = mk_ast_path(
            build_dir.clone(),
            &node.package_name,
            &node.module_name,
            common::EXTENSION_AST_EXPORTS,
        );

        let checker_warnings_path = if node.package_name.is_none() {
            let checker_warnings_path = mk_ast_path(
                build_dir.clone(),
                &node.package_name,
                &node.module_name,
                common::EXTENSION_CHECKER_WARNINGS,
            );
            checker_warnings_paths.push(checker_warnings_path.clone());
            Some(checker_warnings_path)
        } else {
            None
        };

        let dependency_ast_export_paths = graph
            .neighbors(node_index)
            .map(|idx| {
                let dep_node = graph_nodes.get(&idx).unwrap();
                mk_ast_path(
                    build_dir.clone(),
                    &dep_node.package_name,
                    &dep_node.module_name,
                    common::EXTENSION_AST_EXPORTS,
                )
            })
            .collect::<Vec<_>>();

        if let Some((ref dist_dir, ref packages_dir)) = js_dirs {
            let js_path = if let Some(package_name) = node.package_name {
                let mut js_path = packages_dir.clone();
                js_path.push(package_name.as_str());
                js_path.push(common::module_name_to_file_stem(node.module_name));
                js_path.set_extension(common::EXTENSION_JS);
                js_path
            } else {
                let mut js_path = dist_dir.clone();
                js_path.push(common::module_name_to_file_stem(node.module_name));
                js_path.set_extension(common::EXTENSION_JS);
                js_path
            };
            build_ninja.builds.push(Build::new_js(
                node_string.clone(),
                js_path,
                ast_path.clone(),
            ));
        }

        build_ninja.builds.push(Build::new_ast(
            node_string,
            ast_path,
            ast_exports_path,
            checker_warnings_path,
            node.source_path,
            dependency_ast_export_paths,
        ));
    }

    // Callback to get all warnings for the current package
    let get_warnings = move || {
        let mut warnings = Vec::new();
        for warnings_path in checker_warnings_paths {
            let warnings_bundle =
                common::deserialize::<Option<compile::WarningsBundle>>(&warnings_path)?;

            if let Some(compile::WarningsBundle {
                name,
                source,
                warnings: warning_reports,
            }) = warnings_bundle
            {
                let source = std::sync::Arc::new(source);
                warnings.extend(warning_reports.into_iter().map(|warning_report| {
                    miette::Report::from(warning_report)
                        .with_source_code(miette::NamedSource::new(&name, source.clone()))
                }))
            }
        }
        Ok(warnings)
    };

    Ok((build_ninja, get_warnings))
}
/// Generates a [build.ninja](https://ninja-build.org/manual.html#_writing_your_own_ninja_files)
/// file and also returns a function for retrieving compiler warnings once `ninja` has run.
Generates a [build.ninja]
file and also returns a function for retrieving compiler warnings once `ninja` has run.
Generates a [ build . ninja ] file and also returns a function for retrieving compiler warnings once ` ninja ` has run .
pub fn generate_build_ninja(
    build_dir: PathBuf,
    ditto_bin: PathBuf,
    ditto_version: &semver::Version,
    compile_subcommand: &'static str,
    sources: Sources,
    package_sources: PackageSources,
) -> Result<(BuildNinja, GetWarnings)> {
    // TODO make this more concurrent!
    let config = read_config(&sources.config)?;
    // Initial build.ninja file, extended later
    let mut build_ninja = BuildNinja::new(&build_dir, &ditto_bin, compile_subcommand, &config);
    let js_dirs = if config.targets_js() {
        let dist_dir = config.codegen_js_config.dist_dir;
        let packages_dir = config.codegen_js_config.packages_dir;
        build_ninja
            .builds
            .extend(package_sources.iter().map(|(package_name, sources)| {
                let mut package_json_path = packages_dir.clone();
                package_json_path.push(package_name.as_str());
                package_json_path.push("package.json");
                Build::new_package_json(package_name, package_json_path, sources.config.clone())
            }));
        Some((dist_dir, packages_dir))
    } else {
        None
    };
    let (graph, graph_nodes) = prepare_build_graph(sources, package_sources, ditto_version)?;
    // Paths to serialized warnings, so the caller can replay them
    let mut checker_warnings_paths: Vec<PathBuf> = Vec::new();
    for (node_index, node) in graph_nodes.clone() {
        let node_string = node.to_string();
        let ast_path = mk_ast_path(
            build_dir.clone(),
            &node.package_name,
            &node.module_name,
            common::EXTENSION_AST,
        );
        let ast_exports_path = mk_ast_path(
            build_dir.clone(),
            &node.package_name,
            &node.module_name,
            common::EXTENSION_AST_EXPORTS,
        );
        let checker_warnings_path = if node.package_name.is_none() {
            let checker_warnings_path = mk_ast_path(
                build_dir.clone(),
                &node.package_name,
                &node.module_name,
                common::EXTENSION_CHECKER_WARNINGS,
            );
            checker_warnings_paths.push(checker_warnings_path.clone());
            Some(checker_warnings_path)
        } else {
            None
        };
        let dependency_ast_export_paths = graph
            .neighbors(node_index)
            .map(|idx| {
                let dep_node = graph_nodes.get(&idx).unwrap();
                mk_ast_path(
                    build_dir.clone(),
                    &dep_node.package_name,
                    &dep_node.module_name,
                    common::EXTENSION_AST_EXPORTS,
                )
            })
            .collect::<Vec<_>>();
        if let Some((ref dist_dir, ref packages_dir)) = js_dirs {
            let js_path = if let Some(package_name) = node.package_name {
                let mut js_path = packages_dir.clone();
                js_path.push(package_name.as_str());
                js_path.push(common::module_name_to_file_stem(node.module_name));
                js_path.set_extension(common::EXTENSION_JS);
                js_path
            } else {
                let mut js_path = dist_dir.clone();
                js_path.push(common::module_name_to_file_stem(node.module_name));
                js_path.set_extension(common::EXTENSION_JS);
                js_path
            };
            build_ninja.builds.push(Build::new_js(
                node_string.clone(),
                js_path,
                ast_path.clone(),
            ));
        }
        build_ninja.builds.push(Build::new_ast(
            node_string,
            ast_path,
            ast_exports_path,
            checker_warnings_path,
            node.source_path,
            dependency_ast_export_paths,
        ));
    }
    // Callback to get all warnings for the current package
    let get_warnings = move || {
        let mut warnings = Vec::new();
        for warnings_path in checker_warnings_paths {
            let warnings_bundle =
                common::deserialize::<Option<compile::WarningsBundle>>(&warnings_path)?;
            if let Some(compile::WarningsBundle {
                name,
                source,
                warnings: warning_reports,
            }) = warnings_bundle
            {
                let source = std::sync::Arc::new(source);
                warnings.extend(warning_reports.into_iter().map(|warning_report| {
                    miette::Report::from(warning_report)
                        .with_source_code(miette::NamedSource::new(&name, source.clone()))
                }))
            }
        }
        Ok(warnings)
    };
    Ok((build_ninja, get_warnings))
}
pub fn generate_build_ninja ( build_dir : PathBuf , ditto_bin : PathBuf , ditto_version : & semver :: Version , compile_subcommand : & ' static str , sources : Sources , package_sources : PackageSources , ) -> Result < ( BuildNinja , GetWarnings ) > { // TODO make this more concurrent! let config = read_config ( & sources . config ) ? ; // Initial build.ninja file, extended later let mut build_ninja = BuildNinja :: new ( & build_dir , & ditto_bin , compile_subcommand , & config ) ; let js_dirs = if config . targets_js ( ) { let dist_dir = config . codegen_js_config . dist_dir ; let packages_dir = config . codegen_js_config . packages_dir ; build_ninja . builds . extend ( package_sources . iter ( ) . map ( | ( package_name , sources ) | { let mut package_json_path = packages_dir . clone ( ) ; package_json_path . push ( package_name . as_str ( ) ) ; package_json_path . push ( " " ) ; Build :: new_package_json ( package_name , package_json_path , sources . config . clone ( ) ) } ) ) ; Some ( ( dist_dir , packages_dir ) ) } else { None } ; let ( graph , graph_nodes ) = prepare_build_graph ( sources , package_sources , ditto_version ) ? ; // Paths to serialized warnings, so the caller can replay them let mut checker_warnings_paths : Vec < PathBuf > = Vec :: new ( ) ; for ( node_index , node ) in graph_nodes . clone ( ) { let node_string = node . to_string ( ) ; let ast_path = mk_ast_path ( build_dir . clone ( ) , & node . package_name , & node . module_name , common :: EXTENSION_AST , ) ; let ast_exports_path = mk_ast_path ( build_dir . clone ( ) , & node . package_name , & node . module_name , common :: EXTENSION_AST_EXPORTS , ) ; let checker_warnings_path = if node . package_name . is_none ( ) { let checker_warnings_path = mk_ast_path ( build_dir . clone ( ) , & node . package_name , & node . module_name , common :: EXTENSION_CHECKER_WARNINGS , ) ; checker_warnings_paths . push ( checker_warnings_path . clone ( ) ) ; Some ( checker_warnings_path ) } else { None } ; let dependency_ast_export_paths = graph . neighbors ( node_index ) . map ( | idx | { let dep_node = graph_nodes . get ( & idx ) . unwrap ( ) ; mk_ast_path ( build_dir . clone ( ) , & dep_node . package_name , & dep_node . module_name , common :: EXTENSION_AST_EXPORTS , ) } ) . collect :: < Vec < _ > > ( ) ; if let Some ( ( ref dist_dir , ref packages_dir ) ) = js_dirs { let js_path = if let Some ( package_name ) = node . package_name { let mut js_path = packages_dir . clone ( ) ; js_path . push ( package_name . as_str ( ) ) ; js_path . push ( common :: module_name_to_file_stem ( node . module_name ) ) ; js_path . set_extension ( common :: EXTENSION_JS ) ; js_path } else { let mut js_path = dist_dir . clone ( ) ; js_path . push ( common :: module_name_to_file_stem ( node . module_name ) ) ; js_path . set_extension ( common :: EXTENSION_JS ) ; js_path } ; build_ninja . builds . push ( Build :: new_js ( node_string . clone ( ) , js_path , ast_path . clone ( ) , ) ) ; } build_ninja . builds . push ( Build :: new_ast ( node_string , ast_path , ast_exports_path , checker_warnings_path , node . source_path , dependency_ast_export_paths , ) ) ; } // Callback to get all warnings for the current package let get_warnings = move | | { let mut warnings = Vec :: new ( ) ; for warnings_path in checker_warnings_paths { let warnings_bundle = common :: deserialize :: < Option < compile :: WarningsBundle > > ( & warnings_path ) ? ; if let Some ( compile :: WarningsBundle { name , source , warnings : warning_reports , } ) = warnings_bundle { let source = std :: sync :: Arc :: new ( source ) ; warnings . extend ( warning_reports . into_iter ( ) . map ( | warning_report | { miette :: Report :: from ( warning_report ) . with_source_code ( miette :: NamedSource :: new ( & name , source . clone ( ) ) ) } ) ) } } Ok ( warnings ) } ; Ok ( ( build_ninja , get_warnings ) ) }
Generates a [build.ninja](https://ninja-build.org/manual.html#_writing_your_own_ninja_files)
file and also returns a function for retrieving compiler warnings once `ninja` has run.
Generates a [ build . ninja ] ( https : // ninja - build . org / manual . html#_writing_your_own_ninja_files ) file and also returns a function for retrieving compiler warnings once ` ninja ` has run .
build_dir
PathBuf
ditto_bin
PathBuf
ditto_version
&semver::Version
compile_subcommand
&'static str
sources
Sources
package_sources
PackageSources
build_dir
PathBuf
ditto_bin
PathBuf
ditto_version
&semver::Version
compile_subcommand
&'static str
sources
Sources
package_sources
PackageSources