- after the zone swap the cache file mappings are mapped again (device/inode checked), so clean file pages leave the resident set: Stage 2.3 GB -> 1.07 GB resident (peak 3.7 -> 1.8 GB), Calculator 600 -> 273 MB - the platform build script is answered natively from one shared generator (platform/build_gen.rs, byte-identical to build.rs): 230-430 ms -> 0.2 ms - crate records and the front graph are written after the first present and flushed on quit; the host window is joined after the load - cold Calculator at 4 cores: CPU to present -7.5%, instructions -12% Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
105 lines
4.5 KiB
Rust
105 lines
4.5 KiB
Rust
//! What makepad-platform's build script generates, in one place: `platform/build.rs` (cargo) includes
|
|
//! this file with `#[path]`, and `makepad run` (libs/relax/front/src/unitgraph.rs) includes the same file
|
|
//! and answers the script natively, without booting a second Relax process for it. Plain std code, no
|
|
//! cargo calls: the two callers cannot drift (a test in relax-front runs the real build.rs against it).
|
|
#![allow(dead_code)]
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
/// Default bundle name when MAKEPAD_BUNDLE_NAME isn't set. Cargo doesn't expose the consuming
|
|
/// binary's package name to a dependency's build script (`CARGO_PKG_NAME` here is
|
|
/// "makepad-platform"), so walk up from `OUT_DIR` (always
|
|
/// `<root>/target/<profile>/build/<crate>-<hash>/out`) to the directory that contains `target/`
|
|
/// and use that directory's name, first letter capitalised. None if the path doesn't have the
|
|
/// expected shape or the directory name isn't valid UTF-8.
|
|
pub fn detect_app_name(out_dir: &Path) -> Option<String> {
|
|
let workspace_root = out_dir.ancestors().nth(5)?;
|
|
let dir_name = workspace_root.file_name()?.to_str()?;
|
|
if dir_name.is_empty() {
|
|
return None;
|
|
}
|
|
let mut chars = dir_name.chars();
|
|
let first = chars.next()?;
|
|
Some(first.to_uppercase().collect::<String>() + chars.as_str())
|
|
}
|
|
|
|
/// (bundle name, bundle identifier) of the build.
|
|
pub fn bundle(out_dir: &Path) -> (String, String) {
|
|
let name = detect_app_name(out_dir).unwrap_or_else(|| "Makepad App".to_string());
|
|
let id = format!("dev.makepad.{}", name.to_lowercase().replace(' ', "-"));
|
|
(name, id)
|
|
}
|
|
|
|
/// The text of OUT_DIR/app_meta_gen.rs.
|
|
pub fn app_meta_gen(out_dir: &Path) -> String {
|
|
let (bundle_name, bundle_id) = bundle(out_dir);
|
|
format!(
|
|
"/// The bundle name when the app's build sets no MAKEPAD_BUNDLE_NAME.\n\
|
|
pub const DEFAULT_BUNDLE_NAME: &str = {bundle_name:?};\n\
|
|
/// The identifier that goes with [`DEFAULT_BUNDLE_NAME`].\n\
|
|
pub const DEFAULT_BUNDLE_IDENTIFIER: &str = {bundle_id:?};\n"
|
|
)
|
|
}
|
|
|
|
/// Window icons auto-discovered in `<workspace_root>/resources/` (the dir containing `target/`,
|
|
/// 5 ancestors up from OUT_DIR, as in `detect_app_name`). An app's own icons (MAKEPAD_APP_ICON_*)
|
|
/// are read by `app_main!` in the app crate instead (src/app_meta.rs).
|
|
pub struct Icons {
|
|
/// the text of OUT_DIR/app_icon_gen.rs
|
|
pub source: String,
|
|
/// the icon files it includes
|
|
pub files: Vec<PathBuf>,
|
|
/// `<root>/resources` when it is a directory (cargo watches it)
|
|
pub dir: Option<PathBuf>,
|
|
}
|
|
|
|
pub fn app_icon_gen(out_dir: &Path) -> Icons {
|
|
let icons: &[(&str, &str)] = &[
|
|
("icon_32.png", "CUSTOM_ICON_PNG_32"),
|
|
("icon_64.png", "CUSTOM_ICON_PNG_64"),
|
|
("icon_128.png", "CUSTOM_ICON_PNG_128"),
|
|
("icon_256.png", "CUSTOM_ICON_PNG_256"),
|
|
("icon_512.png", "CUSTOM_ICON_PNG_512"),
|
|
("icon_1024.png", "CUSTOM_ICON_PNG_1024"),
|
|
("icon.ico", "CUSTOM_ICON_ICO"),
|
|
];
|
|
let resources_dir = out_dir.ancestors().nth(5).map(|r| r.join("resources"));
|
|
let mut source = String::new();
|
|
let mut files = Vec::new();
|
|
for &(filename, const_name) in icons {
|
|
let path = resources_dir.as_ref().and_then(|dir| {
|
|
let p = dir.join(filename);
|
|
p.is_file().then_some(p)
|
|
});
|
|
let value = match &path {
|
|
Some(p) => {
|
|
files.push(p.clone());
|
|
format!("include_bytes!(r#\"{}\"#)", p.to_string_lossy())
|
|
}
|
|
None => "&[]".to_string(),
|
|
};
|
|
source.push_str(&format!("#[allow(dead_code)] pub static {const_name}: &'static [u8] = {value};\n"));
|
|
}
|
|
Icons { source, files, dir: resources_dir.filter(|d| d.is_dir()) }
|
|
}
|
|
|
|
/// The `cargo:rustc-cfg=` words: the `lines` / `apple_bundle` words of MAKEPAD_BUILD (split on
|
|
/// `+` and `,`) and `apple_sim` for the iOS / tvOS simulator targets.
|
|
pub fn cfgs(makepad_build: Option<&str>, target_os: &str, target: &str) -> Vec<&'static str> {
|
|
let mut out = Vec::new();
|
|
if let Some(configs) = makepad_build {
|
|
for config in configs.split(['+', ',']) {
|
|
match config {
|
|
"lines" => out.push("lines"),
|
|
"apple_bundle" => out.push("apple_bundle"),
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
match target_os {
|
|
"ios" if target == "aarch64-apple-ios-sim" => out.push("apple_sim"),
|
|
"tvos" if target == "aarch64-apple-tvos-sim" => out.push("apple_sim"),
|
|
_ => {}
|
|
}
|
|
out
|
|
}
|