Skip to content

Commit

Permalink
feat: preview of pixi build and workspaces (prefix-dev#2250)
Browse files Browse the repository at this point in the history
## Pixi Build

This PR will incorporate the first, pre-alpha version of pixi build.
This exposes the feature to use source dependencies, which will be built
into `.conda` dependencies. 

---------

Co-authored-by: Bas Zalmstra <[email protected]>
Co-authored-by: Bas Zalmstra <[email protected]>
Co-authored-by: Ruben Arts <[email protected]>
Co-authored-by: nichmor <[email protected]>
Co-authored-by: Ruben Arts <[email protected]>
  • Loading branch information
6 people authored Nov 27, 2024
1 parent 7553b78 commit 32900a0
Show file tree
Hide file tree
Showing 235 changed files with 14,526 additions and 7,223 deletions.
577 changes: 529 additions & 48 deletions Cargo.lock

Large diffs are not rendered by default.

48 changes: 34 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ repository = "https://github.com/prefix-dev/pixi"
[workspace.dependencies]
ahash = "0.8.11"
assert_matches = "1.5.0"
async-fd-lock = "0.2.0"
async-once-cell = "0.5.3"
async-trait = "0.1.82"
base64 = "0.22.1"
chrono = "0.4.38"
clap = { version = "4.5.9", default-features = false }
clap-verbosity-flag = "2.2.0"
Expand Down Expand Up @@ -47,8 +49,10 @@ indicatif = "0.17.8"
insta = "1.38.0"
is_executable = "1.0.1"
itertools = "0.13.0"
jsonrpsee = "=0.24.2"
lazy_static = "1.4.0"
libc = { version = "0.2.153", default-features = false }
memchr = "2.7.4"
miette = { version = "7.2.0", features = ["fancy"] }
minijinja = "2.1.1"
nix = { version = "0.29.0", default-features = false }
Expand All @@ -72,6 +76,7 @@ serde_ignored = "0.1.10"
serde_json = "1.0.116"
serde_with = "3.7.0"
serde_yaml = "0.9.34"
sha1 = "0.10.6"
shlex = "1.3.0"
signal-hook = "0.3.17"
spdx = "0.10.4"
Expand All @@ -85,7 +90,7 @@ tokio-util = "0.7.10"
toml_edit = "0.22.11"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
typed-path = "0.9.1"
typed-path = "0.9.2"
uv-distribution-filename = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
uv-distribution-types = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
uv-install-wheel = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
Expand All @@ -94,6 +99,8 @@ uv-pep508 = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
uv-platform-tags = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
uv-pypi-types = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
uv-requirements-txt = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
wax = "0.6.0"
which = "6.0.3"

# Rattler crates
file_url = "0.1.4"
Expand All @@ -110,6 +117,7 @@ rattler_shell = { version = "0.22.6", default-features = false }
rattler_solve = { version = "1.2.2", default-features = false }
rattler_virtual_packages = { version = "1.1.9", default-features = false }


# Bumping this to a higher version breaks the Windows path handling.
url = "2.5.2"
uv-auth = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
Expand All @@ -131,18 +139,21 @@ zip = { version = "2.2.0", default-features = false }
zstd = { version = "0.13.2", default-features = false }

fancy_display = { path = "crates/fancy_display" }
pixi_build_frontend = { path = "crates/pixi_build_frontend" }
pixi_build_types = { path = "crates/pixi_build_types" }
pixi_config = { path = "crates/pixi_config" }
pixi_consts = { path = "crates/pixi_consts" }
pixi_default_versions = { path = "crates/pixi_default_versions" }
pixi_glob = { path = "crates/pixi_glob" }
pixi_manifest = { path = "crates/pixi_manifest" }
pixi_progress = { path = "crates/pixi_progress" }
pixi_record = { path = "crates/pixi_record" }
pixi_spec = { path = "crates/pixi_spec" }
pixi_utils = { path = "crates/pixi_utils", default-features = false }
pixi_uv_conversions = { path = "crates/pixi_uv_conversions" }
pypi_mapping = { path = "crates/pypi_mapping" }
pypi_modifiers = { path = "crates/pypi_modifiers" }


[package]
authors.workspace = true
description = "A package management and workflow tool"
Expand Down Expand Up @@ -176,8 +187,10 @@ slow_integration_tests = []
[dependencies]
ahash = { workspace = true }
assert_matches = { workspace = true }
async-fd-lock = { workspace = true }
async-once-cell = { workspace = true }
barrier_cell = { path = "crates/barrier_cell" }
base64 = { workspace = true }
chrono = { workspace = true }
clap = { workspace = true, features = [
"derive",
Expand Down Expand Up @@ -219,6 +232,7 @@ miette = { workspace = true, features = [
minijinja = { workspace = true, features = ["builtins"] }
once_cell = { workspace = true }
parking_lot = { workspace = true }
rstest = { workspace = true }
uv-distribution-filename = { workspace = true }
uv-distribution-types = { workspace = true }
uv-install-wheel = { workspace = true }
Expand All @@ -241,12 +255,17 @@ uv-pep440 = { workspace = true }
uv-pep508 = { workspace = true }
uv-pypi-types = { workspace = true }

dirs = "5.0.1"
fs-err = { workspace = true, features = ["tokio"] }
pixi_build_frontend = { workspace = true }
pixi_build_types = { workspace = true }
pixi_config = { workspace = true }
pixi_consts = { workspace = true }
pixi_default_versions = { workspace = true }
pixi_glob = { workspace = true }
pixi_manifest = { workspace = true }
pixi_progress = { workspace = true }
pixi_record = { workspace = true }
pixi_spec = { workspace = true }
pixi_utils = { workspace = true, default-features = false }
pixi_uv_conversions = { workspace = true }
Expand Down Expand Up @@ -275,6 +294,7 @@ tokio-util = { workspace = true }
toml_edit = { workspace = true, features = ["serde"] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
typed-path = { workspace = true }
url = { workspace = true }
uv-auth = { workspace = true }
uv-cache = { workspace = true }
Expand All @@ -293,7 +313,6 @@ xxhash-rust = { workspace = true }
zip = { workspace = true, features = ["deflate", "time"] }
zstd = { workspace = true }


[target.'cfg(unix)'.dependencies]
libc = { workspace = true, default-features = false }
nix = { workspace = true, features = ["poll", "term"] }
Expand Down Expand Up @@ -335,18 +354,19 @@ reqwest-retry = { git = "https://github.com/TrueLayer/reqwest-middleware", rev =
# pep508_rs = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" }
# deno_task_shell = { path = "../deno_task_shell" }

#rattler = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_cache = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_digest = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_lock = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_networking = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_package_streaming = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_shell = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_solve = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
#rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" }
file_url = { git = "https://github.com/conda/rattler", branch = "main" }
rattler = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_conda_types = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_digest = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_lock = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_networking = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_package_streaming = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_repodata_gateway = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_shell = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_solve = { git = "https://github.com/conda/rattler", branch = "main" }
rattler_virtual_packages = { git = "https://github.com/conda/rattler", branch = "main" }

#file_url = { path = "../rattler/crates/file_url" }
#rattler = { path = "../rattler/crates/rattler" }
#rattler_cache = { path = "../rattler/crates/rattler_cache" }
#rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" }
Expand Down
47 changes: 47 additions & 0 deletions crates/pixi_build_frontend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[package]
authors.workspace = true
description = "Sets up environments to use for building of pixi.toml files"
edition.workspace = true
homepage.workspace = true
license.workspace = true
name = "pixi_build_frontend"
readme.workspace = true
repository.workspace = true
version = "0.1.0"

[dependencies]
dashmap = { workspace = true }
futures = { workspace = true }
itertools = { workspace = true }
jsonrpsee = { workspace = true, features = ["client"] }
miette = { workspace = true, features = ["fancy", "serde"] }
pixi_config = { workspace = true }
pixi_consts = { workspace = true }
pixi_manifest = { workspace = true }
pixi_utils = { workspace = true, features = ["rustls-tls"] }
rattler = { workspace = true }
rattler_conda_types = { workspace = true }
rattler_repodata_gateway = { workspace = true, features = ["gateway"] }
rattler_shell = { workspace = true }
rattler_solve = { workspace = true, features = ["resolvo"] }
rattler_virtual_packages = { workspace = true }
regex = { workspace = true }
reqwest-middleware = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
serde_with = { workspace = true }
serde_yaml = { workspace = true }
sha1 = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["process", "io-std"] }
tokio-util = { workspace = true, features = ["codec"] }
tracing = { workspace = true }
url = "2.5.0"
which = { workspace = true }

pixi_build_types = { path = "../pixi_build_types" }

[dev-dependencies]
insta = { workspace = true, features = ["yaml", "filters"] }
rstest = { workspace = true }
tempfile = { workspace = true }
125 changes: 125 additions & 0 deletions crates/pixi_build_frontend/src/build_frontend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//! This module is the main entry
use std::{path::PathBuf, sync::Arc};

use miette::Diagnostic;
use rattler_conda_types::ChannelConfig;

use crate::{
protocol,
protocol_builder::{EnabledProtocols, ProtocolBuilder},
tool::{ToolCache, ToolContext},
Protocol, SetupRequest,
};

/// The frontend for building packages.
pub struct BuildFrontend {
/// The cache for tools. This is used to avoid re-installing tools.
tool_cache: Arc<ToolCache>,

/// The channel configuration used by the frontend
channel_config: ChannelConfig,

/// The cache directory to use or `None` to use the default cache directory.
cache_dir: Option<PathBuf>,

/// The configuration to use when enabling the protocols.
enabled_protocols: EnabledProtocols,
}

impl Default for BuildFrontend {
fn default() -> Self {
Self {
tool_cache: Arc::new(ToolCache::new()),
channel_config: ChannelConfig::default_with_root_dir(PathBuf::new()),
cache_dir: None,
enabled_protocols: EnabledProtocols::default(),
}
}
}

#[derive(thiserror::Error, Debug, Diagnostic)]
pub enum BuildFrontendError {
/// Error while discovering the pixi.toml
#[error(transparent)]
#[diagnostic(transparent)]
DiscoveringManifest(#[from] protocol::DiscoveryError),
/// Error from the build protocol.
#[error(transparent)]
#[diagnostic(transparent)]
Protocol(#[from] protocol::FinishError),
/// Error discovering system-tool
#[error("error discovering system-tool")]
ToolError(#[from] which::Error),
}

impl BuildFrontend {
/// Specify the channel configuration
pub fn with_channel_config(self, channel_config: ChannelConfig) -> Self {
Self {
channel_config,
..self
}
}

/// Returns the channel config of the frontend
pub fn channel_config(&self) -> &ChannelConfig {
&self.channel_config
}

/// Optionally sets the cache directory the backend should use.
pub fn with_opt_cache_dir(self, cache_dir: Option<PathBuf>) -> Self {
Self { cache_dir, ..self }
}

/// Sets the cache directory the backend should use.
pub fn with_cache_dir(self, cache_dir: PathBuf) -> Self {
Self {
cache_dir: Some(cache_dir),
..self
}
}

/// Sets the tool context
pub fn with_tool_context(self, context: ToolContext) -> Self {
let tool_cache = ToolCache {
cache: self.tool_cache.cache.clone(),
context,
};

Self {
tool_cache: tool_cache.into(),
..self
}
}

/// Sets the enabling protocols.
pub fn with_enabled_protocols(self, enabled_protocols: EnabledProtocols) -> Self {
Self {
enabled_protocols,
..self
}
}

/// Constructs a new [`Protocol`] for the given request. This object can be
/// used to build the package.
pub async fn setup_protocol(
&self,
request: SetupRequest,
) -> Result<Protocol, BuildFrontendError> {
// Determine the build protocol to use for the source directory.
let protocol = ProtocolBuilder::discover(&request.source_dir, &self.enabled_protocols)?
.with_channel_config(self.channel_config.clone())
.with_opt_cache_dir(self.cache_dir.clone());

tracing::info!(
"discovered a {} source package at {}",
protocol.name(),
request.source_dir.display()
);

protocol
.with_backend_override(request.build_tool_override)
.finish(&self.tool_cache, request.build_id)
.await
}
}
22 changes: 22 additions & 0 deletions crates/pixi_build_frontend/src/jsonrpc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use jsonrpsee::core::traits::ToRpcParams;
use serde::Serialize;
use serde_json::value::RawValue;

mod stdio;
pub(crate) use stdio::{stdio_transport, Receiver, Sender};

/// A helper struct to convert a serializable type into a JSON-RPC parameter.
pub struct RpcParams<T>(pub T);

impl<T: Serialize> ToRpcParams for RpcParams<T> {
fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, serde_json::Error> {
let json = serde_json::to_string(&self.0)?;
RawValue::from_string(json).map(Some)
}
}

impl<T> From<T> for RpcParams<T> {
fn from(value: T) -> Self {
Self(value)
}
}
Loading

0 comments on commit 32900a0

Please sign in to comment.