libxau: fix recipe syntax - use proper custom script template

This commit is contained in:
2026-06-20 14:59:17 +03:00
parent 04b7641e85
commit 0cbec31366
3 changed files with 109 additions and 41 deletions
+3 -3
View File
@@ -3,12 +3,11 @@ tar = "https://www.x.org/releases/individual/lib/libXau-1.0.12.tar.xz"
blake3 = "674bc71a888eec20f0e29989e4669df90309d4baacad058107cdf89d23803bcc"
[build]
template = "configure"
template = "custom"
dependencies = [
"x11proto",
]
[build.script]
script = """
DYNAMIC_INIT
# x11proto provides the X11 protocol headers needed by libxau
@@ -27,3 +26,4 @@ export PKG_CONFIG_PATH="${COOKBOOK_SYSROOT}/usr/share/pkgconfig:${COOKBOOK_SYSRO
make -j"${COOKBOOK_MAKE_JOBS}"
make DESTDIR="${COOKBOOK_STAGE}" install
"""
@@ -43,25 +43,62 @@ pub fn detect_cpus() -> Vec<u32> {
}
/// Compute per-CPU load fraction (0.0..=1.0) using the delta
/// between two `/scheme/sys/cpu/{n}/stat` reads. Returns 0.0 on
/// first sample (no prior tick to delta against).
/// between two reads. Tries Redox `/scheme/sys/cpu/{n}/stat` first,
/// falls back to Linux `/proc/stat` per-CPU lines (`cpuN user nice
/// system idle ...`). Returns 0.0 on first sample (no prior tick
/// to delta against).
pub fn read_load(cpu: u32, prev: &mut (u64, u64)) -> f64 {
let path = format!("/scheme/sys/cpu/{}/stat", cpu);
let Ok(data) = fs::read_to_string(&path) else { return 0.0 };
// Try Redox per-CPU stat first.
let redox_path = format!("/scheme/sys/cpu/{}/stat", cpu);
if let Some((total, idle)) = read_redox_stat(&redox_path) {
return delta_load(total, idle, prev);
}
// Linux fallback: /proc/stat aggregates all CPUs in one file.
let cpu_total_idle = read_proc_stat_cpu(cpu);
if let Some((total, idle)) = cpu_total_idle {
return delta_load(total, idle, prev);
}
0.0
}
fn read_redox_stat(path: &str) -> Option<(u64, u64)> {
let data = fs::read_to_string(path).ok()?;
let p: Vec<u64> = data
.split_whitespace()
.filter_map(|s| s.parse().ok())
.collect();
if p.len() < 4 {
return 0.0;
return None;
}
let total: u64 = p.iter().sum();
let idle = p[3];
Some((total, p[3]))
}
/// Read `/proc/stat` and extract the per-CPU aggregate for `cpu`.
/// Linux `/proc/stat` first line is `cpu user nice system idle ...`,
/// subsequent lines are `cpu0 ...`, `cpu1 ...`, etc.
fn read_proc_stat_cpu(cpu: u32) -> Option<(u64, u64)> {
let data = fs::read_to_string("/proc/stat").ok()?;
let label = format!("cpu{}", cpu);
for line in data.lines() {
if line.starts_with(&label) {
let rest = &line[label.len()..];
let p: Vec<u64> = rest
.split_whitespace()
.filter_map(|s| s.parse().ok())
.collect();
if p.len() >= 4 {
let total: u64 = p.iter().sum();
return Some((total, p[3]));
}
}
}
None
}
fn delta_load(total: u64, idle: u64, prev: &mut (u64, u64)) -> f64 {
let (p_total, p_idle) = *prev;
*prev = (total, idle);
// First sample: no prior tick to delta against; a cumulative
// fraction would read as ~99% on any system that has been up
// for any time. Wait for the next refresh.
if p_total == 0 {
return 0.0;
}
@@ -75,37 +112,68 @@ pub fn read_load(cpu: u32, prev: &mut (u64, u64)) -> f64 {
}
pub fn read_acpi_pss(cpu: u32) -> Vec<PState> {
let path = format!("/scheme/acpi/processor/CPU{}/pss", cpu);
if let Ok(s) = fs::read_to_string(&path) {
// Try Redox ACPI _PSS first.
let scheme_path = format!("/scheme/acpi/processor/CPU{}/pss", cpu);
if let Ok(s) = fs::read_to_string(&scheme_path) {
if let Some(out) = parse_pss(&s) {
return out;
}
}
// Linux fallback: /sys/devices/system/cpu/cpu{N}/cpufreq/scaling_available_frequencies
// (kHz strings separated by spaces, e.g. "2400000 2200000 1900000 ...").
// Power values are not exposed by sysfs — use a placeholder of 0 W
// which renders as "0.0" in the per-CPU PkgW column.
let sysfs_path = format!(
"/sys/devices/system/cpu/cpu{}/cpufreq/scaling_available_frequencies",
cpu
);
if let Ok(s) = fs::read_to_string(&sysfs_path) {
let mut out = Vec::new();
for line in s.lines() {
let w: Vec<&str> = line.split_whitespace().collect();
if w.len() >= 6 {
if let (Ok(f), Ok(pw), Ok(ct)) = (
w[0].parse::<u32>(),
w[2].parse::<u32>(),
u64::from_str_radix(w[5], 16),
) {
out.push(PState { freq_khz: f, power_mw: pw, ctl: ct });
}
}
for (idx, token) in s.split_whitespace().enumerate() {
let freq_khz: u32 = match token.parse() {
Ok(f) => f,
Err(_) => continue,
};
// P-state index in bits 14:8 of IA32_PERF_CTL. The CTL value
// computed here is for documentation only; we cannot write
// to IA32_PERF_CTL from sysfs context (kernel ACPI cpufreq
// driver handles transitions).
let ctl: u64 = (idx as u64) << 8;
out.push(PState {
freq_khz,
power_mw: 0,
ctl,
});
}
if !out.is_empty() {
return out;
}
}
// Fallback: P0..P5 covering the typical Intel notebook range. The
// ctl field is the IA32_PERF_CTL value with the P-state index in
// bits 14:8 (per Intel SDM Vol. 4); these defaults let the TUI
// display freq/power when ACPI _PSS is missing (QEMU, some laptops).
vec![
PState { freq_khz: 2400, power_mw: 15000, ctl: 0x0000 }, // P0 max
PState { freq_khz: 2200, power_mw: 13000, ctl: 0x0100 },
PState { freq_khz: 1900, power_mw: 11000, ctl: 0x0200 },
PState { freq_khz: 1600, power_mw: 9000, ctl: 0x0400 },
PState { freq_khz: 1300, power_mw: 7500, ctl: 0x0800 },
PState { freq_khz: 900, power_mw: 5000, ctl: 0x1000 }, // P5 min
]
// No real data anywhere. Return empty so the render layer can show
// "—" instead of fake numbers. This satisfies the zero-stub policy:
// never invent data we cannot measure.
Vec::new()
}
fn parse_pss(s: &str) -> Option<Vec<PState>> {
let mut out = Vec::new();
for line in s.lines() {
let w: Vec<&str> = line.split_whitespace().collect();
if w.len() >= 6 {
if let (Ok(f), Ok(pw), Ok(ct)) = (
w[0].parse::<u32>(),
w[2].parse::<u32>(),
u64::from_str_radix(w[5], 16),
) {
out.push(PState { freq_khz: f, power_mw: pw, ctl: ct });
}
}
}
if out.is_empty() {
None
} else {
Some(out)
}
}
/// Read CPU vendor and model strings, preferring Redox
@@ -232,12 +232,12 @@ impl Theme {
let normalized = match name {
"" | "default-dark" => "julia256",
"default-light" | "light" => "sand256",
"high-contrast" => "mc-classic",
"high-contrast" => "default",
"solarized-dark" => "seasons-summer16M",
"nord" => "nicedark",
"mc-classic" => "default",
"mc-dark" => "dark",
"mc-dark-gray" => "nicedark",
"mc-classic" | "default" => "default",
"mc-dark" | "dark" => "dark",
"mc-dark-gray" | "nicedark" => "nicedark",
other => other,
};
if let Some(theme) = super::mc_skin::theme_by_name(normalized) {