Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,9 @@ pub fn default_applications() -> HashMap<String, ApplicationAttributes> {
let flmping_cmd = "${FLAME_HOME}/bin/flmping-service".to_string();
let uv_cmd = "${FLAME_HOME}/bin/uv".to_string();
let flmping_url = "file://${FLAME_HOME}/bin/flmping-service".to_string();
let flamepy_sdk_path = "file://${FLAME_HOME}/sdk/python".to_string();
// Use pre-built wheel from wheels directory to avoid rebuild on every run
// The wheel is built during installation via "flmadm install"
let flamepy_wheels_dir = "${FLAME_HOME}/wheels".to_string();

HashMap::from([
(
Expand Down Expand Up @@ -227,10 +229,12 @@ pub fn default_applications() -> HashMap<String, ApplicationAttributes> {
command: Some(uv_cmd),
arguments: vec![
"run".to_string(),
"--find-links".to_string(),
flamepy_wheels_dir,
"--with".to_string(),
"pip".to_string(),
"--with".to_string(),
format!("flamepy @ {}", flamepy_sdk_path),
"flamepy".to_string(),
"python".to_string(),
"-m".to_string(),
"flamepy.runner.runpy".to_string(),
Expand Down
79 changes: 68 additions & 11 deletions flmadm/src/managers/installation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,21 +193,72 @@ impl InstallationManager {
}

// Copy SDK source to the installation directory, excluding development artifacts
// uv will use this directly with --with "flamepy @ file://..."
self.copy_sdk_excluding_artifacts(&sdk_src, &paths.sdk_python)
.context("Failed to copy SDK to installation directory")?;

println!("✓ Copied Python SDK to: {}", paths.sdk_python.display());
println!(" ✓ Copied Python SDK to: {}", paths.sdk_python.display());

// Create a note in the sdk_python directory for reference
let readme_path = paths.sdk_python.join("README.txt");
std::fs::write(
&readme_path,
"Python SDK source copied to this directory.\n\
Applications use 'uv run --with \"flamepy @ file://...\"' to access it.\n\
No separate installation required.\n",
)
.ok(); // Ignore errors for this informational file
// Build wheel for faster runtime loading
// uv always rebuilds local directory dependencies, but wheel files are cached
self.build_python_wheel(paths)?;

Ok(())
}

/// Build Python wheel from SDK source and pre-cache dependencies
fn build_python_wheel(&self, paths: &InstallationPaths) -> Result<()> {
println!(" 📦 Building Python wheel...");

// Create wheels directory
fs::create_dir_all(&paths.wheels).context("Failed to create wheels directory")?;

// Find uv binary
let uv_path = paths.bin.join("uv");
if !uv_path.exists() {
println!(" ⚠️ uv not found, skipping wheel build (will build at runtime)");
return Ok(());
}

// Build wheel using uv
let output = std::process::Command::new(&uv_path)
.arg("build")
.arg("--wheel")
.arg("--out-dir")
.arg(&paths.wheels)
.arg(&paths.sdk_python)
.output()
.context("Failed to execute uv build")?;

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("Failed to build wheel: {}", stderr);
}

println!(" ✓ Built wheel to: {}", paths.wheels.display());

// Pre-cache dependencies by downloading them to the wheels directory
// This way "uv run --find-links <wheels>" can use cached packages
println!(" 📥 Downloading dependencies...");

let output = std::process::Command::new(&uv_path)
.arg("pip")
.arg("download")
.arg("--dest")
.arg(&paths.wheels)
.arg(&paths.sdk_python)
.output()
.context("Failed to execute uv pip download")?;

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
// Don't fail installation if download fails (might be offline)
println!(
" ⚠️ Failed to download dependencies (will fetch at runtime): {}",
stderr.lines().next().unwrap_or(&stderr)
);
} else {
println!(" ✓ Downloaded dependencies to: {}", paths.wheels.display());
}

Ok(())
}
Expand Down Expand Up @@ -402,6 +453,12 @@ impl InstallationManager {
println!(" ✓ Removed Python SDK");
}

// Remove wheels
if paths.wheels.exists() {
fs::remove_dir_all(&paths.wheels).context("Failed to remove wheels directory")?;
println!(" ✓ Removed wheels");
}

// Remove migrations
if paths.migrations.exists() {
fs::remove_dir_all(&paths.migrations)
Expand Down
2 changes: 2 additions & 0 deletions flmadm/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub struct InstallationPaths {
pub prefix: PathBuf,
pub bin: PathBuf,
pub sdk_python: PathBuf,
pub wheels: PathBuf,
pub work: PathBuf,
pub logs: PathBuf,
pub conf: PathBuf,
Expand All @@ -108,6 +109,7 @@ impl InstallationPaths {
Self {
bin: prefix.join("bin"),
sdk_python: prefix.join("sdk/python"),
wheels: prefix.join("wheels"),
work: prefix.join("work"),
logs: prefix.join("logs"),
conf: prefix.join("conf"),
Expand Down
Loading