use indexmap::IndexMap;
use minijinja::Value;
use rattler_build_jinja::Jinja;
use rattler_conda_types::Platform;
pub use rattler_build_script::{
ExecutionArgs, InterpreterError, ResolvedScriptContents, SandboxArguments,
SandboxConfiguration, Script, ScriptContent, platform_script_extensions,
};
use crate::{
env_vars::{self},
metadata::Output,
};
impl Output {
pub(crate) fn jinja_renderer(&self) -> impl Fn(&str) -> Result<String, String> {
let selector_config = self.build_configuration.selector_config();
let jinja = Jinja::new(selector_config.clone()).with_context(&self.recipe.context);
move |template: &str| jinja.render_str(template).map_err(|e| e.to_string())
}
async fn prepare_build_script(&self) -> Result<ExecutionArgs, std::io::Error> {
let host_prefix = self.build_configuration.directories.host_prefix.clone();
let target_platform = self.build_configuration.target_platform;
let env_isolation = self.build_configuration.env_isolation;
let mut env_vars = env_vars::vars(self, "BUILD");
env_vars.extend(env_vars::os_vars(
&host_prefix,
&target_platform,
env_isolation,
));
env_vars.extend(env_vars::env_vars_from_variant(self.variant()));
let jinja_renderer = self.jinja_renderer();
let build_prefix = if self.recipe.build().merge_build_and_host_envs {
None
} else {
Some(&self.build_configuration.directories.build_prefix)
};
let work_dir = &self.build_configuration.directories.work_dir;
Ok(ExecutionArgs {
script: self.recipe.build().script.resolve_content(
&self.build_configuration.directories.recipe_dir,
Some(jinja_renderer),
platform_script_extensions(),
)?,
env_vars: env_vars
.into_iter()
.filter_map(|(k, v)| v.map(|v| (k, v)))
.collect(),
secrets: IndexMap::new(),
build_prefix: build_prefix.map(|p| p.to_owned()),
run_prefix: host_prefix,
execution_platform: Platform::current(),
work_dir: work_dir.clone(),
sandbox_config: self.build_configuration.sandbox_config().cloned(),
env_isolation,
})
}
pub async fn run_build_script(&self) -> Result<(), InterpreterError> {
let span = tracing::info_span!("Running build script");
let _enter = span.enter();
let exec_args = self.prepare_build_script().await?;
let build_prefix = if self.recipe.build().merge_build_and_host_envs {
None
} else {
Some(&self.build_configuration.directories.build_prefix)
};
let mut jinja = Jinja::new(self.build_configuration.selector_config())
.with_context(&self.recipe.context);
for (k, v) in &exec_args.env_vars {
jinja
.context_mut()
.insert(k.clone(), Value::from_safe_string(v.clone()));
}
let jinja_renderer = |template: &str| -> Result<String, String> {
jinja.render_str(template).map_err(|e| e.to_string())
};
self.recipe
.build()
.script
.run_script(
exec_args
.env_vars
.into_iter()
.map(|(k, v)| (k, Some(v)))
.collect(),
&self.build_configuration.directories.work_dir,
&self.build_configuration.directories.recipe_dir,
&self.build_configuration.directories.host_prefix,
build_prefix,
Some(jinja_renderer),
self.build_configuration.sandbox_config(),
self.build_configuration.env_isolation,
)
.await?;
Ok(())
}
pub async fn create_build_script(&self) -> Result<(), std::io::Error> {
let span = tracing::info_span!("Creating build script");
let _enter = span.enter();
let exec_args = self.prepare_build_script().await?;
rattler_build_script::create_build_script(exec_args).await
}
}