feat: Extra build dependencies#5746
Open
HARSHVARANDANI wants to merge 32 commits intoprefix-dev:mainfrom
Open
Conversation
e714a86 to
a6604de
Compare
Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
… CI since the function is no longer unused Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
…accepted in a real pypi lock/update Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
… requires/config/variables instead of local defaults Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
…rams Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
…est during both lock update context initialization paths Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
… the conversion behavior Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
…OML conversion Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
…EP508 build requirements Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
…te dependencies Signed-off-by: HARSHVARANDANI <hpvarandani@gmail.com>
a6604de to
896a854
Compare
Author
|
@baszalmstra Could you take a look at this when you've got time? Some feedback would be really helpful. |
tdejager
requested changes
Mar 31, 2026
Comment on lines
+31
to
+69
| /// Convert manifest-defined extra build dependencies into uv's | ||
| /// [`ExtraBuildRequires`] structure. | ||
| /// | ||
| /// Each manifest requirement is converted to a uv requirement and wrapped in an | ||
| /// [`ExtraBuildRequirement`] with `match_runtime = false` for v1 behavior. | ||
| /// | ||
| /// The `workspace_root` parameter is currently unused but kept in the API to | ||
| /// preserve call-site intent and future conversion support for path-based | ||
| /// requirement forms. | ||
| pub fn convert_extra_build_dependencies( | ||
| deps: &Option<IndexMap<PypiPackageName, Vec<pep508_rs::Requirement>>>, | ||
| _workspace_root: &Path, | ||
| ) -> Result<ExtraBuildRequires, pixi_uv_conversions::ConversionError> { | ||
| let mut extra_build_requires = ExtraBuildRequires::default(); | ||
|
|
||
| for (package, specs) in deps.iter().flatten() { | ||
| let requirements = specs | ||
| .iter() | ||
| .map(|spec| { | ||
| pep508_requirement_to_uv_requirement(spec.clone()).map(|requirement| { | ||
| ExtraBuildRequirement { | ||
| requirement, | ||
| match_runtime: false, | ||
| } | ||
| }) | ||
| }) | ||
| .collect::<Result<Vec<_>, _>>()?; | ||
|
|
||
| if requirements.is_empty() { | ||
| continue; | ||
| } | ||
|
|
||
| let package_name = uv_normalize::PackageName::from_str(package.as_normalized().as_ref()) | ||
| .expect("pypi package names in manifest should always be valid"); | ||
| extra_build_requires.insert(package_name, requirements); | ||
| } | ||
|
|
||
| Ok(extra_build_requires) | ||
| } |
Contributor
There was a problem hiding this comment.
I think this can go into the pixi_uv_conversions crate.
Comment on lines
+208
to
+239
| mod tests { | ||
| use std::str::FromStr; | ||
|
|
||
| use indexmap::IndexMap; | ||
| use pixi_pypi_spec::PypiPackageName; | ||
|
|
||
| use super::convert_extra_build_dependencies; | ||
|
|
||
| #[test] | ||
| fn converts_extra_build_dependencies() { | ||
| let mut deps: IndexMap<PypiPackageName, Vec<pep508_rs::Requirement>> = IndexMap::new(); | ||
| deps.insert( | ||
| PypiPackageName::from_str("fused-ssim").unwrap(), | ||
| vec![pep508_rs::Requirement::from_str("torch>=2").unwrap()], | ||
| ); | ||
|
|
||
| let converted = convert_extra_build_dependencies(&Some(deps), std::path::Path::new(".")) | ||
| .expect("conversion should succeed"); | ||
|
|
||
| let pkg_name = uv_normalize::PackageName::from_str("fused-ssim").unwrap(); | ||
| let requirements = converted.get(&pkg_name).expect("package should be present"); | ||
| assert_eq!(requirements.len(), 1); | ||
| assert_eq!(requirements[0].requirement.name.as_ref(), "torch"); | ||
| assert!(!requirements[0].match_runtime); | ||
| } | ||
|
|
||
| #[test] | ||
| fn empty_extra_build_dependencies_is_noop() { | ||
| let converted = convert_extra_build_dependencies(&None, std::path::Path::new(".")).unwrap(); | ||
| assert!(converted.is_empty()); | ||
| } | ||
| } |
tdejager
requested changes
Mar 31, 2026
Contributor
tdejager
left a comment
There was a problem hiding this comment.
Also we @ruben-arts pointed me to this but we should make the extra-build-dependencies avialable under the dependency types, merge these across feature somehow and re-construct the map before doing the environment installation and solve.
Author
|
@tdejager I have made requested changes. If you could please check for any more changes needed? |
Contributor
|
Hey, this did not make the changes we requested its still a top-level table. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR adds support for specifying extra build dependencies for PyPI packages via pixi.toml.
Some PyPI packages rely on build-time dependencies that are not properly declared in their build-system.requires. This can cause builds to fail when using build isolation, making environments non-reproducible without manual intervention.
This change allows users to explicitly declare missing build dependencies directly in pixi.toml, enabling reproducible environments using a single configuration file.
Example:
Pixi will ensure that the specified dependencies are available in the PEP 517 build environment when building the package.
Motivation
Certain PyPI packages import or require dependencies during build time but fail to declare them in their metadata.
Examples include packages that:
Without this feature, users must:
This reduces reproducibility and complicates workflows.
This feature brings Pixi in line with similar functionality already available in uv.
Fixes #5614
Behavior
When building a PyPI package from source:
Extra dependencies are only available during the build phase and are not installed in the runtime environment unless explicitly declared in
[pypi-dependencies].How Has This Been Tested?
Integration tests confirm:
A custom test package requiring numpy during build phase was used to validate the full pipeline.
AI Disclosure
Checklist: