mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Implement uv build
(#6895)
## Summary This PR exposes uv's PEP 517 implementation via a `uv build` frontend, such that you can use `uv build` to build source and binary distributions (i.e., wheels and sdists) from a given directory. There are some TODOs that I'll tackle in separate PRs: - [x] Support building a wheel from a source distribution (rather than from source) (#6898) - [x] Stream the build output (#6912) Closes https://github.com/astral-sh/uv/issues/1510 Closes https://github.com/astral-sh/uv/issues/1663.
This commit is contained in:
parent
a3a1bfd5ec
commit
df84d25a7e
16 changed files with 1028 additions and 168 deletions
|
@ -18,23 +18,16 @@ workspace = true
|
|||
[dependencies]
|
||||
distribution-filename = { workspace = true }
|
||||
distribution-types = { workspace = true }
|
||||
install-wheel-rs = { workspace = true }
|
||||
pep508_rs = { workspace = true }
|
||||
pypi-types = { workspace = true }
|
||||
uv-build = { workspace = true }
|
||||
uv-cache = { workspace = true, features = ["clap"] }
|
||||
uv-cli = { workspace = true }
|
||||
uv-client = { workspace = true }
|
||||
uv-configuration = { workspace = true }
|
||||
uv-dispatch = { workspace = true }
|
||||
uv-git = { workspace = true }
|
||||
uv-installer = { workspace = true }
|
||||
uv-macros = { workspace = true }
|
||||
uv-options-metadata = { workspace = true }
|
||||
uv-python = { workspace = true }
|
||||
uv-resolver = { workspace = true }
|
||||
uv-settings = { workspace = true, features = ["schemars"] }
|
||||
uv-types = { workspace = true }
|
||||
uv-workspace = { workspace = true, features = ["schemars"] }
|
||||
|
||||
# Any dependencies that are exclusively used in `uv-dev` should be listed as non-workspace
|
||||
|
@ -44,12 +37,11 @@ anyhow = { workspace = true }
|
|||
clap = { workspace = true, features = ["derive", "wrap_help"] }
|
||||
fs-err = { workspace = true, features = ["tokio"] }
|
||||
itertools = { workspace = true }
|
||||
markdown = "0.3.0"
|
||||
markdown = { version = "0.3.0" }
|
||||
owo-colors = { workspace = true }
|
||||
poloto = { version = "19.1.2", optional = true }
|
||||
pretty_assertions = { version = "1.4.0" }
|
||||
resvg = { version = "0.29.0", optional = true }
|
||||
rustc-hash = { workspace = true }
|
||||
schemars = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
use fs_err as fs;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use distribution_types::IndexLocations;
|
||||
use uv_build::{SourceBuild, SourceBuildContext};
|
||||
use uv_cache::{Cache, CacheArgs};
|
||||
use uv_client::RegistryClientBuilder;
|
||||
use uv_configuration::{
|
||||
BuildKind, BuildOptions, Concurrency, ConfigSettings, IndexStrategy, SourceStrategy,
|
||||
};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
use uv_git::GitResolver;
|
||||
use uv_python::{EnvironmentPreference, PythonEnvironment, PythonRequest};
|
||||
use uv_resolver::{FlatIndex, InMemoryIndex};
|
||||
use uv_types::{BuildIsolation, InFlight};
|
||||
|
||||
#[derive(Parser)]
|
||||
pub(crate) struct BuildArgs {
|
||||
/// Base python in a way that can be found with `which`
|
||||
/// TODO(konstin): Also use proper python parsing here
|
||||
#[clap(short, long)]
|
||||
python: Option<PathBuf>,
|
||||
/// Directory to story the built wheel in
|
||||
#[clap(short, long)]
|
||||
wheels: Option<PathBuf>,
|
||||
/// The source distribution to build, as a directory.
|
||||
sdist: PathBuf,
|
||||
/// The subdirectory to build within the source distribution.
|
||||
subdirectory: Option<PathBuf>,
|
||||
/// You can edit the python sources of an editable install and the changes will be used without
|
||||
/// the need to reinstall it.
|
||||
#[clap(short, long)]
|
||||
editable: bool,
|
||||
#[command(flatten)]
|
||||
cache_args: CacheArgs,
|
||||
}
|
||||
|
||||
/// Build a source distribution to a wheel
|
||||
pub(crate) async fn build(args: BuildArgs) -> Result<PathBuf> {
|
||||
let wheel_dir = if let Some(wheel_dir) = args.wheels {
|
||||
fs::create_dir_all(&wheel_dir).context("Invalid wheel directory")?;
|
||||
wheel_dir
|
||||
} else {
|
||||
env::current_dir()?
|
||||
};
|
||||
let build_kind = if args.editable {
|
||||
BuildKind::Editable
|
||||
} else {
|
||||
BuildKind::Wheel
|
||||
};
|
||||
|
||||
let cache = Cache::try_from(args.cache_args)?.init()?;
|
||||
|
||||
let client = RegistryClientBuilder::new(cache.clone()).build();
|
||||
let concurrency = Concurrency::default();
|
||||
let config_settings = ConfigSettings::default();
|
||||
let exclude_newer = None;
|
||||
let flat_index = FlatIndex::default();
|
||||
let git = GitResolver::default();
|
||||
let in_flight = InFlight::default();
|
||||
let index = InMemoryIndex::default();
|
||||
let index_urls = IndexLocations::default();
|
||||
let index_strategy = IndexStrategy::default();
|
||||
let sources = SourceStrategy::default();
|
||||
let python = PythonEnvironment::find(
|
||||
&PythonRequest::default(),
|
||||
EnvironmentPreference::OnlyVirtual,
|
||||
&cache,
|
||||
)?;
|
||||
let build_options = BuildOptions::default();
|
||||
let build_constraints = [];
|
||||
|
||||
let build_dispatch = BuildDispatch::new(
|
||||
&client,
|
||||
&cache,
|
||||
&build_constraints,
|
||||
python.interpreter(),
|
||||
&index_urls,
|
||||
&flat_index,
|
||||
&index,
|
||||
&git,
|
||||
&in_flight,
|
||||
index_strategy,
|
||||
&config_settings,
|
||||
BuildIsolation::Isolated,
|
||||
install_wheel_rs::linker::LinkMode::default(),
|
||||
&build_options,
|
||||
exclude_newer,
|
||||
sources,
|
||||
concurrency,
|
||||
);
|
||||
|
||||
let builder = SourceBuild::setup(
|
||||
&args.sdist,
|
||||
args.subdirectory.as_deref(),
|
||||
None,
|
||||
python.interpreter(),
|
||||
&build_dispatch,
|
||||
SourceBuildContext::default(),
|
||||
args.sdist.display().to_string(),
|
||||
config_settings.clone(),
|
||||
BuildIsolation::Isolated,
|
||||
build_kind,
|
||||
FxHashMap::default(),
|
||||
concurrency.builds,
|
||||
)
|
||||
.await?;
|
||||
Ok(wheel_dir.join(builder.build(&wheel_dir).await?))
|
||||
}
|
|
@ -4,7 +4,7 @@ use std::process::ExitCode;
|
|||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
|
||||
use anstream::{eprintln, println};
|
||||
use anstream::eprintln;
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use owo_colors::OwoColorize;
|
||||
|
@ -16,7 +16,6 @@ use tracing_subscriber::layer::SubscriberExt;
|
|||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::{EnvFilter, Layer};
|
||||
|
||||
use crate::build::{build, BuildArgs};
|
||||
use crate::clear_compile::ClearCompileArgs;
|
||||
use crate::compile::CompileArgs;
|
||||
use crate::generate_all::Args as GenerateAllArgs;
|
||||
|
@ -43,7 +42,6 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
|||
#[global_allocator]
|
||||
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
|
||||
|
||||
mod build;
|
||||
mod clear_compile;
|
||||
mod compile;
|
||||
mod generate_all;
|
||||
|
@ -57,8 +55,6 @@ const ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../");
|
|||
|
||||
#[derive(Parser)]
|
||||
enum Cli {
|
||||
/// Build a source distribution into a wheel.
|
||||
Build(BuildArgs),
|
||||
/// Display the metadata for a `.whl` at a given URL.
|
||||
WheelMetadata(WheelMetadataArgs),
|
||||
/// Compile all `.py` to `.pyc` files in the tree.
|
||||
|
@ -82,10 +78,6 @@ enum Cli {
|
|||
async fn run() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
match cli {
|
||||
Cli::Build(args) => {
|
||||
let target = build(args).await?;
|
||||
println!("Wheel built to {}", target.display());
|
||||
}
|
||||
Cli::WheelMetadata(args) => wheel_metadata::wheel_metadata(args).await?,
|
||||
Cli::Compile(args) => compile::compile(args).await?,
|
||||
Cli::ClearCompile(args) => clear_compile::clear_compile(&args)?,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue