Skip to main content

xtask_lib/tasks/
setup.rs

1//! `cargo xtask setup` — build thirdparty dependencies that must be
2//! ready before `cargo build` runs.
3//!
4//! Currently this covers SQLite only: `libsqlite3-sys`'s own build
5//! script runs before `cadmus-core`'s build.rs, so the custom SQLite
6//! library (built with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`) must
7//! already be on disk and pointed to by `SQLITE3_LIB_DIR` /
8//! `SQLITE3_INCLUDE_DIR`.
9//!
10//! ## Usage
11//!
12//! ```text
13//! cargo xtask setup           # build for all known targets (host + Kobo)
14//! cargo xtask setup --host    # build for the native host only
15//! cargo xtask setup --kobo    # build for Kobo (ARM) only
16//! cargo xtask setup --all     # explicitly build for all known targets
17//! cargo xtask setup --target <triple>  # build for an arbitrary target
18//! ```
19//!
20//! After running, set the printed environment variables before
21//! `cargo build` or `cargo xtask build-kobo`.
22
23use anyhow::{Context, Result};
24use clap::Args;
25
26use build_deps::build::sqlite;
27
28use super::util::workspace;
29
30/// Arguments for `cargo xtask setup`.
31#[derive(Debug, Args)]
32pub struct SetupArgs {
33    /// Build for the native host target only.
34    #[arg(long)]
35    pub host: bool,
36
37    /// Build for the Kobo ARM target only.
38    #[arg(long)]
39    pub kobo: bool,
40
41    /// Build for all known targets (host + Kobo). Implied when no
42    /// flags are passed.
43    #[arg(long)]
44    pub all: bool,
45
46    /// Build for an arbitrary target triple (advanced).
47    #[arg(long)]
48    pub target: Option<String>,
49}
50
51/// Build thirdparty dependencies that must exist before `cargo build`.
52///
53/// When no target flags are supplied the default is `--all`, which
54/// builds for every known target (native host + Kobo ARM).
55///
56/// # Errors
57///
58/// Returns an error if:
59/// - Git submodules cannot be initialised.
60/// - TCL is not installed (required for SQLite amalgamation generation).
61/// - The SQLite build fails.
62pub fn run(args: SetupArgs) -> Result<()> {
63    let root = workspace::root()?;
64
65    build_deps::ensure_submodules(&root).context("failed to initialise git submodules")?;
66
67    let targets = resolve_targets(&args);
68
69    for target in &targets {
70        let artifacts = sqlite::ensure_sqlite(&root, target).context("failed to build sqlite")?;
71
72        println!();
73        println!("SQLite artifacts ready for {target}:");
74        println!("  export SQLITE3_LIB_DIR={}", artifacts.lib_dir.display());
75        println!(
76            "  export SQLITE3_INCLUDE_DIR={}",
77            artifacts.include_dir.display()
78        );
79        println!("  export SQLITE3_STATIC=1");
80    }
81
82    Ok(())
83}
84
85/// Determine which target triples to build based on CLI flags.
86///
87/// `--target` takes precedence; otherwise `--host` / `--kobo` select
88/// individual targets. When none are given `--all` is implied.
89fn resolve_targets(args: &SetupArgs) -> Vec<String> {
90    if let Some(ref t) = args.target {
91        return vec![t.clone()];
92    }
93
94    let build_all = args.all || (!args.host && !args.kobo);
95
96    let mut targets = Vec::new();
97    if build_all || args.host {
98        targets.push(guess_host_triple());
99    }
100    if build_all || args.kobo {
101        targets.push(sqlite::KOBO_TARGET.to_string());
102    }
103    targets
104}
105
106/// Best-effort detection of the host target triple.
107#[must_use]
108fn guess_host_triple() -> String {
109    std::env::var("TARGET").unwrap_or_else(|_| {
110        if cfg!(target_arch = "x86_64") && cfg!(target_os = "linux") {
111            "x86_64-unknown-linux-gnu".to_string()
112        } else if cfg!(target_arch = "aarch64") && cfg!(target_os = "linux") {
113            "aarch64-unknown-linux-gnu".to_string()
114        } else if cfg!(target_arch = "x86_64") && cfg!(target_os = "macos") {
115            "x86_64-apple-darwin".to_string()
116        } else if cfg!(target_arch = "aarch64") && cfg!(target_os = "macos") {
117            "aarch64-apple-darwin".to_string()
118        } else {
119            "x86_64-unknown-linux-gnu".to_string()
120        }
121    })
122}