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
2 changes: 1 addition & 1 deletion crates/fbuild-daemon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ async fn main() {
let identity = fbuild_paths::running_process::DaemonCacheIdentity::discover();
let claim = fbuild_paths::daemon_ownership::OwnerClaim {
pid: std::process::id(),
exe,
exe: exe.into(),
version: env!("CARGO_PKG_VERSION").to_string(),
mode: identity.mode.to_string(),
cache_root_key: identity.cache_root_key.clone(),
Expand Down
57 changes: 42 additions & 15 deletions crates/fbuild-library/src/library/esp32_framework/libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,33 @@ fn mcu_sdk_complete(mcu_dir: &Path) -> bool {
&& mcu_dir.join("lib").join("libfreertos.a").exists()
}

/// A skeleton archive's package manifest proves that its MCU payload was
/// extracted. Package metadata is merged beside the MCU directories, not
/// inside them. Use this only after extracting the requested skeleton, never
/// to skip its download.
fn mcu_skeleton_extracted(tools_dir: &Path, mcu: &str) -> bool {
let sdk_dir = tools_dir.join(NEW_SDK_LAYOUT);
sdk_dir.join(mcu).is_dir() && sdk_dir.join("dependencies.lock").is_file()
/// Merge a requested MCU directory from a skeleton archive, regardless of a
/// package wrapper directory added by the archive producer. Returns whether
/// the archive actually contained the requested MCU payload.
fn merge_skeleton_mcu_entries(
temp_dir: &Path,
tools_dir: &Path,
mcu: &str,
) -> fbuild_core::Result<bool> {
fn visit(dir: &Path, destination: &Path, mcu: &str) -> fbuild_core::Result<bool> {
let mut found = false;
for entry in std::fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if !path.is_dir() {
continue;
}
if entry.file_name() == mcu {
copy_dir_recursive(&path, destination)?;
found = true;
} else {
found |= visit(&path, destination, mcu)?;
}
}
Ok(found)
}

visit(temp_dir, &tools_dir.join(NEW_SDK_LAYOUT).join(mcu), mcu)
}

fn patch_mcu_compatibility(mcu_dir: &Path, mcu: &str) -> fbuild_core::Result<()> {
Expand Down Expand Up @@ -187,10 +207,10 @@ impl Esp32Framework {
// Skeleton archives such as c2_arduino_compile_skeleton.zip extract as
// a direct esp32c2/ directory. Merge direct MCU roots into the new SDK
// layout so sdk_mcu_dir() finds the completed tree.
merge_sdk_archive_entries(temp_dir.path(), &tools_dir)?;
let merged_skeleton = merge_skeleton_mcu_entries(temp_dir.path(), &tools_dir, mcu)?;

for mcu_dir in mcu_sdk_dir_candidates(&tools_dir, mcu) {
if mcu_sdk_complete(&mcu_dir) || mcu_skeleton_extracted(&tools_dir, mcu) {
if mcu_sdk_complete(&mcu_dir) || merged_skeleton {
patch_mcu_compatibility(&mcu_dir, mcu)?;
tracing::info!("{} skeleton libs installed", mcu);
return Ok(());
Expand Down Expand Up @@ -244,15 +264,22 @@ mod tests {
}

#[test]
fn skeleton_marker_requires_package_manifest() {
fn skeleton_merge_finds_mcu_under_package_wrapper() {
let tmp = tempfile::TempDir::new().unwrap();
let tools_dir = tmp.path().join("tools");
let sdk_dir = tools_dir.join(NEW_SDK_LAYOUT);
std::fs::create_dir_all(sdk_dir.join("esp32c2")).unwrap();
let archive = tmp.path().join("archive");
let source_mcu = archive.join("package-wrapper").join("esp32c2");
write(&source_mcu.join("lib").join("libfreertos.a"), "");

assert!(!mcu_skeleton_extracted(&tools_dir, "esp32c2"));
write(&sdk_dir.join("dependencies.lock"), "");
assert!(mcu_skeleton_extracted(&tools_dir, "esp32c2"));
assert!(merge_skeleton_mcu_entries(&archive, &tools_dir, "esp32c2").unwrap());
assert!(
tools_dir
.join(NEW_SDK_LAYOUT)
.join("esp32c2")
.join("lib")
.join("libfreertos.a")
.is_file()
);
}

#[test]
Expand Down
20 changes: 11 additions & 9 deletions crates/fbuild-paths/src/daemon_ownership.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
//! the lock when the holding process exits (including a hard kill); the
//! file itself is not the lock.

use std::path::{Path, PathBuf};
use std::path::Path;

use fbuild_core::file_lock::{self, FileLockGuard, FileLockMode};
use fbuild_core::path::NormalizedPath;

use crate::get_daemon_dir;

Expand Down Expand Up @@ -91,18 +92,18 @@ pub fn try_acquire_spawn_lock_at(path: &Path) -> Option<SpawnLockGuard> {
}

/// Path to the root-ownership lock file.
pub fn root_owner_lock_path() -> PathBuf {
get_daemon_dir().join(ROOT_OWNER_LOCK_NAME)
pub fn root_owner_lock_path() -> NormalizedPath {
get_daemon_dir().join(ROOT_OWNER_LOCK_NAME).into()
}

/// Path to the spawn-herd lock file.
pub fn spawn_lock_path() -> PathBuf {
get_daemon_dir().join(SPAWN_LOCK_NAME)
pub fn spawn_lock_path() -> NormalizedPath {
get_daemon_dir().join(SPAWN_LOCK_NAME).into()
}

/// Path to the [`OwnerClaim`] JSON file.
pub fn owner_claim_path() -> PathBuf {
get_daemon_dir().join(OWNER_CLAIM_NAME)
pub fn owner_claim_path() -> NormalizedPath {
get_daemon_dir().join(OWNER_CLAIM_NAME).into()
}

/// Advisory claim written by the daemon after it has acquired root
Expand All @@ -117,7 +118,7 @@ pub fn owner_claim_path() -> PathBuf {
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct OwnerClaim {
pub pid: u32,
pub exe: PathBuf,
pub exe: NormalizedPath,
/// `env!("CARGO_PKG_VERSION")` of the daemon that wrote the claim.
pub version: String,
/// `"dev"` | `"prod"`.
Expand Down Expand Up @@ -157,6 +158,7 @@ pub fn remove_owner_claim() {
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
use tempfile::TempDir;

#[test]
Expand Down Expand Up @@ -241,7 +243,7 @@ mod tests {
let path = temp.path().join(OWNER_CLAIM_NAME);
let claim = OwnerClaim {
pid: 4242,
exe: PathBuf::from("/usr/local/bin/fbuild-daemon"),
exe: PathBuf::from("/usr/local/bin/fbuild-daemon").into(),
version: "9.9.9".to_string(),
mode: "dev".to_string(),
cache_root_key: "abc123".to_string(),
Expand Down
Loading