Skip to content

Commit 511411d

Browse files
authored
feat: add variants.yaml for troubleshooting (#439)
* misc: always log variants.yaml * feat: store recipe under separate variant hash * misc: update docs * misc: rename dirs * misc: change section
1 parent b44281c commit 511411d

File tree

2 files changed

+162
-19
lines changed

2 files changed

+162
-19
lines changed

crates/pixi-build-backend/src/intermediate_backend.rs

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ where
336336
let mut outputs = Vec::new();
337337

338338
let num_of_outputs = discovered_outputs.len();
339+
340+
let mut variants_saved = false;
341+
339342
for discovered_output in discovered_outputs {
340343
let variant = discovered_output.used_vars;
341344
let hash = HashInfo::from_variant(&variant, &discovered_output.noarch_type);
@@ -377,17 +380,52 @@ where
377380
&named_source.path,
378381
);
379382

380-
// Save intermediate recipe in the debug dir
381-
let debug_path = directories.work_dir.join("recipe.yaml");
382-
tokio_fs::create_dir_all(&directories.work_dir)
383+
// Save intermediate recipe and the used variant
384+
// in the work dir by hash of the variant
385+
// and entire variants.yaml at the root of work_dir
386+
let work_dir = &directories.work_dir;
387+
388+
let recipe_path = work_dir.join("recipe.yaml");
389+
let variants_path = work_dir.join("variants.yaml");
390+
391+
let package_work_dir = work_dir.join("recipe").join(&hash.hash);
392+
let package_recipe_path = package_work_dir.join("recipe.yaml");
393+
let package_variant_path = package_work_dir.join("variants.yaml");
394+
395+
tokio_fs::create_dir_all(&package_work_dir)
396+
.await
397+
.into_diagnostic()?;
398+
399+
let recipe_yaml = generated_recipe.recipe.to_yaml_pretty().into_diagnostic()?;
400+
401+
tokio_fs::write(&package_recipe_path, &recipe_yaml)
383402
.await
384403
.into_diagnostic()?;
385-
tokio_fs::write(
386-
&debug_path,
387-
generated_recipe.recipe.to_yaml_pretty().into_diagnostic()?,
388-
)
389-
.await
390-
.into_diagnostic()?;
404+
405+
let variant_yaml = serde_yaml::to_string(&variant)
406+
.into_diagnostic()
407+
.context("failed to serialize variant to YAML")?;
408+
409+
tokio_fs::write(&package_variant_path, variant_yaml)
410+
.await
411+
.into_diagnostic()?;
412+
413+
// write the entire variants.yaml at the root of work_dir
414+
if !variants_saved {
415+
let variants = serde_yaml::to_string(&variant_config)
416+
.into_diagnostic()
417+
.context("failed to serialize variant config to YAML")?;
418+
419+
tokio_fs::write(&variants_path, variants)
420+
.await
421+
.into_diagnostic()?;
422+
423+
tokio_fs::write(&recipe_path, recipe_yaml)
424+
.await
425+
.into_diagnostic()?;
426+
427+
variants_saved = true;
428+
}
391429

392430
subpackages.insert(
393431
recipe.package().name().clone(),
@@ -569,6 +607,7 @@ where
569607
recipe_path: Some(self.source_dir.join(&self.manifest_rel_path)),
570608
};
571609
let outputs = find_outputs_from_src(named_source.clone())?;
610+
572611
let variant_config = VariantConfig {
573612
variants,
574613
pin_run_as_build: None,
@@ -591,17 +630,56 @@ where
591630
recipe_path,
592631
);
593632

594-
// Save intermediate recipe in the debug dir
595-
let debug_path = directories.work_dir.join("recipe.yaml");
596-
tokio_fs::create_dir_all(&directories.work_dir)
633+
// Save intermediate recipe and the used variant
634+
// in the work dir by hash of the variant
635+
let variant = discovered_output.used_vars;
636+
637+
// Save intermediate recipe and the used variant
638+
// in the work dir by hash of the variant
639+
// and entire variants.yaml at the root of work_dir
640+
let work_dir = &directories.work_dir;
641+
642+
let recipe_path = work_dir.join("recipe.yaml");
643+
let variants_path = work_dir.join("variants.yaml");
644+
645+
let package_dir = directories
646+
.work_dir
647+
.join("recipe")
648+
.join(&discovered_output.hash.hash);
649+
650+
let package_recipe_path = package_dir.join("recipe.yaml");
651+
let package_variant_path = package_dir.join("variants.yaml");
652+
653+
tokio_fs::create_dir_all(&package_dir)
654+
.await
655+
.into_diagnostic()?;
656+
657+
let recipe_yaml = recipe.recipe.to_yaml_pretty().into_diagnostic()?;
658+
659+
tokio_fs::write(&package_recipe_path, &recipe_yaml)
660+
.await
661+
.into_diagnostic()?;
662+
663+
let variant_yaml = serde_yaml::to_string(&variant)
664+
.into_diagnostic()
665+
.context("failed to serialize variant to YAML")?;
666+
667+
tokio_fs::write(&package_variant_path, variant_yaml)
668+
.await
669+
.into_diagnostic()?;
670+
671+
// write the entire variants.yaml at the root of work_dir
672+
let variants = serde_yaml::to_string(&variant_config)
673+
.into_diagnostic()
674+
.context("failed to serialize variant config to YAML")?;
675+
676+
tokio_fs::write(&variants_path, variants)
677+
.await
678+
.into_diagnostic()?;
679+
680+
tokio_fs::write(&recipe_path, recipe_yaml)
597681
.await
598682
.into_diagnostic()?;
599-
tokio_fs::write(
600-
&debug_path,
601-
recipe.recipe.to_yaml_pretty().into_diagnostic()?,
602-
)
603-
.await
604-
.into_diagnostic()?;
605683

606684
let tool_config = Configuration::builder()
607685
.with_opt_cache_dir(self.cache_dir.clone())
@@ -627,7 +705,7 @@ where
627705
virtual_packages: vec![],
628706
},
629707
hash: discovered_output.hash,
630-
variant: discovered_output.used_vars.clone(),
708+
variant,
631709
directories,
632710
channels: vec![],
633711
channel_priority: Default::default(),

docs/index.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,71 @@ Check out our [tutorial series](https://pixi.sh/latest/build/getting_started/) t
4747

4848
Learn how pixi-build integrates with conda-forge's compiler infrastructure to provide cross-platform, ABI-compatible builds. Covers compiler configuration, platform-specific behavior, and available compiler options for supported backends.
4949

50+
## 🔧 Troubleshooting
51+
52+
### Rebuilding Generated Recipes
53+
54+
When you build a package using `pixi build`, the build backends generate a complete rattler-build recipe that is stored in your project's build directory. This can be useful for debugging build issues or understanding exactly how your package is being built.
55+
56+
### Recipe Locations
57+
58+
The build backends generate recipes in two locations:
59+
60+
#### 1. General Recipe (all outputs)
61+
62+
```
63+
<your_project>/.pixi/build/work/<package-name>--<hash>/work/
64+
```
65+
66+
This directory contains:
67+
68+
- `recipe.yaml` - A general recipe that can build all package outputs
69+
- `variants.yaml` - All variant configurations for the package
70+
71+
#### 2. Variant-Specific Recipe (single output)
72+
73+
```
74+
<your_project>/.pixi/build/work/<package-name>--<hash>/work/recipe/<variant_hash>/
75+
```
76+
77+
This directory contains:
78+
79+
- `recipe.yaml` - The complete rattler-build recipe generated by the build backend
80+
- `variants.yaml` - The variant configuration used for this specific build
81+
82+
### Rebuilding a Package
83+
84+
To debug or rebuild a package using the same configuration, you have two options:
85+
86+
### Option 1: Navigate to the recipe directory
87+
88+
1. Navigate to the recipe directory:
89+
```bash
90+
cd .pixi/build/work/<package-name>--<hash>/work/recipe/<variant_hash>/
91+
```
92+
93+
2. Use `rattler-build` to rebuild the package:
94+
```bash
95+
rattler-build build
96+
```
97+
98+
### Option 2: Point to the recipe directory
99+
100+
Use the `--recipe` flag to build without changing directories:
101+
102+
```bash
103+
rattler-build build --recipe .pixi/build/work/<package-name>--<hash>/work/recipe/<variant_hash>/
104+
```
105+
106+
This allows you to:
107+
108+
* Inspect the exact recipe that was generated
109+
* Debug build failures with direct access to `rattler-build`
110+
* Understand how the build backend translated your project model (`pixi.toml`)
111+
112+
!!! tip
113+
The `<variant_hash>` ensures that each unique combination of build variants gets its own recipe directory, making it easy to compare different build configurations.
114+
50115
## 🔗 Useful Links
51116

52117
- [GitHub](https://github.com/prefix-dev/pixi): Pixi source code, feel free to leave a star!

0 commit comments

Comments
 (0)