diff --git a/src/bin/cook.rs b/src/bin/cook.rs index 1f5a4f332..555fd37a0 100644 --- a/src/bin/cook.rs +++ b/src/bin/cook.rs @@ -89,20 +89,21 @@ fn main() { }; } - let recipes = match CookRecipe::get_build_deps_recursive(&recipe_names, !with_package_deps) { - Ok(ok) => ok, - Err(err) => { - eprintln!( - "{}{}cook - error:{}{} {}", - style::Bold, - color::Fg(color::AnsiValue(196)), - color::Fg(color::Reset), - style::Reset, - err, - ); - process::exit(1); - } - }; + let recipes = + match CookRecipe::get_build_deps_recursive(&recipe_names, true, !with_package_deps) { + Ok(ok) => ok, + Err(err) => { + eprintln!( + "{}{}cook - error:{}{} {}", + style::Bold, + color::Fg(color::AnsiValue(196)), + color::Fg(color::Reset), + style::Reset, + err, + ); + process::exit(1); + } + }; for recipe in recipes { if !quiet { diff --git a/src/bin/repo.rs b/src/bin/repo.rs index 2d08507c1..8fe2700e6 100644 --- a/src/bin/repo.rs +++ b/src/bin/repo.rs @@ -9,7 +9,7 @@ use cookbook::cook::pty::{PtyOut, UnixSlavePty, flush_pty, setup_pty}; use cookbook::cook::script::KILL_ALL_PID; use cookbook::cook::tree::{display_tree_entry, format_size}; use cookbook::log_to_pty; -use cookbook::recipe::{BuildKind, CookRecipe}; +use cookbook::recipe::CookRecipe; use pkg::PackageName; use pkg::package::PackageError; use ratatui::Terminal; @@ -418,6 +418,7 @@ fn parse_args(args: Vec) -> anyhow::Result<(CliConfig, CliCommand, Vec) -> anyhow::Result<(CliConfig, CliCommand, Vec { recipe.recipe.source = None; - recipe.recipe.build = cookbook::recipe::BuildRecipe { - kind: BuildKind::Remote, - dependencies: Vec::new(), - }; + recipe.recipe.build.set_as_remote(); } PackageConfig::Build(rule) => { return Err(anyhow!( @@ -458,10 +456,7 @@ fn parse_args(args: Vec) -> anyhow::Result<(CliConfig, CliCommand, Vec, dynamic_dep_pkgars: &BTreeSet, -) -> Result, PackageError> { +) -> Result<(BTreeSet, Vec), PackageError> { let static_dep_pkgars: Vec = build_dep_pkgars .iter() .map(|x| x.0.clone()) @@ -157,7 +156,7 @@ fn auto_deps_from_static_package_deps( .collect(); let pkgs = CookRecipe::get_package_deps_recursive(&static_dep_pkgars, false)?; - Ok(pkgs.into_iter().collect()) + Ok((pkgs.into_iter().collect(), static_dep_pkgars)) } pub fn build( @@ -178,15 +177,13 @@ pub fn build( } let mut dep_pkgars = BTreeSet::new(); - for dependency in recipe.build.dependencies.iter() { - let dependency_dir = recipes::find(dependency.as_str()); - if dependency_dir.is_none() { - return Err(format!("failed to find recipe directory '{}'", dependency)); - } + let build_deps = CookRecipe::get_build_deps_recursive(&recipe.build.dependencies, false, false) + .map_err(|e| format!("{:?}", e))?; + for dependency in build_deps.iter() { dep_pkgars.insert(( - dependency.clone(), - dependency_dir - .unwrap() + dependency.name.clone(), + dependency + .dir .join("target") .join(redoxer::target()) .join("stage.pkgar"), @@ -194,7 +191,7 @@ pub fn build( } if stage_dir.exists() && !check_source { - let auto_deps = build_auto_deps(target_dir, &stage_dir, dep_pkgars, logger)?; + let auto_deps = build_auto_deps(recipe, target_dir, &stage_dir, dep_pkgars, logger)?; return Ok((stage_dir, auto_deps)); } @@ -370,13 +367,14 @@ pub fn build( rename(&stage_dir_tmp, &stage_dir)?; } - let auto_deps = build_auto_deps(target_dir, &stage_dir, dep_pkgars, logger)?; + let auto_deps = build_auto_deps(recipe, target_dir, &stage_dir, dep_pkgars, logger)?; Ok((stage_dir, auto_deps)) } /// Calculate automatic dependencies fn build_auto_deps( + recipe: &Recipe, target_dir: &Path, stage_dir: &PathBuf, dep_pkgars: BTreeSet<(PackageName, PathBuf)>, @@ -394,12 +392,29 @@ fn build_auto_deps( toml::from_str(&toml_content).map_err(|_| "failed to deserialize cached auto_deps")?; wrapper.packages } else { - let mut packages1 = auto_deps_from_dynamic_linking(stage_dir, &dep_pkgars, logger); - let packages2 = - auto_deps_from_static_package_deps(&dep_pkgars, &packages1).unwrap_or_default(); - packages1.extend(packages2); + let mut dynamic_deps = auto_deps_from_dynamic_linking(stage_dir, &dep_pkgars, logger); + let (package_deps, static_deps) = + auto_deps_from_static_package_deps(&dep_pkgars, &dynamic_deps).unwrap_or_default(); + dynamic_deps.extend(package_deps); + + // if auto_deps working, all build deps should be linked as auto_deps, otherwise: + // 1. it's weakly linked, which should be mentioned as package deps + // 2. it's not our direct ELF dependencies, which should be removed from build deps + // 3. only needed for build purpose, which should be moved to dev build deps + if dynamic_deps.len() > 0 && static_deps.len() > 0 { + for dep in &static_deps { + if !recipe.package.dependencies.contains(dep) { + log_to_pty!( + &logger, + "WARNING: build deps {} is not linked in auto_deps", + dep.as_str() + ); + } + } + } + let wrapper = AutoDeps { - packages: packages1, + packages: dynamic_deps, }; serialize_and_write(&auto_deps_path, &wrapper)?; wrapper.packages diff --git a/src/recipe.rs b/src/recipe.rs index 3c9095fd7..153be4076 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -140,6 +140,8 @@ pub struct BuildRecipe { pub kind: BuildKind, #[serde(default)] pub dependencies: Vec, + #[serde(default, rename = "dev-dependencies")] + pub dev_dependencies: Vec, } #[derive(Debug, Clone, Default, Deserialize, PartialEq, Serialize)] @@ -163,6 +165,28 @@ pub struct Recipe { pub package: PackageRecipe, } +impl BuildRecipe { + pub fn new(kind: BuildKind) -> Self { + let mut build = Self::default(); + build.kind = kind; + build + } + + pub fn set_as_remote(&mut self) { + self.kind = BuildKind::Remote; + self.dev_dependencies = Vec::new(); + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct CookRecipe { + pub name: PackageName, + pub dir: PathBuf, + pub recipe: Recipe, + /// If false, it's listed on install config + pub is_deps: bool, +} + impl Recipe { pub fn new(file: &PathBuf) -> Result { if !file.is_file() { @@ -175,14 +199,6 @@ impl Recipe { Ok(recipe) } } -#[derive(Debug, Clone, PartialEq)] -pub struct CookRecipe { - pub name: PackageName, - pub dir: PathBuf, - pub recipe: Recipe, - /// If false, it's listed on install config - pub is_deps: bool, -} impl CookRecipe { pub fn new(name: PackageName, dir: PathBuf, recipe: Recipe) -> Result { @@ -220,6 +236,7 @@ impl CookRecipe { pub fn new_recursive( names: &[PackageName], recurse_build_deps: bool, + recurse_dev_build_deps: bool, recurse_package_deps: bool, collect_build_deps: bool, collect_package_deps: bool, @@ -238,6 +255,30 @@ impl CookRecipe { let dependencies = Self::new_recursive( &recipe.recipe.build.dependencies, recurse_build_deps, + recurse_dev_build_deps, + recurse_package_deps, + collect_build_deps, + collect_package_deps, + collect_build_deps, + recursion - 1, + ) + .map_err(|mut err| { + err.append_recursion(name); + err + })?; + + for dependency in dependencies { + if !recipes.contains(&dependency) { + recipes.push(dependency); + } + } + } + + if recurse_dev_build_deps { + let dependencies = Self::new_recursive( + &recipe.recipe.build.dev_dependencies, + recurse_build_deps, + recurse_dev_build_deps, recurse_package_deps, collect_build_deps, collect_package_deps, @@ -260,6 +301,7 @@ impl CookRecipe { let dependencies = Self::new_recursive( &recipe.recipe.package.dependencies, recurse_build_deps, + recurse_dev_build_deps, recurse_package_deps, collect_build_deps, collect_package_deps, @@ -288,9 +330,19 @@ impl CookRecipe { pub fn get_build_deps_recursive( names: &[PackageName], + include_dev: bool, mark_is_deps: bool, ) -> Result, PackageError> { - let mut packages = Self::new_recursive(names, true, false, true, false, true, WALK_DEPTH)?; + let mut packages = Self::new_recursive( + names, + true, + include_dev, + false, + true, + false, + true, + WALK_DEPTH, + )?; if mark_is_deps { for package in packages.iter_mut() { @@ -306,8 +358,16 @@ impl CookRecipe { include_names: bool, ) -> Result, PackageError> { // recurse_build_deps == true here as libraries (build deps) can have runtime files (package deps) - let packages = - Self::new_recursive(names, true, true, false, true, include_names, WALK_DEPTH)?; + let packages = Self::new_recursive( + names, + true, + false, + true, + false, + true, + include_names, + WALK_DEPTH, + )?; Ok(packages.into_iter().map(|p| p.name).collect()) } @@ -351,13 +411,10 @@ mod tests { script: None, shallow_clone: None, }), - build: BuildRecipe { - kind: BuildKind::Cargo { - package_path: None, - cargoflags: String::new(), - }, - dependencies: Vec::new(), - }, + build: BuildRecipe::new(BuildKind::Cargo { + package_path: None, + cargoflags: String::new(), + }), package: PackageRecipe::default(), } ); @@ -392,12 +449,9 @@ mod tests { patches: Vec::new(), script: None, }), - build: BuildRecipe { - kind: BuildKind::Custom { - script: "make".to_string() - }, - dependencies: Vec::new(), - }, + build: BuildRecipe::new(BuildKind::Custom { + script: "make".to_string() + }), package: PackageRecipe::default(), } ); @@ -424,10 +478,7 @@ mod tests { recipe, Recipe { source: None, - build: BuildRecipe { - kind: BuildKind::None, - dependencies: Vec::new(), - }, + build: BuildRecipe::new(BuildKind::None), package: PackageRecipe { dependencies: vec![PackageName::new("gcc13").unwrap()], version: None,