* wip: fix manganis import path * upgrade tauri bundler, convert todo!() to unimplemented!() * feat: mobile hotreloading + ios asset configuration * remove oid demo and its associated env vars * nuke all the things that cause cache thrashing * swap to Asset type * add some more logs * display impl for attrvalue * dont panic on collect failure * cut down web deps to 150 * clean up deps in a lot of places, simplify build scripts * clean up asset resolution and cli-dev profile * wire up absolute paths for manganis asset in a particular mode * move document related things around to shorten compile times * move most things to `document::Item` and then decompose the cli-config * switch link to stylesheet for clarity in examples * move manganis workspace example to examples folder * decompose manganis-cli-support * dont need mobile demo anymore * remove gloo dialogs * html doesnt need document * rename hotreload to devtools * really clean up the html crate * fix weird rsx spacing * clean up desktop to use callback * clean up document a bit * re-wire up devsocket * fix utf css * yeeeet that js out of here * synthetic web system works * web crate almost done being cleaned up * desktop mostly cleaned up too * clean up cli a bit * more cli cleanup * cli builds again * clean up cli, inline structs, cut down number of unique types where possible * hotreload works again for desktop and this time, mobile too * cfg out tungstenite * devserver err * more refactor to cli builder * switch to unbounded_send * new structure is much cleaner * add http serve subcommand * bundled hotreload * kick stylsheets * clean up a bit more, split up eventloop * amazingly serve seems done * change from pub to pub(crate) in cli * remove tools * bit more polish to cli * fix issue with join * gracefully handle fullstack without a server * fullstack mobile demo * fix launch function, move projects into example-projects folder * hoist examples * add "run" command * clean up launch * remove old manual websocket receiver * doctor command * allow desktop to scroll * cut apart router crate * dont put launch in prelude * use dioxus::launch where possible * rename rsx, cut out hotreload tests * remove liveview project * bump native * fix compile for renderers * move sync event response out of interpreter * move render in serve * rollback settings change * cli compiles, huzzah! * change uris for asset * fix asset * new tui screen * new cargo-like tui works * very very verty close * it works! very small bug with incorrect grapheme calc * Clean up devserver a bit * status sytem * tidy up debug filters * clean up logging situation * Fix a number of bugs with log printing * new printing system is more reliable * wire up more stuff * things working but fullstack is having issues * fullstack works again! * hotreloading bundled assets works again * bundled hotreload and beginnings of macos bundling * Hotreload desktop * combined server builds * add build handle * fix fullstack assets * make open async, add some hooks for ios * migrate filemap to runner * wip global crate system * fixup bundles + organize asset * fix asset location bug * all the bundled reloading! * open ios simulator! * full hotreload support for mobile + serverfn * basic cleanups * clean up dx * Move filemap * fix cutting of newlines * assets workibg, some android * hoist wry/tao * use sync locks and headers to fix issues with android * desktop -> mac/win/linux with alias * better logging * feat: workspace (entire computer!) hotreload * should rebuild toggle, ios simulator bootup * proper mobile support in launch * more robust handling of assets * fix cargo * bring back some of tauri bundle * make warnings go away, clippy happy on cli * some final clippy cleanups * fmt * move manganis to its own folder * upgrade bundle to stable * drastically slim down manganis, prepping for merge * typos, failing test, docsrs config * remove static gen test * nix static gen test * we use --platform web instead of --platform fullstack now * only bind dev urls in desktop/mobile * install gtk * nix static gen * split build dir by app name
114 lines
4.2 KiB
Rust
114 lines
4.2 KiB
Rust
use anyhow::Context;
|
|
use manganis_core::{LinkSection, ResourceAsset};
|
|
use object::{read::archive::ArchiveFile, File as ObjectFile, Object, ObjectSection};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::path::Path;
|
|
use std::{collections::HashMap, path::PathBuf};
|
|
|
|
/// A manifest of all assets collected from dependencies
|
|
///
|
|
/// This will be filled in primarily by incremental compilation artifacts.
|
|
#[derive(Debug, PartialEq, Default, Clone, Serialize, Deserialize)]
|
|
pub(crate) struct AssetManifest {
|
|
/// Map of bundled asset name to the asset itself
|
|
pub(crate) assets: HashMap<PathBuf, ResourceAsset>,
|
|
}
|
|
|
|
impl AssetManifest {
|
|
pub(crate) fn load_from_file(path: &Path) -> anyhow::Result<Self> {
|
|
let src = std::fs::read_to_string(path)
|
|
.context("Failed to read asset manifest from filesystem")?;
|
|
serde_json::from_str(&src)
|
|
.with_context(|| format!("Failed to parse asset manifest from {path:?}\n{src}"))
|
|
}
|
|
|
|
/// Fill this manifest with a file object/rlib files, typically extracted from the linker intercepted
|
|
pub(crate) fn add_from_object_path(&mut self, path: PathBuf) -> anyhow::Result<()> {
|
|
let Some(ext) = path.extension() else {
|
|
return Ok(());
|
|
};
|
|
|
|
let Some(ext) = ext.to_str() else {
|
|
return Ok(());
|
|
};
|
|
|
|
let data = std::fs::read(path.clone())?;
|
|
|
|
match ext {
|
|
// Parse an unarchived object file
|
|
"o" => {
|
|
if let Ok(object) = object::File::parse(&*data) {
|
|
self.add_from_object_file(&object)?;
|
|
}
|
|
}
|
|
|
|
// Parse an rlib as a collection of objects
|
|
"rlib" => {
|
|
if let Ok(archive) = object::read::archive::ArchiveFile::parse(&*data) {
|
|
self.add_from_archive_file(&archive, &data)?;
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Fill this manifest from an rlib / ar file that contains many object files and their entryies
|
|
fn add_from_archive_file(&mut self, archive: &ArchiveFile, data: &[u8]) -> object::Result<()> {
|
|
// Look through each archive member for object files.
|
|
// Read the archive member's binary data (we know it's an object file)
|
|
// And parse it with the normal `object::File::parse` to find the manganis string.
|
|
for member in archive.members() {
|
|
let member = member?;
|
|
let name = String::from_utf8_lossy(member.name()).to_string();
|
|
|
|
// Check if the archive member is an object file and parse it.
|
|
if name.ends_with(".o") {
|
|
let data = member.data(data)?;
|
|
let object = object::File::parse(data)?;
|
|
_ = self.add_from_object_file(&object);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Fill this manifest with whatever tables might come from the object file
|
|
fn add_from_object_file(&mut self, obj: &ObjectFile) -> anyhow::Result<()> {
|
|
for section in obj.sections() {
|
|
let Ok(section_name) = section.name() else {
|
|
continue;
|
|
};
|
|
|
|
// Check if the link section matches the asset section for one of the platforms we support. This may not be the current platform if the user is cross compiling
|
|
let matches = LinkSection::ALL
|
|
.iter()
|
|
.any(|x| x.link_section == section_name);
|
|
|
|
if !matches {
|
|
continue;
|
|
}
|
|
|
|
let bytes = section
|
|
.uncompressed_data()
|
|
.context("Could not read uncompressed data from object file")?;
|
|
|
|
let as_str = std::str::from_utf8(&bytes)
|
|
.context("object file contained non utf8 encoding")?
|
|
.chars()
|
|
.filter(|c| !c.is_control())
|
|
.collect::<String>();
|
|
|
|
let assets = serde_json::Deserializer::from_str(&as_str).into_iter::<ResourceAsset>();
|
|
for as_resource in assets.flatten() {
|
|
// Some platforms (e.g. macOS) start the manganis section with a null byte, we need to filter that out before we deserialize the JSON
|
|
self.assets
|
|
.insert(as_resource.absolute.clone(), as_resource);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|