Implement Perl build helper commands and integrate into CLI
- Added `run_helper_configure` and `run_helper_install` functions in `perl.rs` to handle Perl-specific build configurations and installations. - Introduced new internal commands in `cli.rs` for Perl configuration and installation. - Updated `internal.rs` to execute Perl helper commands using the new functions. - Enhanced `shell_helpers.rs` to include scripts for Perl configure and install commands. - Modified `hooks.rs` to apply build helper context and directories for post-extract and post-configure commands. - Added tests to ensure the correct execution of Perl build helper commands and their integration with the build process.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
//! GNU Autotools build system (configure && make && make install)
|
||||
|
||||
use crate::builder::BuildHelperContext;
|
||||
use crate::builder::state::{BuildStep, StateTracker};
|
||||
use crate::cross::CrossConfig;
|
||||
use crate::fakeroot;
|
||||
@@ -501,6 +502,202 @@ pub(crate) fn ensure_host_build(
|
||||
.with_context(|| format!("Failed to resolve host build dir: {}", build_dir.display()))
|
||||
}
|
||||
|
||||
pub(crate) fn run_helper_configure(
|
||||
context: &BuildHelperContext,
|
||||
source_dir: Option<&Path>,
|
||||
build_dir: Option<&Path>,
|
||||
cross: Option<&CrossConfig>,
|
||||
env_vars: &[(String, String)],
|
||||
extra_args: &[String],
|
||||
) -> Result<()> {
|
||||
let flags = context.build_flags();
|
||||
let source_dir = source_dir
|
||||
.map(Path::to_path_buf)
|
||||
.unwrap_or(std::env::current_dir().context("Failed to determine current directory")?);
|
||||
let build_dir = build_dir.map(Path::to_path_buf).unwrap_or_else(|| {
|
||||
flags
|
||||
.build_dir
|
||||
.as_ref()
|
||||
.map(|dir| source_dir.join(dir))
|
||||
.unwrap_or_else(|| source_dir.clone())
|
||||
});
|
||||
fs::create_dir_all(&build_dir)
|
||||
.with_context(|| format!("Failed to create build directory: {}", build_dir.display()))?;
|
||||
|
||||
let mut helper_env = env_vars.to_vec();
|
||||
let cc = if let Some(cc_cfg) = cross {
|
||||
cc_cfg.cc.clone()
|
||||
} else {
|
||||
helper_env
|
||||
.iter()
|
||||
.find(|(key, _)| key == "CC")
|
||||
.map(|(_, value)| value.clone())
|
||||
.unwrap_or_else(|| flags.cc.clone())
|
||||
};
|
||||
|
||||
if let Some(cflags_str) = helper_env
|
||||
.iter()
|
||||
.find(|(key, _)| key == "CFLAGS")
|
||||
.map(|(_, value)| value.clone())
|
||||
.filter(|value| !value.trim().is_empty())
|
||||
{
|
||||
let expanded = expand_shell_commands(&cflags_str, &cc)?;
|
||||
crate::builder::set_env_var(&mut helper_env, "CFLAGS", expanded);
|
||||
}
|
||||
|
||||
let configure_path = helper_configure_path(context, &source_dir);
|
||||
let mut configure_cmd = Command::new(&configure_path);
|
||||
configure_cmd.current_dir(&build_dir);
|
||||
crate::builder::prepare_tool_command(&mut configure_cmd, &helper_env);
|
||||
|
||||
let help_text = configure_help_text(&configure_path, &build_dir, &helper_env);
|
||||
configure_cmd.arg(format!("--prefix={}", flags.prefix));
|
||||
for default_dir_arg in default_configure_install_dirs(&flags, help_text.as_deref()) {
|
||||
configure_cmd.arg(default_dir_arg);
|
||||
}
|
||||
|
||||
let supports_host =
|
||||
configure_supports_option(help_text.as_deref(), "--host", &flags.configure_file);
|
||||
let supports_build =
|
||||
configure_supports_option(help_text.as_deref(), "--build", &flags.configure_file);
|
||||
|
||||
let requested_host = if let Some(cc_cfg) = cross {
|
||||
Some(cc_cfg.host_triple().to_string())
|
||||
} else if !flags.chost.is_empty() {
|
||||
Some(flags.chost.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.map(|host| {
|
||||
if flags.lib32_variant {
|
||||
lib32_host_triple(&host)
|
||||
} else {
|
||||
host
|
||||
}
|
||||
});
|
||||
|
||||
let requested_build = if cross.is_some() {
|
||||
CrossConfig::build_triple().ok()
|
||||
} else if !flags.cbuild.is_empty() {
|
||||
Some(flags.cbuild.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(host) = requested_host {
|
||||
if supports_host {
|
||||
configure_cmd.arg(format!("--host={host}"));
|
||||
} else {
|
||||
crate::log_info!(" configure does not support --host; skipping {}", host);
|
||||
}
|
||||
}
|
||||
if let Some(build) = requested_build {
|
||||
if supports_build {
|
||||
configure_cmd.arg(format!("--build={build}"));
|
||||
} else {
|
||||
crate::log_info!(" configure does not support --build; skipping {}", build);
|
||||
}
|
||||
}
|
||||
|
||||
for arg in &flags.configure {
|
||||
configure_cmd.arg(expand_with_envs(&context.expand_vars(arg), &helper_env));
|
||||
}
|
||||
for arg in crate::builder::static_build_args_for(crate::package::BuildType::Autotools, &flags)?
|
||||
{
|
||||
add_auto_configure_arg_if_supported(&mut configure_cmd, help_text.as_deref(), &arg);
|
||||
}
|
||||
for arg in extra_args {
|
||||
add_auto_configure_arg_if_supported(
|
||||
&mut configure_cmd,
|
||||
help_text.as_deref(),
|
||||
&expand_with_envs(&context.expand_vars(arg), &helper_env),
|
||||
);
|
||||
}
|
||||
|
||||
let status = crate::interrupts::command_status(&mut configure_cmd)
|
||||
.with_context(|| format!("Failed to run helper configure in {}", build_dir.display()))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("configure failed with status: {}", status);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn run_helper_install(
|
||||
context: &BuildHelperContext,
|
||||
build_dir: Option<&Path>,
|
||||
env_vars: &[(String, String)],
|
||||
extra_args: &[String],
|
||||
) -> Result<()> {
|
||||
let flags = context.build_flags();
|
||||
let source_dir = helper_source_dir();
|
||||
let build_dir = build_dir.map(Path::to_path_buf).unwrap_or_else(|| {
|
||||
flags
|
||||
.build_dir
|
||||
.as_ref()
|
||||
.map(|dir| source_dir.join(dir))
|
||||
.unwrap_or_else(|| source_dir.clone())
|
||||
});
|
||||
let destdir = std::env::var("DESTDIR").context("DESTDIR must be set for autotools_install")?;
|
||||
let make_exec = resolve_make_exec(&flags.make_exec);
|
||||
let install_dirs = resolve_make_dirs(
|
||||
&build_dir,
|
||||
&flags.make_install_dirs,
|
||||
"build.flags.make_install_dirs",
|
||||
)?;
|
||||
let install_targets = phase_targets(
|
||||
&flags.make_install_target,
|
||||
&flags.make_install_targets,
|
||||
Some("install"),
|
||||
);
|
||||
|
||||
for install_dir in install_dirs {
|
||||
let mut install_cmd = fakeroot::wrap_install_command(make_exec, Path::new(&destdir));
|
||||
install_cmd.current_dir(&install_dir);
|
||||
if make_exec_supports_make_assignments(make_exec)
|
||||
&& !has_make_variable_override(&flags.make_install_vars, "DESTDIR")
|
||||
{
|
||||
install_cmd.arg(format!("DESTDIR={destdir}"));
|
||||
}
|
||||
add_make_variable_overrides_if_supported(
|
||||
&mut install_cmd,
|
||||
make_exec,
|
||||
&flags.make_install_vars,
|
||||
"install",
|
||||
)?;
|
||||
for install_target in &install_targets {
|
||||
install_cmd.arg(install_target);
|
||||
}
|
||||
for arg in extra_args {
|
||||
install_cmd.arg(context.expand_vars(arg));
|
||||
}
|
||||
|
||||
let mut install_env = env_vars.to_vec();
|
||||
crate::builder::set_env_var(&mut install_env, "DESTDIR", destdir.clone());
|
||||
crate::builder::prepare_tool_command(&mut install_cmd, &install_env);
|
||||
|
||||
let status = crate::interrupts::command_status(&mut install_cmd).with_context(|| {
|
||||
format!(
|
||||
"Failed to run helper {} {} in {}",
|
||||
make_exec,
|
||||
install_targets.join(" "),
|
||||
install_dir.display()
|
||||
)
|
||||
})?;
|
||||
if !status.success() {
|
||||
anyhow::bail!(
|
||||
"{} {} failed with status: {} (dir: {})",
|
||||
make_exec,
|
||||
install_targets.join(" "),
|
||||
status,
|
||||
install_dir.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn num_cpus() -> usize {
|
||||
std::thread::available_parallelism()
|
||||
.map(|n| n.get())
|
||||
@@ -544,6 +741,22 @@ fn resolve_configure_path(spec: &PackageSpec, actual_src: &Path) -> PathBuf {
|
||||
}
|
||||
}
|
||||
|
||||
fn helper_configure_path(context: &BuildHelperContext, actual_src: &Path) -> PathBuf {
|
||||
let flags = context.build_flags();
|
||||
let configured = context.expand_vars(&flags.configure_file);
|
||||
let trimmed = configured.trim();
|
||||
if trimmed.is_empty() {
|
||||
return actual_src.join("configure");
|
||||
}
|
||||
|
||||
let path = Path::new(trimmed);
|
||||
if path.is_absolute() {
|
||||
path.to_path_buf()
|
||||
} else {
|
||||
actual_src.join(path)
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_help_text(
|
||||
configure_path: &Path,
|
||||
build_dir: &Path,
|
||||
@@ -823,6 +1036,12 @@ fn nonempty_trimmed(value: &str) -> Option<&str> {
|
||||
(!trimmed.is_empty()).then_some(trimmed)
|
||||
}
|
||||
|
||||
fn helper_source_dir() -> PathBuf {
|
||||
std::env::var(crate::builder::DEPOT_BUILD_HELPER_SOURCE_DIR_ENV)
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")))
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_make_exec(configured: &str) -> &str {
|
||||
nonempty_trimmed(configured).unwrap_or("make")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user