feat: update depot version to 0.17.0 and enhance Python build/install commands
This commit is contained in:
Generated
+1
-1
@@ -418,7 +418,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2"
|
||||
|
||||
[[package]]
|
||||
name = "depot"
|
||||
version = "0.16.1"
|
||||
version = "0.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ar",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "depot"
|
||||
version = "0.16.1"
|
||||
version = "0.17.0"
|
||||
edition = "2024"
|
||||
|
||||
[lints.rust]
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
project(
|
||||
'depot',
|
||||
version: '0.16.1',
|
||||
version: '0.17.0',
|
||||
meson_version: '>=0.60.0',
|
||||
default_options: ['buildtype=release'],
|
||||
)
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ mod custom;
|
||||
mod makefile;
|
||||
mod meson;
|
||||
mod perl;
|
||||
mod python;
|
||||
pub(crate) mod python;
|
||||
mod rust;
|
||||
pub mod state;
|
||||
|
||||
|
||||
+38
-19
@@ -62,19 +62,7 @@ pub fn build(
|
||||
fs::create_dir_all(&dist_dir)
|
||||
.with_context(|| format!("Failed to create dist dir: {}", dist_dir.display()))?;
|
||||
|
||||
match detect_frontend(&actual_src)? {
|
||||
BuildFrontend::Pep517(cfg) => {
|
||||
build_wheel_pep517(&actual_src, &dist_dir, &env_vars, &cfg, &config_settings)?
|
||||
}
|
||||
BuildFrontend::LegacySetupPy => {
|
||||
if !config_settings.is_empty() {
|
||||
bail!(
|
||||
"build.flags.config_setting is only supported for PEP 517 builds (pyproject.toml)"
|
||||
);
|
||||
}
|
||||
build_wheel_setup_py(&actual_src, &dist_dir, &env_vars)?;
|
||||
}
|
||||
}
|
||||
build_wheels(&actual_src, &dist_dir, &env_vars, &config_settings)?;
|
||||
|
||||
hooks::run_post_compile_commands(spec, &actual_src, destdir)?;
|
||||
state.mark_done(BuildStep::PostCompileDone)?;
|
||||
@@ -84,11 +72,7 @@ pub fn build(
|
||||
|
||||
if !state.is_done(BuildStep::PostInstallDone) {
|
||||
let wheels = collect_wheels(&dist_dir)?;
|
||||
let py_version = detect_python_major_minor(&env_vars)?;
|
||||
let prefix_rel = normalized_prefix(&flags.prefix)?;
|
||||
for wheel in wheels {
|
||||
install_wheel(&wheel, destdir, &prefix_rel, &py_version)?;
|
||||
}
|
||||
install_wheels(&wheels, destdir, &flags.prefix, &env_vars)?;
|
||||
|
||||
hooks::run_post_install_commands(spec, &actual_src, destdir)?;
|
||||
state.mark_done(BuildStep::PostInstallDone)?;
|
||||
@@ -356,7 +340,28 @@ fn build_wheel_pep517(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn collect_wheels(dist_dir: &Path) -> Result<Vec<PathBuf>> {
|
||||
pub(crate) fn build_wheels(
|
||||
src_dir: &Path,
|
||||
dist_dir: &Path,
|
||||
env_vars: &[(String, String)],
|
||||
config_settings: &[String],
|
||||
) -> Result<()> {
|
||||
match detect_frontend(src_dir)? {
|
||||
BuildFrontend::Pep517(cfg) => {
|
||||
build_wheel_pep517(src_dir, dist_dir, env_vars, &cfg, config_settings)
|
||||
}
|
||||
BuildFrontend::LegacySetupPy => {
|
||||
if !config_settings.is_empty() {
|
||||
bail!(
|
||||
"build.flags.config_setting is only supported for PEP 517 builds (pyproject.toml)"
|
||||
);
|
||||
}
|
||||
build_wheel_setup_py(src_dir, dist_dir, env_vars)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn collect_wheels(dist_dir: &Path) -> Result<Vec<PathBuf>> {
|
||||
let mut wheels = Vec::new();
|
||||
for entry in fs::read_dir(dist_dir).with_context(|| {
|
||||
format!(
|
||||
@@ -513,6 +518,20 @@ fn install_wheel(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn install_wheels(
|
||||
wheel_paths: &[PathBuf],
|
||||
destdir: &Path,
|
||||
prefix: &str,
|
||||
env_vars: &[(String, String)],
|
||||
) -> Result<()> {
|
||||
let py_version = detect_python_major_minor(env_vars)?;
|
||||
let prefix_rel = normalized_prefix(prefix)?;
|
||||
for wheel in wheel_paths {
|
||||
install_wheel(wheel, destdir, &prefix_rel, &py_version)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_top_level_dist_info_entry_points(rel: &Path) -> bool {
|
||||
let parts = match path_parts(rel, "wheel entry") {
|
||||
Ok(p) => p,
|
||||
|
||||
+27
@@ -152,6 +152,33 @@ pub enum Commands {
|
||||
#[arg(short, long)]
|
||||
output: Option<PathBuf>,
|
||||
},
|
||||
#[command(hide = true)]
|
||||
Internal {
|
||||
#[command(subcommand)]
|
||||
command: InternalCommands,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum InternalCommands {
|
||||
#[command(hide = true)]
|
||||
PythonBuild {
|
||||
#[arg(long, default_value = ".")]
|
||||
src_dir: PathBuf,
|
||||
#[arg(long, default_value = "dist")]
|
||||
dist_dir: PathBuf,
|
||||
#[arg(long = "config-setting")]
|
||||
config_settings: Vec<String>,
|
||||
},
|
||||
#[command(hide = true)]
|
||||
PythonInstall {
|
||||
#[arg(long, default_value = "dist")]
|
||||
dist_dir: PathBuf,
|
||||
#[arg(long = "wheel", value_name = "FILE")]
|
||||
wheels: Vec<PathBuf>,
|
||||
#[arg(long, default_value = "/usr")]
|
||||
prefix: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
|
||||
+41
-1
@@ -1,4 +1,4 @@
|
||||
use crate::cli::{Cli, Commands, RepoCommands, RepoKindArg};
|
||||
use crate::cli::{Cli, Commands, InternalCommands, RepoCommands, RepoKindArg};
|
||||
use crate::{
|
||||
builder, cli_assets, config, cross, db, deps, index, install, locking, package, planner,
|
||||
signing, source, staging, ui,
|
||||
@@ -260,6 +260,43 @@ fn parse_keep_list(metadata: &toml::Value) -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn current_process_env_vars() -> Vec<(String, String)> {
|
||||
std::env::vars().collect()
|
||||
}
|
||||
|
||||
fn run_internal_command(command: InternalCommands) -> Result<()> {
|
||||
match command {
|
||||
InternalCommands::PythonBuild {
|
||||
src_dir,
|
||||
dist_dir,
|
||||
config_settings,
|
||||
} => {
|
||||
let env_vars = current_process_env_vars();
|
||||
crate::builder::python::build_wheels(&src_dir, &dist_dir, &env_vars, &config_settings)
|
||||
}
|
||||
InternalCommands::PythonInstall {
|
||||
dist_dir,
|
||||
wheels,
|
||||
prefix,
|
||||
} => {
|
||||
let env_vars = current_process_env_vars();
|
||||
let wheel_paths = if wheels.is_empty() {
|
||||
crate::builder::python::collect_wheels(&dist_dir)?
|
||||
} else {
|
||||
wheels
|
||||
};
|
||||
let destdir = std::env::var("DESTDIR")
|
||||
.context("DESTDIR must be set for internal python-install")?;
|
||||
crate::builder::python::install_wheels(
|
||||
&wheel_paths,
|
||||
Path::new(&destdir),
|
||||
&prefix,
|
||||
&env_vars,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn package_spec_from_archive_metadata(metadata: &toml::Value) -> package::PackageSpec {
|
||||
let mut spec = package::PackageSpec {
|
||||
package: package::PackageInfo {
|
||||
@@ -4465,6 +4502,9 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
output_path.display()
|
||||
));
|
||||
}
|
||||
Commands::Internal { command } => {
|
||||
run_internal_command(command)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+2
-2
@@ -15,12 +15,12 @@ pub fn is_root() -> bool {
|
||||
pub fn wrap_install_command(program: &str, destdir: &Path) -> Command {
|
||||
let script_path = shell_script_path(program);
|
||||
if is_root() {
|
||||
build_command(program, script_path.as_deref())
|
||||
build_command(program, script_path)
|
||||
} else {
|
||||
// Use system fakeroot command which handles LD_PRELOAD internally
|
||||
let mut cmd = Command::new("fakeroot");
|
||||
cmd.arg("--");
|
||||
if let Some(script_path) = script_path.as_deref() {
|
||||
if let Some(script_path) = script_path {
|
||||
cmd.arg("sh");
|
||||
cmd.arg(script_path);
|
||||
} else {
|
||||
|
||||
+124
-3
@@ -12,14 +12,20 @@ pub const INTERNAL_DEPOT_DIR: &str = ".depot";
|
||||
pub const INTERNAL_OUTPUTS_DIR: &str = ".depot/outputs";
|
||||
const DEPOT_HAUL_HELPER_ENV: &str = "DEPOT_HAUL_HELPER";
|
||||
const DEPOT_SUBDESTDIR_HELPER_ENV: &str = "DEPOT_SUBDESTDIR_HELPER";
|
||||
const DEPOT_PYTHON_BUILD_HELPER_ENV: &str = "DEPOT_PYTHON_BUILD_HELPER";
|
||||
const DEPOT_PYTHON_INSTALL_HELPER_ENV: &str = "DEPOT_PYTHON_INSTALL_HELPER";
|
||||
const DEPOT_EXECUTABLE_ENV: &str = "DEPOT_EXECUTABLE";
|
||||
|
||||
/// Ephemeral helper command directory to prepend to PATH while running scripts.
|
||||
pub struct ShellHelpers {
|
||||
_tempdir: TempDir,
|
||||
path_value: String,
|
||||
outputs_dir: PathBuf,
|
||||
depot_executable: PathBuf,
|
||||
haul_path: PathBuf,
|
||||
subdestdir_path: PathBuf,
|
||||
python_build_path: PathBuf,
|
||||
python_install_path: PathBuf,
|
||||
}
|
||||
|
||||
impl ShellHelpers {
|
||||
@@ -37,6 +43,8 @@ impl ShellHelpers {
|
||||
let bin_dir = tempdir.path().join("bin");
|
||||
fs::create_dir_all(&bin_dir)
|
||||
.with_context(|| format!("Failed to create helper bin dir: {}", bin_dir.display()))?;
|
||||
let depot_executable = std::env::current_exe()
|
||||
.context("Failed to locate depot executable for shell helpers")?;
|
||||
|
||||
let haul_path = bin_dir.join("haul");
|
||||
fs::write(&haul_path, HAUL_SCRIPT).with_context(|| {
|
||||
@@ -75,14 +83,57 @@ impl ShellHelpers {
|
||||
})?;
|
||||
}
|
||||
|
||||
let python_build_path = bin_dir.join("python_build");
|
||||
fs::write(&python_build_path, PYTHON_BUILD_SCRIPT).with_context(|| {
|
||||
format!(
|
||||
"Failed to write shell helper command: {}",
|
||||
python_build_path.display()
|
||||
)
|
||||
})?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mut perms = fs::metadata(&python_build_path)
|
||||
.with_context(|| format!("Failed to stat helper: {}", python_build_path.display()))?
|
||||
.permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(&python_build_path, perms).with_context(|| {
|
||||
format!("Failed to chmod helper: {}", python_build_path.display())
|
||||
})?;
|
||||
}
|
||||
|
||||
let python_install_path = bin_dir.join("python_install");
|
||||
fs::write(&python_install_path, PYTHON_INSTALL_SCRIPT).with_context(|| {
|
||||
format!(
|
||||
"Failed to write shell helper command: {}",
|
||||
python_install_path.display()
|
||||
)
|
||||
})?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let mut perms = fs::metadata(&python_install_path)
|
||||
.with_context(|| {
|
||||
format!("Failed to stat helper: {}", python_install_path.display())
|
||||
})?
|
||||
.permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(&python_install_path, perms).with_context(|| {
|
||||
format!("Failed to chmod helper: {}", python_install_path.display())
|
||||
})?;
|
||||
}
|
||||
|
||||
let path_value = crate::runtime_env::prepend_helper_to_safe_path(&bin_dir);
|
||||
|
||||
Ok(Self {
|
||||
_tempdir: tempdir,
|
||||
path_value,
|
||||
outputs_dir: destdir.join(INTERNAL_OUTPUTS_DIR),
|
||||
depot_executable,
|
||||
haul_path,
|
||||
subdestdir_path,
|
||||
python_build_path,
|
||||
python_install_path,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -105,6 +156,21 @@ impl ShellHelpers {
|
||||
DEPOT_SUBDESTDIR_HELPER_ENV,
|
||||
self.subdestdir_path.to_string_lossy().into_owned(),
|
||||
);
|
||||
set_env_var(
|
||||
env_vars,
|
||||
DEPOT_PYTHON_BUILD_HELPER_ENV,
|
||||
self.python_build_path.to_string_lossy().into_owned(),
|
||||
);
|
||||
set_env_var(
|
||||
env_vars,
|
||||
DEPOT_PYTHON_INSTALL_HELPER_ENV,
|
||||
self.python_install_path.to_string_lossy().into_owned(),
|
||||
);
|
||||
set_env_var(
|
||||
env_vars,
|
||||
DEPOT_EXECUTABLE_ENV,
|
||||
self.depot_executable.to_string_lossy().into_owned(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Apply helper-related variables directly to a `std::process::Command`.
|
||||
@@ -113,7 +179,10 @@ impl ShellHelpers {
|
||||
.env("DEPOT_OUTPUTS_DIR", &self.outputs_dir)
|
||||
.env("DEPOT_INTERNAL_DIR", INTERNAL_DEPOT_DIR)
|
||||
.env(DEPOT_HAUL_HELPER_ENV, &self.haul_path)
|
||||
.env(DEPOT_SUBDESTDIR_HELPER_ENV, &self.subdestdir_path);
|
||||
.env(DEPOT_SUBDESTDIR_HELPER_ENV, &self.subdestdir_path)
|
||||
.env(DEPOT_PYTHON_BUILD_HELPER_ENV, &self.python_build_path)
|
||||
.env(DEPOT_PYTHON_INSTALL_HELPER_ENV, &self.python_install_path)
|
||||
.env(DEPOT_EXECUTABLE_ENV, &self.depot_executable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +190,7 @@ impl ShellHelpers {
|
||||
/// through `/bin/sh`, avoiding direct execution from mounts that may be `noexec`.
|
||||
pub fn wrap_shell_command(command: &str) -> String {
|
||||
format!(
|
||||
"haul() {{ /bin/sh \"${{{DEPOT_HAUL_HELPER_ENV}:?}}\" \"$@\"; }}\nsubdestdir() {{ /bin/sh \"${{{DEPOT_SUBDESTDIR_HELPER_ENV}:?}}\" \"$@\"; }}\n{command}"
|
||||
"haul() {{ /bin/sh \"${{{DEPOT_HAUL_HELPER_ENV}:?}}\" \"$@\"; }}\nsubdestdir() {{ /bin/sh \"${{{DEPOT_SUBDESTDIR_HELPER_ENV}:?}}\" \"$@\"; }}\npython_build() {{ /bin/sh \"${{{DEPOT_PYTHON_BUILD_HELPER_ENV}:?}}\" \"$@\"; }}\npython_install() {{ /bin/sh \"${{{DEPOT_PYTHON_INSTALL_HELPER_ENV}:?}}\" \"$@\"; }}\n{command}"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -273,9 +342,36 @@ mkdir -p "$path"
|
||||
printf '%s\n' "$path"
|
||||
"#;
|
||||
|
||||
const PYTHON_BUILD_SCRIPT: &str = r#"#!/bin/sh
|
||||
set -eu
|
||||
|
||||
fail() {
|
||||
echo "python_build: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "${DEPOT_EXECUTABLE:-}" != "" ] || fail "DEPOT_EXECUTABLE is not set"
|
||||
|
||||
exec "$DEPOT_EXECUTABLE" internal python-build "$@"
|
||||
"#;
|
||||
|
||||
const PYTHON_INSTALL_SCRIPT: &str = r#"#!/bin/sh
|
||||
set -eu
|
||||
|
||||
fail() {
|
||||
echo "python_install: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "${DEPOT_EXECUTABLE:-}" != "" ] || fail "DEPOT_EXECUTABLE is not set"
|
||||
[ "${DESTDIR:-}" != "" ] || fail "DESTDIR is not set"
|
||||
|
||||
exec "$DEPOT_EXECUTABLE" internal python-install "$@"
|
||||
"#;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{INTERNAL_DEPOT_DIR, ShellHelpers, shell_ident_suffix};
|
||||
use super::{INTERNAL_DEPOT_DIR, ShellHelpers, shell_ident_suffix, wrap_shell_command};
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[test]
|
||||
@@ -307,4 +403,29 @@ mod tests {
|
||||
.into_owned();
|
||||
assert!(path.starts_with(&helper_prefix));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_helpers_export_python_helper_paths() {
|
||||
let destdir = tempdir().unwrap();
|
||||
let helpers = ShellHelpers::new(destdir.path()).unwrap();
|
||||
let mut envs = Vec::new();
|
||||
helpers.apply_to_env_vars(&mut envs);
|
||||
|
||||
assert!(
|
||||
envs.iter()
|
||||
.any(|(key, _)| key == "DEPOT_PYTHON_BUILD_HELPER")
|
||||
);
|
||||
assert!(
|
||||
envs.iter()
|
||||
.any(|(key, _)| key == "DEPOT_PYTHON_INSTALL_HELPER")
|
||||
);
|
||||
assert!(envs.iter().any(|(key, _)| key == "DEPOT_EXECUTABLE"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrap_shell_command_exposes_python_helpers() {
|
||||
let wrapped = wrap_shell_command("python_build\npython_install");
|
||||
assert!(wrapped.contains("python_build()"));
|
||||
assert!(wrapped.contains("python_install()"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user