Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ mod caller_utils_generator;
mod caller_utils_ts_generator;
mod wit_generator;

// Default Rust toolchain to use for builds
pub const DEFAULT_RUST_TOOLCHAIN: &str = "+1.85.1";

const PY_VENV_NAME: &str = "process_env";
const JAVASCRIPT_SRC_PATH: &str = "src/lib.js";
const PYTHON_SRC_PATH: &str = "src/lib.py";
Expand Down Expand Up @@ -942,6 +945,7 @@ async fn compile_rust_wasm_process(
process_dir: &Path,
features: &str,
verbose: bool,
toolchain: &str,
) -> Result<()> {
let Some(package_dir) = process_dir.parent() else {
return Err(eyre!(
Expand Down Expand Up @@ -981,7 +985,7 @@ async fn compile_rust_wasm_process(

// Build the module using Cargo
let mut args = vec![
"+stable",
toolchain,
"build",
"-p",
&process_name,
Expand Down Expand Up @@ -1148,9 +1152,10 @@ async fn compile_package_item(
is_py_process: bool,
is_js_process: bool,
verbose: bool,
toolchain: String,
) -> Result<()> {
if is_rust_process {
compile_rust_wasm_process(&path, &features, verbose).await?;
compile_rust_wasm_process(&path, &features, verbose, &toolchain).await?;
} else if is_py_process {
let python = get_python_version(None, None)?
.ok_or_else(|| eyre!("kit requires Python 3.10 or newer"))?;
Expand Down Expand Up @@ -1209,6 +1214,7 @@ async fn fetch_dependencies(
hyperapp: bool,
force: bool,
verbose: bool,
toolchain: &str,
) -> Result<()> {
if let Err(e) = Box::pin(execute(
package_dir,
Expand All @@ -1229,6 +1235,7 @@ async fn fetch_dependencies(
force,
verbose,
true,
toolchain,
))
.await
{
Expand Down Expand Up @@ -1267,6 +1274,7 @@ async fn fetch_dependencies(
force,
verbose,
false,
toolchain,
))
.await?;
fetch_local_built_dependency(apis, wasm_paths, &local_dependency)?;
Expand Down Expand Up @@ -1453,6 +1461,7 @@ async fn check_and_populate_dependencies(
metadata: &Erc721Metadata,
skip_deps_check: bool,
verbose: bool,
toolchain: &str,
) -> Result<(HashMap<String, Vec<u8>>, HashSet<String>)> {
let mut checked_rust = false;
let mut checked_py = false;
Expand All @@ -1468,15 +1477,15 @@ async fn check_and_populate_dependencies(
let path = entry.path();
if path.is_dir() {
if path.join(RUST_SRC_PATH).exists() && !checked_rust && !skip_deps_check {
let deps = check_rust_deps()?;
get_deps(deps, &mut recv_kill, false, verbose).await?;
let deps = check_rust_deps(toolchain)?;
get_deps(deps, &mut recv_kill, false, verbose, toolchain).await?;
checked_rust = true;
} else if path.join(PYTHON_SRC_PATH).exists() && !checked_py {
check_py_deps()?;
checked_py = true;
} else if path.join(JAVASCRIPT_SRC_PATH).exists() && !checked_js && !skip_deps_check {
let deps = check_js_deps()?;
get_deps(deps, &mut recv_kill, false, verbose).await?;
get_deps(deps, &mut recv_kill, false, verbose, toolchain).await?;
checked_js = true;
} else if Some("api") == path.file_name().and_then(|s| s.to_str()) {
// read api files: to be used in build
Expand Down Expand Up @@ -1583,11 +1592,18 @@ async fn compile_package(
verbose: bool,
hyperapp_processed_projects: Option<Vec<PathBuf>>,
ignore_deps: bool, // for internal use; may cause problems when adding recursive deps
toolchain: &str,
) -> Result<()> {
let metadata = read_and_update_metadata(package_dir)?;
let mut wasm_paths = HashSet::new();
let (mut apis, dependencies) =
check_and_populate_dependencies(package_dir, &metadata, skip_deps_check, verbose).await?;
let (mut apis, dependencies) = check_and_populate_dependencies(
package_dir,
&metadata,
skip_deps_check,
verbose,
toolchain,
)
.await?;

info!("dependencies: {dependencies:?}");
if !ignore_deps && !dependencies.is_empty() {
Expand All @@ -1608,6 +1624,7 @@ async fn compile_package(
hyperapp,
force,
verbose,
toolchain,
)
.await?
}
Expand Down Expand Up @@ -1664,6 +1681,7 @@ async fn compile_package(
is_py_process,
is_js_process,
verbose.clone(),
toolchain.to_string(),
));
}
while let Some(res) = tasks.join_next().await {
Expand Down Expand Up @@ -1747,6 +1765,7 @@ pub async fn execute(
force: bool,
verbose: bool,
ignore_deps: bool, // for internal use; may cause problems when adding recursive deps
toolchain: &str,
) -> Result<()> {
debug!(
"execute:
Expand Down Expand Up @@ -1858,7 +1877,7 @@ pub async fn execute(
if !skip_deps_check {
let mut recv_kill = make_fake_kill_chan();
let deps = check_js_deps()?;
get_deps(deps, &mut recv_kill, false, verbose).await?;
get_deps(deps, &mut recv_kill, false, verbose, DEFAULT_RUST_TOOLCHAIN).await?;
}
let valid_node = get_newest_valid_node_version(None, None)?;
for ui_dir in ui_dirs {
Expand All @@ -1884,6 +1903,7 @@ pub async fn execute(
verbose,
hyperapp_processed_projects,
ignore_deps,
toolchain,
)
.await?;
}
Expand Down
2 changes: 2 additions & 0 deletions src/build_start_package/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub async fn execute(
reproducible: bool,
force: bool,
verbose: bool,
toolchain: &str,
) -> Result<()> {
build::execute(
package_dir,
Expand All @@ -46,6 +47,7 @@ pub async fn execute(
force,
verbose,
false,
toolchain,
)
.await?;
start_package::execute(package_dir, url).await?;
Expand Down
10 changes: 9 additions & 1 deletion src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use reqwest::Client;
use tokio::time::{sleep, Duration};
use tracing::{debug, info, instrument};

use crate::build;
use crate::run_tests::cleanup::{clean_process_by_pid, cleanup_on_signal};
use crate::run_tests::types::BroadcastRecvBool;
use crate::setup::{check_foundry_deps, get_deps};
Expand Down Expand Up @@ -257,7 +258,14 @@ pub async fn start_chain(
tracing: bool,
) -> Result<Option<Child>> {
let deps = check_foundry_deps()?;
get_deps(deps, &mut recv_kill, false, verbose).await?;
get_deps(
deps,
&mut recv_kill,
false,
verbose,
build::DEFAULT_RUST_TOOLCHAIN,
)
.await?;

info!("Checking for Anvil on port {}...", port);
if wait_for_anvil(port, 1, None).await.is_ok() {
Expand Down
4 changes: 2 additions & 2 deletions src/dev_ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::process::Command;
use color_eyre::{eyre::eyre, Result};
use tracing::{info, instrument};

use crate::build::{make_fake_kill_chan, run_command};
use crate::build::{make_fake_kill_chan, run_command, DEFAULT_RUST_TOOLCHAIN};
use crate::setup::{check_js_deps, get_deps, get_newest_valid_node_version};

#[instrument(level = "trace", skip_all)]
Expand All @@ -17,7 +17,7 @@ pub async fn execute(
if !skip_deps_check {
let deps = check_js_deps()?;
let mut recv_kill = make_fake_kill_chan();
get_deps(deps, &mut recv_kill, false, false).await?;
get_deps(deps, &mut recv_kill, false, false, DEFAULT_RUST_TOOLCHAIN).await?;
}
let valid_node = get_newest_valid_node_version(None, None)?;

Expand Down
55 changes: 55 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,31 @@ fn parse_u128_with_underscores(s: &str) -> Result<u128, &'static str> {
.map_err(|_| "Invalid number format")
}

#[instrument(level = "trace", skip_all)]
fn parse_rust_toolchain(s: &str) -> Result<String, &'static str> {
// Validate the format: must start with '+' followed by version or channel name
if !s.starts_with('+') {
return Err("Rust toolchain must start with '+' (e.g., '+stable', '+1.85.1', '+nightly')");
}

let toolchain = &s[1..];

// Check if it's a valid channel name or version format
if toolchain.is_empty() {
return Err("Rust toolchain cannot be empty after '+'");
}

// Basic validation: alphanumeric, dots, dashes, and hyphens are allowed
if !toolchain
.chars()
.all(|c| c.is_alphanumeric() || c == '.' || c == '-' || c == '_')
{
return Err("Invalid characters in Rust toolchain specification");
}

Ok(s.to_string())
}

#[instrument(level = "trace", skip_all)]
async fn get_latest_commit_sha_from_branch(
owner: &str,
Expand Down Expand Up @@ -247,6 +272,7 @@ async fn execute(
let reproducible = matches.get_one::<bool>("REPRODUCIBLE").unwrap();
let force = matches.get_one::<bool>("FORCE").unwrap();
let verbose = matches.get_one::<bool>("VERBOSE").unwrap();
let toolchain = matches.get_one::<String>("TOOLCHAIN").unwrap();

build::execute(
&package_dir,
Expand All @@ -267,6 +293,7 @@ async fn execute(
*force,
*verbose,
false,
toolchain,
)
.await
}
Expand Down Expand Up @@ -312,6 +339,7 @@ async fn execute(
let reproducible = matches.get_one::<bool>("REPRODUCIBLE").unwrap();
let force = matches.get_one::<bool>("FORCE").unwrap();
let verbose = matches.get_one::<bool>("VERBOSE").unwrap();
let toolchain = matches.get_one::<String>("TOOLCHAIN").unwrap();

build_start_package::execute(
&package_dir,
Expand All @@ -331,6 +359,7 @@ async fn execute(
*reproducible,
*force,
*verbose,
toolchain,
)
.await
}
Expand Down Expand Up @@ -473,6 +502,7 @@ async fn execute(
let foundry_optional = matches.get_one::<bool>("FOUNDRY_OPTIONAL").unwrap();
let javascript_optional = matches.get_one::<bool>("JAVASCRIPT_OPTIONAL").unwrap();
let non_interactive = matches.get_one::<bool>("NON_INTERACTIVE").unwrap();
let toolchain = matches.get_one::<String>("TOOLCHAIN").unwrap();

let mut recv_kill = build::make_fake_kill_chan();
setup::execute(
Expand All @@ -483,6 +513,7 @@ async fn execute(
*javascript_optional,
*non_interactive,
*verbose,
toolchain,
)
.await
}
Expand Down Expand Up @@ -829,6 +860,14 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.help("If set, output stdout and stderr")
.required(false)
)
.arg(Arg::new("TOOLCHAIN")
.action(ArgAction::Set)
.long("toolchain")
.help("Rust toolchain to use (e.g., '+stable', '+1.85.1', '+nightly')")
.default_value(build::DEFAULT_RUST_TOOLCHAIN)
.value_parser(clap::builder::ValueParser::new(parse_rust_toolchain))
.required(false)
)
)
.subcommand(Command::new("build-start-package")
.about("Build and start a Hyperware package")
Expand Down Expand Up @@ -942,6 +981,14 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.help("If set, output stdout and stderr")
.required(false)
)
.arg(Arg::new("TOOLCHAIN")
.action(ArgAction::Set)
.long("toolchain")
.help("Rust toolchain to use (e.g., '+stable', '+1.85.1', '+nightly')")
.default_value(build::DEFAULT_RUST_TOOLCHAIN)
.value_parser(clap::builder::ValueParser::new(parse_rust_toolchain))
.required(false)
)
)
.subcommand(Command::new("chain")
.about("Start a local chain for development")
Expand Down Expand Up @@ -1297,6 +1344,14 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result<Command> {
.help("If set, do not prompt and instead always reply `Y` to prompts (i.e. automatically install dependencies without user input)")
.required(false)
)
.arg(Arg::new("TOOLCHAIN")
.action(ArgAction::Set)
.long("toolchain")
.help("Rust toolchain to use (e.g., '+stable', '+1.85.1', '+nightly')")
.default_value(build::DEFAULT_RUST_TOOLCHAIN)
.value_parser(clap::builder::ValueParser::new(parse_rust_toolchain))
.required(false)
)
)
.subcommand(Command::new("start-package")
.about("Start a built Hyprware package")
Expand Down
5 changes: 4 additions & 1 deletion src/run_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use tracing::{debug, info, instrument};
use hyperware_process_lib::kernel_types::PackageManifestEntry;

use crate::boot_fake_node;
use crate::build;
use crate::build::{self, DEFAULT_RUST_TOOLCHAIN};
use crate::chain;
use crate::inject_message;
use crate::start_package;
Expand Down Expand Up @@ -382,6 +382,7 @@ async fn build_packages(
false,
false,
false,
DEFAULT_RUST_TOOLCHAIN,
)
.await?;
debug!("Start {path:?}");
Expand All @@ -408,6 +409,7 @@ async fn build_packages(
false,
false,
false,
DEFAULT_RUST_TOOLCHAIN,
)
.await?;
}
Expand All @@ -431,6 +433,7 @@ async fn build_packages(
false,
false,
false,
DEFAULT_RUST_TOOLCHAIN,
)
.await?;
}
Expand Down
Loading