diff --git a/Cargo.lock b/Cargo.lock index 6117f17..63c29a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -323,6 +323,10 @@ version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +[[package]] +name = "libvhdl_conn" +version = "0.1.0" + [[package]] name = "log" version = "0.4.29" @@ -791,10 +795,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vhdl_ui" -version = "0.1.0" - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 5fb620f..08eb630 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,3 @@ [workspace] -members = ["conn", "relay"] \ No newline at end of file +members = ["libvhdl_conn", "relay"] +resolver = "3" \ No newline at end of file diff --git a/conn/.gitignore b/libvhdl_conn/.gitignore similarity index 100% rename from conn/.gitignore rename to libvhdl_conn/.gitignore diff --git a/conn/Cargo.lock b/libvhdl_conn/Cargo.lock similarity index 100% rename from conn/Cargo.lock rename to libvhdl_conn/Cargo.lock diff --git a/conn/Cargo.toml b/libvhdl_conn/Cargo.toml similarity index 84% rename from conn/Cargo.toml rename to libvhdl_conn/Cargo.toml index ec1b92a..1c3739e 100644 --- a/conn/Cargo.toml +++ b/libvhdl_conn/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "vhdl_ui" +name = "libvhdl_conn" version = "0.1.0" edition = "2024" diff --git a/conn/src/lib.rs b/libvhdl_conn/src/lib.rs similarity index 100% rename from conn/src/lib.rs rename to libvhdl_conn/src/lib.rs diff --git a/relay/build.rs b/relay/build.rs new file mode 100644 index 0000000..dda77d5 --- /dev/null +++ b/relay/build.rs @@ -0,0 +1,58 @@ +use std::path::PathBuf; +use std::process::Command; + +fn main() { + // silly hack of sorts because bindeps are unstable + + + let manifest_dir = PathBuf::from( + std::env::var("CARGO_MANIFEST_DIR") + .expect("CARGO_MANIFEST_DIR was not set by Cargo"), + ); + let workspace_root = manifest_dir + .parent() + .expect("relay crate should live under a workspace root"); + + println!("cargo:rerun-if-changed={}", workspace_root.join("conn").display()); + + let isolated_target_dir = workspace_root.join("target").join("conn-build"); + + let status = Command::new("cargo") + .arg("build") + .arg("--package") + .arg("libvhdl_conn") + .arg("--release") + .arg("--lib") + .arg("--target-dir") + .arg(&isolated_target_dir) + .current_dir(workspace_root) + .status() + .expect("failed to spawn cargo build for conn"); + + if !status.success() { + panic!( + "build script failed: `cargo build --package conn --release --lib` exited with {status}" + ); + } + + // Copy the built staticlib into the workspace release target path used by relay/src/build.rs. + let isolated_release_dir = isolated_target_dir.join("release"); + let out_release_dir = workspace_root.join("target").join("release"); + std::fs::create_dir_all(&out_release_dir).expect("failed to create workspace target/release"); + + // conn currently builds as libconn.a; keep a compatibility alias for relay/src/build.rs (libvhdl_ui.a). + let src_lib = isolated_release_dir.join("libconn.a"); + if !src_lib.exists() { + panic!( + "build script failed: expected static library not found at {}", + src_lib.display() + ); + } + + let dst_conn = out_release_dir.join("libvhdl_conn.a"); + std::fs::copy(&src_lib, &dst_conn).expect("failed to copy libconn.a into workspace target/release"); + + let dst_compat = out_release_dir.join("libvhdl_conn.a"); + std::fs::copy(&src_lib, &dst_compat) + .expect("failed to copy compatibility libvhdl_conn.a into workspace target/release"); +} diff --git a/relay/src/build.rs b/relay/src/build.rs index 064f434..f89c149 100644 --- a/relay/src/build.rs +++ b/relay/src/build.rs @@ -5,6 +5,9 @@ use tokio::process::{Child, Command}; use crate::HResult; +const EMBEDDED_VHDL_UI_LIB: &[u8] = + include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/../target/release/libvhdl_conn.a")); + async fn ensure_ok(child: Child) -> Result<(), Box> { let result = child.wait_with_output().await?; if !result.status.success() { @@ -73,6 +76,8 @@ pub async fn copy_and_build( pub async fn build(path: &Path, src: &Path) -> HResult<()>{ std::fs::create_dir_all(path)?; + let embedded_lib_path = path.join("libvhdl_conn.a"); + std::fs::write(&embedded_lib_path, EMBEDDED_VHDL_UI_LIB)?; let mut cmd = Command::new("ghdl"); cmd.kill_on_drop(true); @@ -102,7 +107,7 @@ pub async fn build(path: &Path, src: &Path) -> HResult<()>{ cmd.args(["-m", "--std=08"]); cmd.arg(format!( "-Wl,{}", - std::fs::canonicalize("../target/release/libvhdl_ui.a")?.display() + embedded_lib_path.display() )); cmd.arg("tb"); cmd.current_dir(path); @@ -112,4 +117,4 @@ pub async fn build(path: &Path, src: &Path) -> HResult<()>{ ensure_ok(cmd.spawn()?).await?; Ok(()) -} \ No newline at end of file +} diff --git a/relay/src/local.rs b/relay/src/local.rs index db7576f..5311190 100644 --- a/relay/src/local.rs +++ b/relay/src/local.rs @@ -30,7 +30,6 @@ struct Handler { build_dir: PathBuf, src_dir: PathBuf, - program: Option, process: Option, refresh_time: Duration, @@ -45,7 +44,6 @@ impl Handler { receiver, build_dir: build, src_dir: src, - program: None, process: None, refresh_time: Duration::from_millis(30), } @@ -186,10 +184,7 @@ impl Handler { match build::build(&self.build_dir, &self.src_dir).await { Ok(_) => {}, Err(err) => { - _ = self - .sender - .send(Message::Text(format!("Failed to build: {err}").into())) - .await; + _ = self.eprint(format!("Failed to build: {err}")).await; return; } }; diff --git a/relay/src/main.rs b/relay/src/main.rs index 263e6a2..6173288 100644 --- a/relay/src/main.rs +++ b/relay/src/main.rs @@ -1,29 +1,60 @@ use axum::{ Router, extract::ws::WebSocketUpgrade, + http::{StatusCode, header}, + response::{Html, IntoResponse}, routing::get, }; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; -use tower_http::services::ServeDir; pub mod build; pub mod run; pub mod local; pub mod remote; +const UI_INDEX_HTML: &str = include_str!("../ui/index.html"); +const UI_STYLES_CSS: &str = include_str!("../ui/styles.css"); +const UI_APP_JS: &str = include_str!("../ui/app.js"); + +async fn serve_index() -> impl IntoResponse { + Html(UI_INDEX_HTML) +} + +async fn serve_styles() -> impl IntoResponse { + ( + [(header::CONTENT_TYPE, "text/css; charset=utf-8")], + UI_STYLES_CSS, + ) +} + +async fn serve_app_js() -> impl IntoResponse { + ( + [(header::CONTENT_TYPE, "application/javascript; charset=utf-8")], + UI_APP_JS, + ) +} + +async fn not_found() -> impl IntoResponse { + (StatusCode::NOT_FOUND, "not found") +} + #[tokio::main] async fn main() { let app = Router::new() - .route( - "/ws/local", - get(|ws: WebSocketUpgrade| async move { ws.on_upgrade(remote::ws_handler) }), - ) + .route("/", get(serve_index)) + .route("/index.html", get(serve_index)) + .route("/styles.css", get(serve_styles)) + .route("/app.js", get(serve_app_js)) .route( "/ws/remote", get(|ws: WebSocketUpgrade| async move { ws.on_upgrade(local::ws_handler) }), ) - .fallback_service(ServeDir::new("ui")); + .route( + "/ws/local", + get(|ws: WebSocketUpgrade| async move { ws.on_upgrade(remote::ws_handler) }), + ) + .fallback(get(not_found)); let addr = SocketAddr::from(([127, 0, 0, 1], 8080)); println!("Open UI: http://{}/", addr); diff --git a/run_relay.sh b/run_relay.sh index 3d19296..6fceba8 100755 --- a/run_relay.sh +++ b/run_relay.sh @@ -1,10 +1,6 @@ #!/usr/bin/env bash set -euo pipefail -pushd conn >/dev/null -cargo build --release -popd >/dev/null - pushd relay >/dev/null cargo run --release -- "$@"