Pro · Cargo → WebAssembly
Crates reales, proyectos multi-archivo
Pro desbloquea proyectos con Cargo.toml y dependencias reales de crates.io. Forge —el motor de build nativo en Swift (experimental)— resuelve, compila a WebAssembly y ejecuta todo en el dispositivo, con builds incrementales y fallback de versión estilo JetBrains. Es el modo para programas de Rust de verdad, no solo snippets.
PanoramaQué añade Pro sobre Scratchpad
Scratchpad es un archivo y los crates incluidos. Pro es un proyecto Cargo de verdad: un manifiesto, un árbol src/ con tantos módulos como quieras, y dependencias traídas de crates.io. Forge toma ese proyecto, resuelve el grafo de dependencias, lo compila a WebAssembly y ejecuta el resultado en tu iPad — sin escritorio, sin servidor de por medio.
- Cargo.toml — declara metadatos del crate, features y dependencias, igual que en escritorio.
- Multi-archivo — divide el código en módulos y archivos bajo src/.
- Deps de crates.io — los crates de Rust puro se resuelven y compilan en el dispositivo.
- Builds incrementales — Forge cachea el trabajo, así que las recompilaciones son mucho más rápidas que la primera en frío.
Anatomía
Cómo se ve un proyecto
Un proyecto Pro es un layout normal de Cargo. En la raíz vive Cargo.toml —el manifiesto que nombra el crate y lista sus dependencias— y una carpeta src/ guarda tu código, empezando por main.rs. Eres libre de dividir la lógica en tantos módulos y archivos como quieras; es exactamente la estructura que usarías en escritorio.
mi-proyecto/ ├─ Cargo.toml # nombre, versión, deps ├─ Cargo.lock # versiones resueltas └─ src/ ├─ main.rs # punto de entrada ├─ modelo.rs # tus módulos └─ util.rs
Un proyecto Cargo estándar — manifiesto en la raíz, código bajo src/
Ferric genera esto por ti al crear un proyecto Pro, así que arrancas desde un manifiesto y un main.rs que funciona en vez de una hoja en blanco. A partir de ahí añades módulos con declaraciones mod y traes crates editando Cargo.toml — la misma memoria muscular que en cualquier proyecto de Rust.
Primeros pasosCrea y ejecuta un proyecto
-
Crea un proyecto Pro
Crea un proyecto nuevo y Ferric genera un Cargo.toml más una carpeta src/ con main.rs. Puedes dividir tu código en tantos módulos como quieras.
-
Añade dependencias
Lista crates bajo [dependencies] en Cargo.toml. Forge los descarga y vendoriza la primera vez que compilas.
-
Compila con Forge
Forge compila el proyecto y sus dependencias a WebAssembly y cachea cada unidad, así que las recompilaciones incrementales solo rehacen lo que cambió.
-
Ejecuta e itera
Ejecuta la salida wasm en el dispositivo y lee stdout/stderr en la consola. Edita, recompila, ejecuta — el ciclo se mantiene rápido.
Dependencias
Trabajar con crates.io
Este es el corazón de Pro. Declaras dependencias exactamente como en cualquier proyecto Cargo — un requisito de versión, features opcionales, lo de siempre. Forge lee el manifiesto, resuelve un conjunto compatible de versiones, vendoriza las fuentes y las compila a WebAssembly junto a tu código.
[package] name = "mi-proyecto" version = "0.1.0" edition = "2021" [dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" rand = "0.8"
Cargo.toml — declara crates y features
Luego los usas desde tu código con normalidad. Aquí serde deriva la (de)serialización y serde_json imprime un struct — todo compilado a wasm y ejecutado en el dispositivo.
use serde::Serialize; #[derive(Serialize)] struct Placa { nombre: String, gpios: u8 } fn main() { let p = Placa { nombre: "Pico 2".into(), gpios: 30 }; println!("{}", serde_json::to_string(&p).unwrap()); }
Compilando serde v1.0 · serde_json v1.0 · rand v0.8
Terminado → wasm
{"nombre":"Pico 2","gpios":30}
Añadir una dependencia, paso a paso
-
Añade la línea a Cargo.toml
Abre Cargo.toml y añade el crate bajo [dependencies] con un requisito de versión — por ejemplo rand = «0.8». Para crates que separan funcionalidad tras features, añade una lista de features, como serde con «derive».
-
Compila para resolver y vendorizar
En la siguiente build Forge resuelve un conjunto de versiones compatible, escribe un Cargo.lock y vendoriza las fuentes en el dispositivo. Esta primera descarga es la única vez que el crate toca la red; después todo es local.
-
Úsalo desde tu código
Trae elementos al ámbito con use y llámalos con normalidad. El crate se compila a WebAssembly junto a tu propio código y corre en el mismo sandbox.
Aquí rand —un crate de Rust puro— saca un número aleatorio. Funciona por completo sin conexión una vez vendorizado: la aleatoriedad viene del propio generador del crate, no de la red.
use rand::Rng; fn main() { let mut rng = rand::thread_rng(); let tirada: u8 = rng.gen_range(1..=6); println!("salió un {tirada}"); }
Compilando rand v0.8 · getrandom
Terminado → wasm
salió un 4
Qué crates funcionan
La mayoría de crates de Rust puro compilan y corren en el dispositivo. Una muestra no exhaustiva de lo que se usa hoy:
- serde / serde_json — (de)serialización con derives.
- clap (con derives) — parseo de línea de comandos y structs de argumentos.
- regex, image, uuid, nalgebra, petgraph — texto, imágenes, matemáticas y grafos.
- tokio (single-thread) — runtime async, corriendo en un solo hilo.
Fallback de versión
Si una versión pedida no resuelve o no compila en el dispositivo, Ferric no queda bloqueado. Siguiendo el enfoque estilo JetBrains, retrocede a una versión compatible en vez de fallar de golpe — así un pin estricto no frena toda tu build.
Builds incrementales
La primera build en frío de un proyecto con dependencias es la que más tarda — todo compila desde cero. Después Forge cachea cada unidad compilada, así que editar tu propio código y recompilar solo rehace lo que de verdad cambió. Ese ciclo apretado de editar y ejecutar es lo que hace usable a Pro en una tableta.
Async
Async, en un solo hilo
El async funciona — puedes compilar con tokio o runtimes similares — pero todo corre en single-thread. El sandbox de WebKit no tiene hilos del sistema operativo, así que no hay paralelismo real: las tareas se planifican de forma cooperativa en un hilo. Para la mayoría de programas de forma E/S y de lógica concurrente eso es justo lo que quieres; para trabajo intensivo de CPU repartido entre núcleos, es una limitación real a tener en cuenta.
Límites honestos
Qué no funciona, y por qué
Pro es potente, pero no es un toolchain de escritorio completo, y es mejor conocer los bordes de antemano que chocar con ellos a mitad de proyecto. Hay tres que importan.
Dependencias de C nativas y TLS
No hay compilador de C en el dispositivo, así que cualquier crate con una dependencia de C nativa — un crate *-sys que compila C o C++ en tiempo de build — no puede construirse. En la práctica esto descarta el stack de TLS y criptografía: ring y openssl no compilan, y tampoco nada que los arrastre, como reqwest o rustls. El ecosistema de Rust puro es enorme, pero la red-con-TLS es el hueco notable. Si un crate ofrece un feature de Rust puro, ese camino suele funcionar.
El límite de pila wasm de iOS
Un puñado de crates se apoyan en recursión extrema en tiempo de compilación —árboles match gigantes o tablas const— y chocan con el límite de pila del motor wasm en iOS. num-format es el ejemplo canónico. Cuando pasa, Ferric lo detecta y te lo comunica con claridad en vez de colgarse en silencio, así que nunca te quedas mirando una build congelada sin saber qué falló.
Ejecución en un solo hilo
Como se cubrió arriba, el sandbox de WebKit no tiene hilos del sistema operativo, así que los runtimes async corren en un solo hilo y no hay paralelismo de datos entre núcleos. La mayoría de programas de forma E/S y de lógica concurrente no se ven afectados; el caso a replantear es el trabajo intensivo de CPU que espera muchos núcleos.
Los crates con dependencias de C nativas no compilan — no hay compilador de C en el dispositivo. Eso descarta TLS/criptografía como ring u openssl, y todo lo que los arrastre (reqwest, rustls).
Unos pocos crates con recursión extrema en tiempo de compilación (p. ej. num-format) chocan con el límite de pila del motor wasm de iOS. Ferric lo detecta y te lo comunica con claridad en vez de colgarse.
Los runtimes async funcionan, pero en single-thread: el sandbox de WebKit no tiene hilos del sistema operativo. Y Forge es experimental — espera asperezas mientras madura.
A dónde seguir
Forge es un motor de build nativo en Swift y hoy experimental. Ferric compila y ejecuta Rust por completo en tu iPad — sin nube, sin cuenta.