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

Commit d6b9aaf

Browse files
committed
Separate build data structs from serializations
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 fc6344a commit d6b9aaf

8 files changed

Lines changed: 813 additions & 397 deletions

File tree

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)