Skip to content

Commit 2ed5720

Browse files
committed
Add uv build
1 parent 83467f0 commit 2ed5720

File tree

14 files changed

+1110
-109
lines changed

14 files changed

+1110
-109
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uv-build/src/lib.rs

Lines changed: 149 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ static DEFAULT_BACKEND: LazyLock<Pep517Backend> = LazyLock::new(|| Pep517Backend
7979
pub enum Error {
8080
#[error(transparent)]
8181
Io(#[from] io::Error),
82-
#[error("Invalid source distribution: {0}")]
83-
InvalidSourceDist(String),
82+
#[error("{} does not appear to be a Python project, as neither `pyproject.toml` nor `setup.py` is present in the directory", _0.simplified_display())]
83+
InvalidSourceDist(PathBuf),
8484
#[error("Invalid `pyproject.toml`")]
8585
InvalidPyprojectToml(#[from] toml::de::Error),
8686
#[error("Editable installs with setup.py legacy builds are unsupported, please specify a build backend in pyproject.toml")]
@@ -595,8 +595,7 @@ impl SourceBuild {
595595
// We require either a `pyproject.toml` or a `setup.py` file at the top level.
596596
if !source_tree.join("setup.py").is_file() {
597597
return Err(Box::new(Error::InvalidSourceDist(
598-
"The archive contains neither a `pyproject.toml` nor a `setup.py` file at the top level"
599-
.to_string(),
598+
source_tree.to_path_buf(),
600599
)));
601600
}
602601

@@ -723,7 +722,7 @@ impl SourceBuild {
723722
#[instrument(skip_all, fields(version_id = self.version_id))]
724723
pub async fn build_wheel(&self, wheel_dir: &Path) -> Result<String, Error> {
725724
// The build scripts run with the extracted root as cwd, so they need the absolute path.
726-
let wheel_dir = fs::canonicalize(wheel_dir)?;
725+
let wheel_dir = std::path::absolute(wheel_dir)?;
727726

728727
// Prevent clashes from two uv processes building wheels in parallel.
729728
let tmp_dir = tempdir_in(&wheel_dir)?;
@@ -737,86 +736,159 @@ impl SourceBuild {
737736
Ok(filename)
738737
}
739738

739+
/// Perform a PEP 517 build for a wheel or source distribution (sdist).
740740
async fn pep517_build(
741741
&self,
742742
wheel_dir: &Path,
743743
pep517_backend: &Pep517Backend,
744744
) -> Result<String, Error> {
745-
let metadata_directory = self
746-
.metadata_directory
747-
.as_deref()
748-
.map_or("None".to_string(), |path| {
749-
format!(r#""{}""#, path.escape_for_python())
750-
});
751-
752-
// Write the hook output to a file so that we can read it back reliably.
753-
let outfile = self
754-
.temp_dir
755-
.path()
756-
.join(format!("build_{}.txt", self.build_kind));
757-
758-
debug!(
759-
r#"Calling `{}.build_{}("{}", {}, {})`"#,
760-
pep517_backend.backend,
761-
self.build_kind,
762-
wheel_dir.escape_for_python(),
763-
self.config_settings.escape_for_python(),
764-
metadata_directory,
765-
);
766-
let script = formatdoc! {
767-
r#"
768-
{}
745+
match self.build_kind {
746+
BuildKind::Sdist => {
747+
// Write the hook output to a file so that we can read it back reliably.
748+
let outfile = self
749+
.temp_dir
750+
.path()
751+
.join(format!("build_{}.txt", self.build_kind));
752+
753+
debug!(
754+
r#"Calling `{}.build_{}("{}", {})`"#,
755+
pep517_backend.backend,
756+
self.build_kind,
757+
wheel_dir.escape_for_python(),
758+
self.config_settings.escape_for_python(),
759+
);
760+
let script = formatdoc! {
761+
r#"
762+
{}
763+
764+
sdist_filename = backend.build_{}("{}", {})
765+
with open("{}", "w") as fp:
766+
fp.write(sdist_filename)
767+
"#,
768+
pep517_backend.backend_import(),
769+
self.build_kind,
770+
wheel_dir.escape_for_python(),
771+
self.config_settings.escape_for_python(),
772+
outfile.escape_for_python()
773+
};
774+
let span = info_span!(
775+
"run_python_script",
776+
script=format!("build_{}", self.build_kind),
777+
python_version = %self.venv.interpreter().python_version()
778+
);
779+
let output = self
780+
.runner
781+
.run_script(
782+
&self.venv,
783+
&script,
784+
&self.source_tree,
785+
&self.environment_variables,
786+
&self.modified_path,
787+
)
788+
.instrument(span)
789+
.await?;
790+
if !output.status.success() {
791+
return Err(Error::from_command_output(
792+
format!(
793+
"Build backend failed to build sdist through `build_{}()`",
794+
self.build_kind
795+
),
796+
&output,
797+
&self.version_id,
798+
));
799+
}
769800

770-
wheel_filename = backend.build_{}("{}", {}, {})
771-
with open("{}", "w") as fp:
772-
fp.write(wheel_filename)
773-
"#,
774-
pep517_backend.backend_import(),
775-
self.build_kind,
776-
wheel_dir.escape_for_python(),
777-
self.config_settings.escape_for_python(),
778-
metadata_directory,
779-
outfile.escape_for_python()
780-
};
781-
let span = info_span!(
782-
"run_python_script",
783-
script=format!("build_{}", self.build_kind),
784-
python_version = %self.venv.interpreter().python_version()
785-
);
786-
let output = self
787-
.runner
788-
.run_script(
789-
&self.venv,
790-
&script,
791-
&self.source_tree,
792-
&self.environment_variables,
793-
&self.modified_path,
794-
)
795-
.instrument(span)
796-
.await?;
797-
if !output.status.success() {
798-
return Err(Error::from_command_output(
799-
format!(
800-
"Build backend failed to build wheel through `build_{}()`",
801-
self.build_kind
802-
),
803-
&output,
804-
&self.version_id,
805-
));
806-
}
801+
let distribution_filename = fs::read_to_string(&outfile)?;
802+
if !wheel_dir.join(&distribution_filename).is_file() {
803+
return Err(Error::from_command_output(
804+
format!(
805+
"Build backend failed to produce sdist through `build_{}()`: `{distribution_filename}` not found",
806+
self.build_kind
807+
),
808+
&output,
809+
&self.version_id,
810+
));
811+
}
812+
Ok(distribution_filename)
813+
}
814+
BuildKind::Wheel | BuildKind::Editable => {
815+
let metadata_directory = self
816+
.metadata_directory
817+
.as_deref()
818+
.map_or("None".to_string(), |path| {
819+
format!(r#""{}""#, path.escape_for_python())
820+
});
821+
822+
// Write the hook output to a file so that we can read it back reliably.
823+
let outfile = self
824+
.temp_dir
825+
.path()
826+
.join(format!("build_{}.txt", self.build_kind));
827+
828+
debug!(
829+
r#"Calling `{}.build_{}("{}", {}, {})`"#,
830+
pep517_backend.backend,
831+
self.build_kind,
832+
wheel_dir.escape_for_python(),
833+
self.config_settings.escape_for_python(),
834+
metadata_directory,
835+
);
836+
let script = formatdoc! {
837+
r#"
838+
{}
839+
840+
wheel_filename = backend.build_{}("{}", {}, {})
841+
with open("{}", "w") as fp:
842+
fp.write(wheel_filename)
843+
"#,
844+
pep517_backend.backend_import(),
845+
self.build_kind,
846+
wheel_dir.escape_for_python(),
847+
self.config_settings.escape_for_python(),
848+
metadata_directory,
849+
outfile.escape_for_python()
850+
};
851+
let span = info_span!(
852+
"run_python_script",
853+
script=format!("build_{}", self.build_kind),
854+
python_version = %self.venv.interpreter().python_version()
855+
);
856+
let output = self
857+
.runner
858+
.run_script(
859+
&self.venv,
860+
&script,
861+
&self.source_tree,
862+
&self.environment_variables,
863+
&self.modified_path,
864+
)
865+
.instrument(span)
866+
.await?;
867+
if !output.status.success() {
868+
return Err(Error::from_command_output(
869+
format!(
870+
"Build backend failed to build wheel through `build_{}()`",
871+
self.build_kind
872+
),
873+
&output,
874+
&self.version_id,
875+
));
876+
}
807877

808-
let distribution_filename = fs::read_to_string(&outfile)?;
809-
if !wheel_dir.join(&distribution_filename).is_file() {
810-
return Err(Error::from_command_output(
811-
format!(
812-
"Build backend failed to produce wheel through `build_{}()`: `{distribution_filename}` not found",
813-
self.build_kind
814-
),
815-
&output,
816-
&self.version_id,
817-
));
878+
let distribution_filename = fs::read_to_string(&outfile)?;
879+
if !wheel_dir.join(&distribution_filename).is_file() {
880+
return Err(Error::from_command_output(
881+
format!(
882+
"Build backend failed to produce through `build_{}()`: `{distribution_filename}` not found",
883+
self.build_kind
884+
),
885+
&output,
886+
&self.version_id,
887+
));
888+
}
889+
Ok(distribution_filename)
890+
}
818891
}
819-
Ok(distribution_filename)
820892
}
821893
}
822894

0 commit comments

Comments
 (0)