diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fae0d91d94..6cc9094f36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: generate pac - run: cargo run --manifest-path=xtask/Cargo.toml -- --generate-only ${{ matrix.chip }} + run: cargo run --manifest-path=xtask/Cargo.toml -- generate ${{ matrix.chip }} - name: build pac run: cd ${{ matrix.chip }} && cargo check --all-targets @@ -62,7 +62,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: generate pac - run: cargo run --manifest-path=xtask/Cargo.toml -- --generate-only ${{ matrix.chip }} + run: cargo run --manifest-path=xtask/Cargo.toml -- generate ${{ matrix.chip }} - name: build pac run: cd ${{ matrix.chip }} && cargo check --all-targets @@ -90,7 +90,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: generate pac - run: cargo +nightly run --manifest-path=xtask/Cargo.toml -- --generate-only ${{ matrix.chip }} + run: cargo +nightly run --manifest-path=xtask/Cargo.toml -- generate ${{ matrix.chip }} - name: build pac run: cd ${{ matrix.chip }} && cargo +1.65.0 check --all-targets @@ -113,6 +113,6 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: generate pac - run: cargo run --manifest-path=xtask/Cargo.toml -- --generate-only ${{ matrix.chip }} + run: cargo run --manifest-path=xtask/Cargo.toml -- generate ${{ matrix.chip }} - name: build pac run: cd ${{ matrix.chip }} && cargo check --all-targets diff --git a/README.md b/README.md index 86a7f92d08..8b8396bcb7 100644 --- a/README.md +++ b/README.md @@ -35,24 +35,26 @@ If you submit a pull request we kindly ask that you keep the patches and generat ## Generating the PACs -We use the workflow described by [cargo-xtask] to automate tasks within this monorepo. Currently there is only a single task which generates a Peripheral Access Crate (PAC) for the specified chip(s). We've opted not to use the `cargo xtask` alias, as this requires a workspace which can cause problems when using different toolchains and targets like we are. +We use the workflow described by [cargo-xtask] to automate tasks within this monorepo. We've opted not to use the `cargo xtask` alias as this requires a workspace, which can cause problems when using different toolchains and targets like we are. ```text -Usage: xtask [OPTIONS] [CHIPS]... +Usage: xtask -Arguments: - [CHIPS]... Chip(s) to target [possible values: esp32, esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3, esp8266] +Commands: + patch Patch the specified package(s)'s SVD file + generate Generate the specified package(s) + build Build the specified package(s) + bump-version Bump the version of the specified package(s) + help Print this message or the help of the given subcommand(s) Options: - -p, --patch-only Only patch the SVD, do not generate or build the PAC - -g, --generate-only Patch the SVD and generate the PAC, but do not build it - -h, --help Print help + -h, --help Print help ``` For example, to generate a PAC for the ESP32-C3 _without_ subsequently building the crate, from within the `xtask/` directory run: ```shell -$ cargo run -- --generate-only esp32c3 +$ cargo run -- generate esp32c3 ``` [cargo-xtask]: https://github.com/matklad/cargo-xtask/ diff --git a/xtask/Cargo.lock b/xtask/Cargo.lock index 41086ba71b..d174cebf7a 100644 --- a/xtask/Cargo.lock +++ b/xtask/Cargo.lock @@ -11,11 +11,20 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" dependencies = [ "anstyle", "anstyle-parse", @@ -52,9 +61,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", "windows-sys", @@ -62,9 +71,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "atty" @@ -91,9 +100,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bstr" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" dependencies = [ "memchr", "serde", @@ -113,9 +122,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.2.4" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62" +checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" dependencies = [ "clap_builder", "clap_derive", @@ -124,9 +133,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.4" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749" +checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" dependencies = [ "anstream", "anstyle", @@ -138,21 +147,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "colorchoice" @@ -258,7 +267,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -354,9 +363,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "linked-hash-map" @@ -366,9 +375,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "log" @@ -402,9 +411,9 @@ checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" dependencies = [ "unicode-ident", ] @@ -421,29 +430,29 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.7.3" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.1", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "roxmltree" @@ -456,9 +465,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.12" +version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "722529a737f5a942fdbac3a46cee213053196737c5eaa3386d52e85b786f2659" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ "bitflags", "errno", @@ -480,24 +489,30 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -512,15 +527,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" -dependencies = [ - "serde", -] - [[package]] name = "serde_yaml" version = "0.8.26" @@ -653,9 +659,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", @@ -688,39 +694,22 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", -] - -[[package]] -name = "toml" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", + "syn 2.0.16", ] [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" -dependencies = [ - "serde", -] +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" dependencies = [ "indexmap", - "serde", - "serde_spanned", "toml_datetime", "winnow", ] @@ -854,18 +843,18 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" dependencies = [ "memchr", ] [[package]] name = "xml-rs" -version = "0.8.4" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" +checksum = "1690519550bfa95525229b9ca2350c63043a4857b3b0013811b2ccf4a2420b01" [[package]] name = "xmlparser" @@ -892,10 +881,11 @@ dependencies = [ "env_logger 0.10.0", "form", "log", + "semver", "strum", "svd2rust", "svdtools", - "toml", + "toml_edit", ] [[package]] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 852e8df05c..4ad659fa87 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -5,15 +5,16 @@ edition = "2021" publish = false [dependencies] -anyhow = "1.0.70" -clap = { version = "4.2.4", features = ["derive"] } +anyhow = "1.0.71" +clap = { version = "4.2.7", features = ["derive"] } env_logger = "0.10.0" form = "0.10.0" log = "0.4.17" +semver = "1.0.17" strum = { version = "0.24.1", features = ["derive"] } svd2rust = { version = "0.28.0", default-features = false } svdtools = "0.3.0" -toml = "0.7.3" +toml_edit = "0.19.9" [patch.crates-io] svd2rust = { git = "https://github.com/rust-embedded/svd2rust.git", rev = "e6a6d150e480808b870a33a9032d25e3343bb656" } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 512fb6790b..b519fe1729 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -7,15 +7,12 @@ use std::{ }; use anyhow::{Error, Result}; -use clap::{Parser, ValueEnum}; -use form::util::create_directory_structure; -use log::{info, warn, LevelFilter}; -use strum::{Display, EnumIter, EnumString, IntoEnumIterator}; -use svd2rust::{generate::device::render, load_from, util::build_rs, Config, Target}; -use svdtools::patch::process_file; -use toml::Value; - -#[derive(Debug, Clone, Display, EnumIter, EnumString, ValueEnum)] +use clap::{Parser, Subcommand, ValueEnum}; +use strum::{Display, EnumIter, IntoEnumIterator}; +use svd2rust::{Config, Target}; +use toml_edit::Document; + +#[derive(Debug, Clone, Display, EnumIter, ValueEnum)] #[strum(serialize_all = "lowercase")] enum Chip { Esp32, @@ -28,88 +25,119 @@ enum Chip { Esp8266, } +#[derive(Debug, Clone, Copy, Display, ValueEnum)] +#[strum(serialize_all = "lowercase")] +enum Version { + Major, + Minor, + Patch, +} + #[derive(Debug, Parser)] struct Cli { - /// Chip(s) to target - #[clap(value_enum)] - chips: Vec, - /// Only patch the SVD, do not generate or build the PAC - #[clap(short, long, conflicts_with = "generate_only")] - patch_only: bool, - /// Patch the SVD and generate the PAC, but do not build it - #[clap(short, long, conflicts_with = "patch_only")] - generate_only: bool, + #[command(subcommand)] + command: Commands, +} + +#[derive(Debug, Subcommand)] +enum Commands { + /// Patch the specified package(s)'s SVD file + Patch { + /// Chip(s) to target + #[clap(value_enum, default_values_t = Chip::iter())] + chips: Vec, + }, + + /// Generate the specified package(s) + /// + /// Additionally patches the releavant SVD(s) prior to generating the + /// package(s). + Generate { + /// Chip(s) to target + #[clap(value_enum, default_values_t = Chip::iter())] + chips: Vec, + }, + + /// Build the specified package(s) + /// + /// Additionally patches the relevant SVD(s) and generates the relevant + /// package(s) prior to building the package(s). + Build { + /// Chip(s) to target + #[clap(value_enum, default_values_t = Chip::iter())] + chips: Vec, + }, + + /// Bump the version of the specified package(s) + BumpVersion { + /// How much to bump the version + #[clap(value_enum)] + amount: Version, + /// Chip(s) to target + #[clap(value_enum, default_values_t = Chip::iter())] + chips: Vec, + }, } fn main() -> Result<()> { env_logger::Builder::new() - .filter_module("xtask", LevelFilter::Info) + .filter_module("xtask", log::LevelFilter::Info) .init(); - let args = Cli::parse(); - // The directory containing the cargo manifest for the 'xtask' package is a // subdirectory within the cargo workspace. let workspace = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let workspace = workspace.parent().unwrap().canonicalize()?; - // One or more chips can be specified as command-line arguments. If none are - // provided then the task will be run for all chips. - let chips = if !args.chips.is_empty() { - args.chips.iter().map(|c| c.to_string()).collect::>() - } else { - Chip::iter().map(|c| c.to_string()).collect::>() - }; - - for chip in chips { - info!("chip: {chip}"); - let path = workspace.join(&chip); - - // Always patch the SVD upon execution. If '--patch-only' has NOT been set, then - // additionally generate and format the PAC. If '--generate-only' has NOT been - // set, clean and build the PAC crate. - patch_svd(&chip, &path)?; - - if !args.patch_only { - // Remove the src/ directory before we generate. If this fails we will assume - // it's because the directory does not exist. - if fs::remove_dir_all(&path.join("src")).is_err() { - warn!("unable to remove 'src/' directory"); - } - - generate_pac(&chip, &path)?; - format(&path)?; - - if !args.generate_only { - clean(&path)?; - build(&path)?; - } - } - - info!("finished with {chip}") + match Cli::parse().command { + Commands::Patch { chips } => chips + .iter() + .try_for_each(|chip| patch_svd(&workspace, chip)), + Commands::Generate { chips } => chips + .iter() + .try_for_each(|chip: &Chip| generate_package(&workspace, chip)), + Commands::Build { chips } => chips + .iter() + .try_for_each(|chip| build_package(&workspace, chip)), + Commands::BumpVersion { + chips, + amount: version, + } => chips + .iter() + .try_for_each(|chip| bump_version(&workspace, chip, version)), } - - Ok(()) } -fn patch_svd(chip: &str, path: &Path) -> Result<()> { - let svd_path = path.join("svd"); +fn patch_svd(workspace: &Path, chip: &Chip) -> Result<()> { + log::info!("applying patches to SVD file for {chip}"); + + let svd_path = workspace.join(chip.to_string()).join("svd"); let yaml_file = svd_path.join("patches").join(format!("{chip}.yaml")); - process_file(&yaml_file)?; + svdtools::patch::process_file(&yaml_file)?; let from = svd_path.join(format!("{chip}.base.svd.patched")); let to = svd_path.join(format!("{chip}.svd")); - info!("applying patches to SVD file"); fs::rename(from, to)?; Ok(()) } -fn generate_pac(chip: &str, path: &Path) -> Result<()> { +fn generate_package(workspace: &Path, chip: &Chip) -> Result<()> { + // Patch the SVD prior to generating the package: + patch_svd(workspace, chip)?; + + let path = workspace.join(chip.to_string()); + + // Remove the src/ directory before we generate. If this fails we will assume + // it's because the directory does not exist. + if fs::remove_dir_all(path.join("src")).is_err() { + log::warn!("unable to remove 'src/' directory"); + } + let svd_file = path.join("svd").join(format!("{chip}.svd")); - info!("generating PAC from '{}'", svd_file.display()); + log::info!("generating PAC from '{}'", svd_file.display()); - let target = if get_build_target(path)?.contains("riscv") { + let target = if build_target(&path)?.contains("riscv") { Target::RISCV } else { Target::XtensaLX @@ -117,7 +145,7 @@ fn generate_pac(chip: &str, path: &Path) -> Result<()> { let config = Config { target, - output_dir: path.to_path_buf(), + output_dir: path.clone(), const_generic: true, ..match target { @@ -130,10 +158,10 @@ fn generate_pac(chip: &str, path: &Path) -> Result<()> { }; let input = fs::read_to_string(svd_file)?; - let device = load_from(&input, &config)?; + let device = svd2rust::load_from(&input, &config)?; let mut device_x = String::new(); - let items = render(&device, &config, &mut device_x)?; + let items = svd2rust::generate::device::render(&device, &config, &mut device_x)?; let data = items.to_string(); // Here we will sneakily patch in our own logo for the documentation :) @@ -146,43 +174,28 @@ fn generate_pac(chip: &str, path: &Path) -> Result<()> { file.write_all(data.as_ref())?; writeln!(File::create(path.join("device.x"))?, "{}", device_x)?; - writeln!(File::create(path.join("build.rs"))?, "{}", build_rs())?; + writeln!( + File::create(path.join("build.rs"))?, + "{}", + svd2rust::util::build_rs() + )?; - Ok(()) -} - -fn format(path: &PathBuf) -> Result<()> { - info!("running `form` and `rustfmt` on PAC"); - let lib_file = path.join("lib.rs"); - - let base_dir = path.join("src"); - let string_contents = fs::read_to_string(&lib_file)?; - create_directory_structure(base_dir, &string_contents).map_err(Error::msg)?; - - fs::remove_file(&lib_file)?; - - Command::new("cargo") - .arg("fmt") - .current_dir(path) - .output()?; + format(&path)?; Ok(()) } -fn clean(path: &PathBuf) -> Result<()> { - Command::new("cargo") - .arg("clean") - .current_dir(path) - .output()?; +fn build_package(workspace: &Path, chip: &Chip) -> Result<()> { + // Patch the SVD and generate the package prior to building: + generate_package(workspace, chip)?; - Ok(()) -} + let path = workspace.join(chip.to_string()); + clean(&path)?; -fn build(path: &PathBuf) -> Result<()> { - let channel = get_release_channel(path)?; - let target = get_build_target(path)?; + let channel = release_channel(&path)?; + let target = build_target(&path)?; - info!("building PAC using '{channel}' channel and targeting '{target}'"); + log::info!("building PAC using '{channel}' channel and targeting '{target}'"); Command::new("cargo") .args([ &format!("+{channel}"), @@ -200,30 +213,94 @@ fn build(path: &PathBuf) -> Result<()> { Ok(()) } -fn get_release_channel(path: &Path) -> Result { - let toolchain_file = path.join("rust-toolchain.toml"); - let channel = extract_toml_value(&toolchain_file, &["toolchain", "channel"])?; +fn bump_version(workspace: &Path, chip: &Chip, amount: Version) -> Result<()> { + let path = workspace.join(chip.to_string()); + + let manifest_path = path.join("Cargo.toml"); + let manifest = fs::read_to_string(&manifest_path)?; + let mut manifest = manifest.parse::()?; + + let version = manifest["package"]["version"] + .to_string() + .trim() + .trim_matches('"') + .to_string(); + let prev_version = &version; + + let mut version = semver::Version::parse(&version)?; + match amount { + Version::Major => { + version.major += 1; + version.minor = 0; + version.patch = 0; + } + Version::Minor => { + version.minor += 1; + version.patch = 0; + } + Version::Patch => { + version.patch += 1; + } + } - Ok(channel) + log::info!("bumping version for package: {chip} ({prev_version} -> {version})"); + manifest["package"]["version"] = toml_edit::value(version.to_string()); + fs::write(manifest_path, manifest.to_string())?; + + Ok(()) } -fn get_build_target(path: &Path) -> Result { +fn build_target(path: &Path) -> Result { let config_file = path.join(".cargo").join("config.toml"); let target = extract_toml_value(&config_file, &["build", "target"])?; Ok(target) } +fn release_channel(path: &Path) -> Result { + let toolchain_file = path.join("rust-toolchain.toml"); + let channel = extract_toml_value(&toolchain_file, &["toolchain", "channel"])?; + + Ok(channel) +} + fn extract_toml_value(path: &Path, keys: &[&str]) -> Result { let contents = fs::read_to_string(path)?; - let value = contents.parse::()?; + let document = contents.parse::()?; - let mut item = &value; + let mut item = document.as_item(); for key in keys { - item = item.get(key).unwrap(); + item = item.as_table().unwrap().get(key).unwrap(); } - let item = item.to_string().replace('\"', ""); + let item = item.to_string().trim().replace('"', ""); Ok(item) } + +fn format(path: &Path) -> Result<()> { + log::info!("running `form` and `rustfmt` on PAC"); + let lib_file = path.join("lib.rs"); + + let base_dir = path.join("src"); + let string_contents = fs::read_to_string(&lib_file)?; + form::create_directory_structure(base_dir, &string_contents).map_err(Error::msg)?; + + fs::remove_file(&lib_file)?; + + Command::new("cargo") + .arg("fmt") + .current_dir(path) + .output()?; + + Ok(()) +} + +fn clean(path: &Path) -> Result<()> { + Command::new("cargo") + .arg("clean") + .current_dir(path) + .output()?; + + Ok(()) +}