Skip to content
This repository was archived by the owner on Jan 27, 2026. It is now read-only.

Commit 7872392

Browse files
authored
Separate build data structs from serializations (#332)
We have three versions of the build format (v1-3), where we converted prior versions to the latest and used the latest as the actual configuration. The downside of this approach is that every time we introduce a new version, we have to move all utility functions, etc. to the latest. This change decouples the configuration that is used to generate the build files from the concrete serializations. The core data structures move to the top-level module and v1-v3.rs now only contain plain data structures to (de)serialize with serde.
1 parent fbe7cd0 commit 7872392

File tree

8 files changed

+813
-397
lines changed

8 files changed

+813
-397
lines changed

build2cmake/src/config/common.rs

Lines changed: 0 additions & 24 deletions
This file was deleted.

build2cmake/src/config/compat.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use eyre::Result;
2+
use serde::Deserialize;
3+
use serde_value::Value;
4+
5+
use super::{v1, v2, v3, Build};
6+
7+
#[derive(Debug)]
8+
pub enum BuildCompat {
9+
V1(v1::Build),
10+
V2(v2::Build),
11+
V3(v3::Build),
12+
}
13+
14+
impl<'de> Deserialize<'de> for BuildCompat {
15+
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
16+
where
17+
D: serde::Deserializer<'de>,
18+
{
19+
let value = Value::deserialize(deserializer)?;
20+
21+
v1::Build::deserialize(value.clone())
22+
.map(BuildCompat::V1)
23+
.or_else(|_| v2::Build::deserialize(value.clone()).map(BuildCompat::V2))
24+
.or_else(|_| v3::Build::deserialize(value.clone()).map(BuildCompat::V3))
25+
.map_err(serde::de::Error::custom)
26+
}
27+
}
28+
29+
impl TryFrom<BuildCompat> for Build {
30+
type Error = eyre::Error;
31+
32+
fn try_from(compat: BuildCompat) -> Result<Self> {
33+
match compat {
34+
BuildCompat::V1(v1_build) => v1_build.try_into(),
35+
BuildCompat::V2(v2_build) => v2_build.try_into(),
36+
BuildCompat::V3(v3_build) => Ok(v3_build.into()),
37+
}
38+
}
39+
}

build2cmake/src/config/deps.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use std::{collections::HashMap, sync::LazyLock};
2+
3+
use eyre::Result;
4+
use serde::{Deserialize, Serialize};
5+
use thiserror::Error;
6+
7+
use super::Backend;
8+
9+
pub static PYTHON_DEPENDENCIES: LazyLock<PythonDependencies> =
10+
LazyLock::new(|| serde_json::from_str(include_str!("../python_dependencies.json")).unwrap());
11+
12+
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
13+
#[non_exhaustive]
14+
#[serde(rename_all = "lowercase")]
15+
pub enum Dependency {
16+
#[serde(rename = "cutlass_2_10")]
17+
Cutlass2_10,
18+
#[serde(rename = "cutlass_3_5")]
19+
Cutlass3_5,
20+
#[serde(rename = "cutlass_3_6")]
21+
Cutlass3_6,
22+
#[serde(rename = "cutlass_3_8")]
23+
Cutlass3_8,
24+
#[serde(rename = "cutlass_3_9")]
25+
Cutlass3_9,
26+
#[serde(rename = "cutlass_4_0")]
27+
Cutlass4_0,
28+
#[serde(rename = "cutlass_sycl")]
29+
CutlassSycl,
30+
#[serde(rename = "metal-cpp")]
31+
MetalCpp,
32+
Torch,
33+
}
34+
35+
#[derive(Debug, Deserialize, Serialize)]
36+
#[serde(deny_unknown_fields)]
37+
pub struct PythonDependencies {
38+
general: HashMap<String, PythonDependency>,
39+
backends: HashMap<Backend, HashMap<String, PythonDependency>>,
40+
}
41+
42+
impl PythonDependencies {
43+
pub fn get_dependency(&self, dependency: &str) -> Result<&[String], DependencyError> {
44+
match self.general.get(dependency) {
45+
None => Err(DependencyError::GeneralDependency {
46+
dependency: dependency.to_string(),
47+
}),
48+
Some(dep) => Ok(&dep.python),
49+
}
50+
}
51+
52+
pub fn get_backend_dependency(
53+
&self,
54+
backend: Backend,
55+
dependency: &str,
56+
) -> Result<&[String], DependencyError> {
57+
let backend_deps = match self.backends.get(&backend) {
58+
None => {
59+
return Err(DependencyError::Backend {
60+
backend: backend.to_string(),
61+
})
62+
}
63+
Some(backend_deps) => backend_deps,
64+
};
65+
match backend_deps.get(dependency) {
66+
None => Err(DependencyError::Dependency {
67+
backend: backend.to_string(),
68+
dependency: dependency.to_string(),
69+
}),
70+
Some(dep) => Ok(&dep.python),
71+
}
72+
}
73+
}
74+
75+
#[derive(Debug, Deserialize, Serialize)]
76+
struct PythonDependency {
77+
nix: Vec<String>,
78+
python: Vec<String>,
79+
}
80+
81+
#[derive(Debug, Error)]
82+
pub enum DependencyError {
83+
#[error("No dependencies are defined for backend: {backend:?}")]
84+
Backend { backend: String },
85+
#[error("Unknown dependency `{dependency:?}` for backend `{backend:?}`")]
86+
Dependency { backend: String, dependency: String },
87+
#[error("Unknown dependency: `{dependency:?}`")]
88+
GeneralDependency { dependency: String },
89+
}

0 commit comments

Comments
 (0)