Skip to content

Commit 12fa149

Browse files
authored
feat: out-of-tree satisfiability fixed (#4872)
1 parent d243b1b commit 12fa149

File tree

6 files changed

+158
-7
lines changed

6 files changed

+158
-7
lines changed

crates/pixi_core/src/lock_file/satisfiability/mod.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,24 +1497,60 @@ pub(crate) async fn verify_package_platform_satisfiability(
14971497
.iter()
14981498
.filter_map(PixiRecord::as_source)
14991499
{
1500-
let Some(path_record) = source_record.manifest_source.as_path() else {
1500+
let Some(locked_input_hash) = &source_record.input_hash else {
15011501
continue;
15021502
};
15031503

1504-
let Some(locked_input_hash) = &source_record.input_hash else {
1505-
continue;
1504+
// Determine the source directory to hash
1505+
// If build_source is specified, it points to where the actual source files are located
1506+
// and should be resolved relative to the manifest_source location
1507+
// Otherwise, use manifest_source directly
1508+
let source_dir = if let Some(build_source) = &source_record.build_source {
1509+
// Convert to mutable source spec (only path-based sources are supported)
1510+
let Ok(mutable_source) = build_source.clone().into_mutable() else {
1511+
continue;
1512+
};
1513+
let Some(build_path_record) = mutable_source.as_path() else {
1514+
continue;
1515+
};
1516+
1517+
// Get the manifest directory first
1518+
let Some(manifest_path_record) = source_record.manifest_source.as_path() else {
1519+
continue;
1520+
};
1521+
let manifest_dir = manifest_path_record.resolve(project_root);
1522+
1523+
// Resolve build_source relative to the manifest directory
1524+
build_path_record.resolve(&manifest_dir)
1525+
} else {
1526+
let Some(path_record) = source_record.manifest_source.as_path() else {
1527+
continue;
1528+
};
1529+
path_record.resolve(project_root)
15061530
};
15071531

1508-
let source_dir = path_record.resolve(project_root);
15091532
let source_dir = source_dir.canonicalize().map_err(|e| {
15101533
Box::new(PlatformUnsat::FailedToCanonicalizePath(
1511-
path_record.path.as_str().into(),
1534+
source_dir.display().to_string().into(),
1535+
e,
1536+
))
1537+
})?;
1538+
1539+
// Always discover the backend from the manifest directory (where pixi.toml with build config is)
1540+
// even if we're hashing files from a different build_source directory
1541+
let Some(manifest_path_record) = source_record.manifest_source.as_path() else {
1542+
continue;
1543+
};
1544+
let manifest_dir = manifest_path_record.resolve(project_root);
1545+
let manifest_dir = manifest_dir.canonicalize().map_err(|e| {
1546+
Box::new(PlatformUnsat::FailedToCanonicalizePath(
1547+
manifest_path_record.path.as_str().into(),
15121548
e,
15131549
))
15141550
})?;
15151551

15161552
let discovered_backend = DiscoveredBackend::discover(
1517-
&source_dir,
1553+
&manifest_dir,
15181554
&environment.channel_config(),
15191555
&EnabledProtocols::default(),
15201556
)
@@ -1542,8 +1578,13 @@ pub(crate) async fn verify_package_platform_satisfiability(
15421578
.map_err(Box::new)?;
15431579

15441580
if input_hash.hash != locked_input_hash.hash {
1581+
let manifest_path = source_record
1582+
.manifest_source
1583+
.as_path()
1584+
.map(|p| p.path.to_string())
1585+
.unwrap_or_else(|| source_record.manifest_source.to_string());
15451586
return Err(Box::new(PlatformUnsat::InputHashMismatch(
1546-
path_record.path.to_string(),
1587+
manifest_path,
15471588
format!("{:x}", input_hash.hash),
15481589
format!("{:x}", locked_input_hash.hash),
15491590
)));
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "out-of-tree-package"
3+
version = "0.1.0"
4+
5+
[package.build]
6+
backend = { name = "pixi-build-cmake", version = "0.3.*" }
7+
# Point to source files in a different directory (out-of-tree build)
8+
source = { path = "../source-files" }

tests/data/satisfiability/out-of-tree-source/pixi.lock

Lines changed: 81 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[workspace]
2+
channels = [
3+
"https://prefix.dev/pixi-build-backends",
4+
"https://prefix.dev/conda-forge",
5+
]
6+
platforms = ["linux-64"]
7+
preview = ["pixi-build"]
8+
9+
[dependencies]
10+
out-of-tree-package = { path = "build-config" }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(out-of-tree-package)
3+
4+
# Simple test project for out-of-tree builds
5+
add_executable(test_app main.cpp)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <iostream>
2+
3+
int main() {
4+
std::cout << "Hello from out-of-tree build!" << std::endl;
5+
return 0;
6+
}

0 commit comments

Comments
 (0)