spacetimedb_cli/subcommands/
build.rs

1use crate::Config;
2use clap::ArgAction::SetTrue;
3use clap::{Arg, ArgMatches};
4use std::ffi::OsString;
5use std::path::{Path, PathBuf};
6
7pub fn cli() -> clap::Command {
8    clap::Command::new("build")
9        .about("Builds a spacetime module.")
10        .arg(
11            Arg::new("project_path")
12                .long("project-path")
13                .short('p')
14                .value_parser(clap::value_parser!(PathBuf))
15                .default_value(".")
16                .help("The system path (absolute or relative) to the project you would like to build")
17        )
18        .arg(
19            Arg::new("lint_dir")
20                .long("lint-dir")
21                .value_parser(clap::value_parser!(OsString))
22                .default_value("src")
23                .help("The directory to lint for nonfunctional print statements. If set to the empty string, skips linting.")
24        )
25        .arg(
26            Arg::new("debug")
27                .long("debug")
28                .short('d')
29                .action(SetTrue)
30                .help("Builds the module using debug instead of release (intended to speed up local iteration, not recommended for CI)"),
31        )
32}
33
34pub async fn exec(_config: Config, args: &ArgMatches) -> Result<PathBuf, anyhow::Error> {
35    let project_path = args.get_one::<PathBuf>("project_path").unwrap();
36    let lint_dir = args.get_one::<OsString>("lint_dir").unwrap();
37    let lint_dir = if lint_dir.is_empty() {
38        None
39    } else {
40        Some(PathBuf::from(lint_dir))
41    };
42    let build_debug = args.get_flag("debug");
43
44    // Create the project path, or make sure the target project path is empty.
45    if project_path.exists() {
46        if !project_path.is_dir() {
47            return Err(anyhow::anyhow!(
48                "Fatal Error: path {} exists but is not a directory.",
49                project_path.display()
50            ));
51        }
52    } else {
53        return Err(anyhow::anyhow!(
54            "Fatal Error: path {} does not exist.",
55            project_path.display()
56        ));
57    }
58
59    let bin_path = crate::tasks::build(project_path, lint_dir.as_deref(), build_debug)?;
60    println!("Build finished successfully.");
61
62    Ok(bin_path)
63}
64
65pub async fn exec_with_argstring(
66    config: Config,
67    project_path: &Path,
68    arg_string: &str,
69) -> Result<PathBuf, anyhow::Error> {
70    // Note: "build" must be the start of the string, because `build::cli()` is the entire build subcommand.
71    // If we don't include this, the args will be misinterpreted (e.g. as commands).
72    let arg_string = format!("build {} --project-path {}", arg_string, project_path.display());
73    let arg_matches = cli().get_matches_from(arg_string.split_whitespace());
74    exec(config.clone(), &arg_matches).await
75}