Skip to content

Commit

Permalink
feat: add pixi-build behind preview feature (#2514)
Browse files Browse the repository at this point in the history
Co-authored-by: Ruben Arts <[email protected]>
Co-authored-by: Bas Zalmstra <[email protected]>
  • Loading branch information
3 people authored Nov 22, 2024
1 parent 34115e9 commit 0e1a25e
Show file tree
Hide file tree
Showing 21 changed files with 709 additions and 743 deletions.
1 change: 1 addition & 0 deletions crates/pixi_build_frontend/tests/basic/pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ channels = ["conda-forge"]
description = "Add a short description here"
name = "basic"
platforms = ["osx-arm64"]
preview = ["pixi-build"]
version = "0.1.0"

[tasks]
Expand Down
1 change: 1 addition & 0 deletions crates/pixi_build_frontend/tests/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ async fn test_missing_backend() {
name = "project"
platforms = []
channels = []
preview = ['pixi-build']
[build-system]
dependencies = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ expression: snapshot
---
Globs:
- tests/data/satisfiability/source-dependency/**/*
Hash: 218e03654fe6ebe41d9488d62e24584d118e8bbc06aa054d6b64d2538abc6d01
Hash: bcec5beb36091c68ee58f72f1f4d33f3658b98732912f2cbe5827898d8a666f9
Matched files:
- tests/data/satisfiability/source-dependency/child-package/pixi.toml
- tests/data/satisfiability/source-dependency/pixi.lock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ expression: snapshot
Globs:
- tests/data/satisfiability/source-dependency/**/*
- !tests/data/satisfiability/source-dependency/**/*.lock
Hash: d0ddcb9b7cb2d9174875232dfa29e52f6e1b8e43cdcae03fea11af0177c4c2d7
Hash: c0506e1c483578c78217015a4b19e90826c005bfe2ed9a59c83bc2054d4b5d4a
Matched files:
- tests/data/satisfiability/source-dependency/child-package/pixi.toml
- tests/data/satisfiability/source-dependency/pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ expression: snapshot
---
Globs:
- tests/data/satisfiability/source-dependency/pixi.toml
Hash: 3fd25b6fc88a942ba43885b4b561385b819d879ffe28fc64a06beec4fa87a757
Hash: 0acde3549cf146ff910d07405f8146dea0659c19b25d6292048da9f2d47e667e
Matched files:
- tests/data/satisfiability/source-dependency/pixi.toml
68 changes: 66 additions & 2 deletions crates/pixi_manifest/src/manifests/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,8 +733,8 @@ impl Manifest {
}

/// Returns the preview field of the project
pub fn preview(&self) -> Option<&Preview> {
self.workspace.workspace.preview.as_ref()
pub fn preview(&self) -> &Preview {
&self.workspace.workspace.preview
}

/// Return the build section from the parsed manifest
Expand Down Expand Up @@ -2355,4 +2355,68 @@ bar = "*"
.collect();
assert_eq!(channels, vec!["pytorch", "conda-forge", "bioconda"]);
}

#[test]
fn test_validation_failure_source_dependency() {
let toml = r#"
[project]
name = "test"
channels = ['conda-forge']
platforms = ['linux-64']
[dependencies]
foo = { path = "./foo" }
"#;

let manifest = Manifest::from_str(Path::new("pixi.toml"), toml);
let err = manifest.unwrap_err();
insta::assert_snapshot!(err, @"source dependencies are used in the feature 'default', but the `pixi-build` preview feature is not enabled");
}

#[test]
fn test_validation_failure_build_section() {
let toml = r#"
[project]
name = "test"
channels = ['conda-forge']
platforms = ['linux-64']
[build-system]
build-backend = "pixi-build-cmake"
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/conda-forge",
]
dependencies = ["pixi-build-cmake"]
"#;

let manifest = Manifest::from_str(Path::new("pixi.toml"), toml);
let err = manifest.unwrap_err();
insta::assert_snapshot!(err, @"the build-system is defined, but the `pixi-build` preview feature is not enabled");
}

#[test]
fn test_validation_succeed_build() {
let toml = r#"
[project]
name = "test"
channels = ['conda-forge']
platforms = ['linux-64']
preview = ["pixi-build"]
[build-system]
build-backend = "pixi-build-cmake"
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/conda-forge",
]
dependencies = ["pixi-build-cmake"]
[dependencies]
foo = { path = "./foo" }
"#;

let manifest = Manifest::from_str(Path::new("pixi.toml"), toml);
manifest.unwrap();
}
}
9 changes: 8 additions & 1 deletion crates/pixi_manifest/src/preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ pub enum Preview {
Features(Vec<PreviewFeature>), // For `preview = ["feature"]`
}

impl Default for Preview {
fn default() -> Self {
Self::Features(Vec::new())
}
}

impl Preview {
/// Returns true if all preview features are enabled
pub fn all_enabled(&self) -> bool {
Expand Down Expand Up @@ -92,7 +98,8 @@ impl PartialEq<KnownPreviewFeature> for PreviewFeature {
#[serde(rename_all = "kebab-case")]
/// Currently supported preview features are listed here
pub enum KnownPreviewFeature {
// Add known features here
/// Build feature, to enable conda source builds
PixiBuild,
}

impl<'de> Deserialize<'de> for PreviewFeature {
Expand Down
82 changes: 69 additions & 13 deletions crates/pixi_manifest/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use std::{

use super::pypi::pypi_options::PypiOptions;
use crate::{
Environment, Feature, FeatureName, SystemRequirements, TargetSelector, WorkspaceManifest,
Environment, Feature, FeatureName, KnownPreviewFeature, SystemRequirements, TargetSelector,
WorkspaceManifest,
};

impl WorkspaceManifest {
Expand Down Expand Up @@ -133,18 +134,47 @@ impl WorkspaceManifest {
}

// Warn on any unknown preview features
if let Some(preview) = self.workspace.preview.as_ref() {
let preview = preview.unknown_preview_features();
if !preview.is_empty() {
let are = if preview.len() > 1 { "are" } else { "is" };
let s = if preview.len() > 1 { "s" } else { "" };
let preview_array = if preview.len() == 1 {
format!("{:?}", preview)
} else {
format!("[{:?}]", preview.iter().format(", "))
};
tracing::warn!(
"The preview feature{s}: {preview_array} {are} defined in the manifest but un-used pixi");
let preview = self.workspace.preview.unknown_preview_features();
if !preview.is_empty() {
let are = if preview.len() > 1 { "are" } else { "is" };
let s = if preview.len() > 1 { "s" } else { "" };
let preview_array = if preview.len() == 1 {
format!("{:?}", preview)
} else {
format!("[{:?}]", preview.iter().format(", "))
};
tracing::warn!(
"The preview feature{s}: {preview_array} {are} defined in the manifest but un-used pixi");
}

// Check if the pixi build feature is enabled
let build_enabled = self
.workspace
.preview
.is_enabled(KnownPreviewFeature::PixiBuild);

// Error any conda source dependencies are used and is not set
if !build_enabled {
let supported_platforms = self.workspace.platforms.as_ref();
// Check all features for source dependencies
for feature in self.features.values() {
if is_using_source_deps(feature, supported_platforms.iter()) {
return Err(miette::miette!(
help = "enable the `pixi-build` preview feature to use source dependencies",
"source dependencies are used in the feature '{}', but the `pixi-build` preview feature is not enabled",
feature.name
));
}
}

if self.build_system.is_some() {
// Check if we have enabled the build feature if we have a build section
if !build_enabled {
return Err(miette::miette!(
help = "enable the `pixi-build` preview feature to use the build-system section by setting `preview = [\"pixi-build\"]",
"the build-system is defined, but the `pixi-build` preview feature is not enabled"
));
}
}
}

Expand Down Expand Up @@ -244,6 +274,32 @@ impl WorkspaceManifest {
}
}

/// Check if any feature is making use of conda source dependencies
fn is_using_source_deps<'a>(
feature: &Feature,
supported_platforms: impl IntoIterator<Item = &'a Platform>,
) -> bool {
// List all spec types
let spec_types = [
crate::SpecType::Build,
crate::SpecType::Run,
crate::SpecType::Host,
];
// Check if any of the spec types have source dependencies
for platform in supported_platforms {
for spec in spec_types {
let deps = feature.dependencies(spec, Some(*platform));
if let Some(deps) = deps {
if deps.iter().any(|(_, spec)| spec.is_source()) {
return true;
}
}
}
}

false
}

// Create an error report for using a platform that is not supported by the
// project.
fn create_unsupported_platform_report(
Expand Down
6 changes: 3 additions & 3 deletions crates/pixi_manifest/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use serde_with::{serde_as, DisplayFromStr};
use url::Url;

use super::pypi::pypi_options::PypiOptions;
use crate::preview::Preview;
use crate::utils::PixiSpanned;
use crate::{preview::Preview, utils::PixiSpanned};

/// Describes the contents of the `[package]` section of the project manifest.
#[serde_as]
Expand Down Expand Up @@ -67,5 +66,6 @@ pub struct Workspace {
pub pypi_options: Option<PypiOptions>,

/// Preview features
pub preview: Option<Preview>,
#[serde(default)]
pub preview: Preview,
}
8 changes: 4 additions & 4 deletions examples/cpp-sdl/pixi.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/cpp-sdl/pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ channels = ["https://fast.prefix.dev/conda-forge"]
description = "Showcases how to create a simple C++ executable with Pixi"
name = "sdl_example"
platforms = ["win-64", "linux-64", "osx-arm64", "osx-64"]
preview = ["pixi-build"]

[build-system]
build-backend = "pixi-build-cmake"
Expand Down
Loading

0 comments on commit 0e1a25e

Please sign in to comment.