From 5f285d1113a9a11521305904440a7e49ce812f9d Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 25 Oct 2024 04:05:05 -0700 Subject: [PATCH] Add an `xtask` package to simplify our CI workflow (#22) * Add an option to specify the output directory of the generated project * Remove the `stack-protector` option * Add an `xtask` package to simplify our CI workflow * Update the CI workflow to use `xtask` package and run tests * Remove extraneous HAL initialization from `async_main` * Use `stable` release channel for running tests * Fix a typo in `README.md` --- .github/workflows/ci.yml | 59 ++-- README.md | 31 ++- src/main.rs | 29 +- template/.cargo/config.toml | 3 - template/rust-toolchain.toml | 6 +- template/src/bin/async_main.rs | 2 - xtask/Cargo.lock | 478 +++++++++++++++++++++++++++++++++ xtask/Cargo.toml | 13 + xtask/src/main.rs | 147 ++++++++++ 9 files changed, 691 insertions(+), 77 deletions(-) create mode 100644 xtask/Cargo.lock create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 603b9e4..a5fbefb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,42 +24,19 @@ concurrency: jobs: verify: - name: "${{ matrix.chip }} | ${{ matrix.options }}" - + name: "Check ${{ matrix.chip }}" runs-on: ubuntu-latest strategy: fail-fast: false matrix: - chip: [ - "esp32", - "esp32c2", - "esp32c3", - "esp32c6", - "esp32h2", - "esp32s2", - "esp32s3", - ] - options: [ - "", - "-o alloc", - "-o wifi -o alloc", - "-o ble -o alloc", - "-o embassy", - "-o probe-rs", - "-o stack-protector" - ] - # Exclude some combinations that are not supported - exclude: - - chip: "esp32h2" - options: "-o wifi -o alloc" - - chip: "esp32s2" - options: "-o ble -o alloc" + chip: [esp32, esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3] + steps: - uses: actions/checkout@v4 # Rust toolchain for Xtensa: - - if: matrix.chip == 'esp32' || matrix.chip == 'esp32s2' || matrix.chip == 'esp32s3' + - if: ${{ contains(fromJson('["esp32", "esp32s2", "esp32s3"]'), matrix.chip) }} uses: esp-rs/xtensa-toolchain@v1.5 with: default: true @@ -67,27 +44,23 @@ jobs: ldproxy: false # Rust toolchain for RISC-V: - - if: matrix.chip != 'esp32' && matrix.chip != 'esp32s2' && matrix.chip != 'esp32s3' + - if: ${{ !contains(fromJson('["esp32", "esp32s2", "esp32s3"]'), matrix.chip) }} uses: dtolnay/rust-toolchain@stable with: target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf components: clippy,rustfmt,rust-src - # Rust toolchain for RISC-V: - - if: matrix.chip != 'esp32' && matrix.chip != 'esp32s2' && matrix.chip != 'esp32s3' && matrix.options == '-o stack-protector' - uses: dtolnay/rust-toolchain@nightly - with: - target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf - components: clippy,rustfmt,rust-src - - uses: Swatinem/rust-cache@v2 - - name: Generate project - run: cargo run --release -- --chip ${{ matrix.chip }} --headless ${{ matrix.options }} test + - name: Generate and check project + run: cd xtask && cargo run -- check ${{ matrix.chip }} + + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable - - name: Build and check the project - working-directory: test - run: | - cargo fmt -- --check - cargo clippy --no-deps -- -Dwarnings - cargo build --release + - name: Run tests + run: cargo test diff --git a/README.md b/README.md index 9140a18..bf51b8d 100644 --- a/README.md +++ b/README.md @@ -11,23 +11,29 @@ Template generation tool to create `no_std` applications targeting Espressif's l ## Quickstart To generate a proect using this template: + 1. Install `esp-generate`: + ``` cargo install esp-generate --git https://github.com/esp-rs/esp-generate.git ``` + 2. Generate a project. There are two options: - 1. Using TUI: - ``` - esp-generate --chip esp32 tests - ``` - Replace the chip and project name accordingly and choose the different options using the TUI. - - 2. Adding the options to the `esp-generate command: - ``` - esp-generate --chip esp32 -o wifi -o alloc tests - ``` - Replace the chip and project name accordingly and choose the different options using the `-o/--option` flag. - For a full list of available options, see [Usage](#usage) section. + + 1. Using TUI: + + ``` + esp-generate --chip esp32 tests + ``` + + Replace the chip and project name accordingly and choose the different options using the TUI. + + 2. Adding the options to the `esp-generate` command: + ``` + esp-generate --chip esp32 -o wifi -o alloc tests + ``` + Replace the chip and project name accordingly and choose the different options using the `-o/--option` flag. + For a full list of available options, see [Usage](#usage) section. ## Usage @@ -52,7 +58,6 @@ Options: - `ble`: Enables BLE via the `esp-wifi` crate. Requires `alloc`. - `embassy`: Adds `embassy` framework support. - `probe-rs`: Enables `defmt` and flashes using `probe-rs` instead of `espflash`. -- `stack-protector`: Enable stack-smash protection (`nightly` only). - `optional`: Enables the following set of options: - `wokwi`: Adds support for Wokwi simulation using [VS Code Wokwi extension]. - `dev-container`: Adds support for [VS Code Dev Containers] and [GitHub Codespaces]. diff --git a/src/main.rs b/src/main.rs index 1665b44..7777806 100644 --- a/src/main.rs +++ b/src/main.rs @@ -104,13 +104,6 @@ static OPTIONS: &[GeneratorOptionItem] = &[ disables: &[], chips: &[], }), - GeneratorOptionItem::Option(GeneratorOption { - name: "stack-protector", - display_name: "Enable stack-smash protection (`nightly` only).", - enables: &[], - disables: &[], - chips: &[], - }), GeneratorOptionItem::Category(GeneratorOptionCategory { name: "optional", display_name: "Options", @@ -175,12 +168,25 @@ struct Args { #[arg(short, long)] option: Vec, + + #[arg(short = 'O', long)] + output_path: Option, } fn main() { let args = Args::parse(); - if env::current_dir().unwrap().join(&args.name).exists() { + let path = &args + .output_path + .clone() + .unwrap_or_else(|| env::current_dir().unwrap()); + + if !path.is_dir() { + eprintln!("Output path must be a directory"); + process::exit(-1); + } + + if path.join(&args.name).exists() { eprintln!("Directory already exists"); process::exit(-1); } @@ -190,6 +196,7 @@ fn main() { let mut selected = if !args.headless { let repository = tui::Repository::new(args.chip, OPTIONS, &args.option); + // TUI stuff ahead let terminal = tui::init_terminal().unwrap(); @@ -227,7 +234,7 @@ fn main() { } } - let dir = PathBuf::from(&args.name); + let dir = path.join(&args.name); std::fs::create_dir(&dir).unwrap(); for &(file_path, contents) in template_files::TEMPLATE_FILES.iter() { @@ -248,14 +255,14 @@ fn main() { .arg("group_imports=StdExternalCrate") .arg("--config") .arg("imports_granularity=Module") - .current_dir(&args.name) + .current_dir(path.join(&args.name)) .output() .unwrap(); // Run git init process::Command::new("git") .arg("init") - .current_dir(&args.name) + .current_dir(path.join(&args.name)) .output() .unwrap(); } diff --git a/template/.cargo/config.toml b/template/.cargo/config.toml index 1ad5218..6f429ec 100644 --- a/template/.cargo/config.toml +++ b/template/.cargo/config.toml @@ -24,9 +24,6 @@ rustflags = [ # NOTE: May negatively impact performance of produced code "-C", "force-frame-pointers", #ENDIF -#IF option("stack-protector") - "-Z", "stack-protector=all", -#ENDIF ] #REPLACE riscv32imac-unknown-none-elf rust_target diff --git a/template/rust-toolchain.toml b/template/rust-toolchain.toml index 1d0f5c5..be770de 100644 --- a/template/rust-toolchain.toml +++ b/template/rust-toolchain.toml @@ -1,10 +1,6 @@ [toolchain] #IF option("riscv") -#IF option("stack-protector") -channel = "nightly" -#ELSE -#+channel = "stable" -#ENDIF +channel = "stable" components = ["rust-src"] #REPLACE riscv32imac-unknown-none-elf rust_target targets = ["riscv32imac-unknown-none-elf"] diff --git a/template/src/bin/async_main.rs b/template/src/bin/async_main.rs index b5155b8..7cdfee6 100644 --- a/template/src/bin/async_main.rs +++ b/template/src/bin/async_main.rs @@ -40,8 +40,6 @@ async fn main(spawner: Spawner) { info!("Embassy initialized!"); //IF option("wifi") || option("ble") - let peripherals = esp_hal::init(esp_hal::Config::default()); - let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1); let _init = esp_wifi::init( //IF option("wifi") diff --git a/xtask/Cargo.lock b/xtask/Cargo.lock new file mode 100644 index 0000000..fa8ba8c --- /dev/null +++ b/xtask/Cargo.lock @@ -0,0 +1,478 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" + +[[package]] +name = "basic-toml" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "esp-metadata" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9972bbb21dcafe430b87f92efc7a788978a2d17cf8f572d104beeb48602482a" +dependencies = [ + "anyhow", + "basic-toml", + "clap", + "serde", + "strum", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "serde" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xtask" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", + "env_logger", + "esp-metadata", + "log", + "tempfile", +] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 0000000..ae3fa70 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "xtask" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies] +anyhow = "1.0.91" +clap = { version = "4.5.20", features = ["derive"] } +env_logger = "0.11.5" +esp-metadata = { version = "0.4.0", features = ["clap"] } +log = "0.4.22" +tempfile = "3.13.0" diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 0000000..51dc685 --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,147 @@ +use std::{ + path::{Path, PathBuf}, + process::{Command, Stdio}, +}; + +use anyhow::Result; +use clap::{Parser, Subcommand}; +use esp_metadata::Chip; + +#[derive(Debug, Parser)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Debug, Subcommand)] +enum Commands { + /// Generate a project; ensure that it builds, lints pass, and that it is + /// formatted correctly + Check { + /// Target chip to check + #[arg(value_enum)] + chip: Chip, + }, +} + +fn main() -> Result<()> { + env_logger::Builder::new() + .filter_module("xtask", log::LevelFilter::Info) + .init(); + + // The directory containing the Cargo manifest for the 'xtask' package is + // a subdirectory within the workspace: + let workspace = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let workspace = workspace.parent().unwrap().canonicalize()?; + + match Cli::parse().command { + Commands::Check { chip } => check(&workspace, chip), + } +} + +// ---------------------------------------------------------------------------- +// CHECK + +fn check(workspace: &Path, chip: Chip) -> Result<()> { + log::info!("CHECK: {chip}"); + + const PROJECT_NAME: &str = "test"; + for options in options_for_chip(chip) { + log::info!("WITH OPTIONS: {options:?}"); + + // We will generate the project in a temporary directory, to avoid + // making a mess when this subcommand is executed locally: + let project_path = tempfile::tempdir()?.into_path(); + log::info!("PROJECT PATH: {project_path:?}"); + + // Generate a project targeting the specified chip and using the + // specified generation options: + generate(workspace, &project_path, PROJECT_NAME, chip, &options)?; + + // Ensure that the generated project builds without errors: + Command::new("cargo") + .args(["build", "--release"]) + .current_dir(project_path.join(PROJECT_NAME)) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .output()?; + + // Run clippy against the generated project to check for lint errors: + Command::new("cargo") + .args(["clippy", "--no-deps", "--", "-Dwarnings"]) + .current_dir(project_path.join(PROJECT_NAME)) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .output()?; + + // Ensure that the generated project is correctly formatted: + Command::new("cargo") + .args(["fmt", "--", "--check"]) + .current_dir(project_path.join(PROJECT_NAME)) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .output()?; + } + + Ok(()) +} + +fn options_for_chip(chip: Chip) -> Vec> { + let default_options: Vec> = vec![ + vec![], // No options + vec!["alloc".into()], + vec!["alloc".into(), "wifi".into()], + vec!["alloc".into(), "ble".into()], + vec!["embassy".into()], + vec!["probe-rs".into()], + ]; + + match chip { + Chip::Esp32h2 => default_options + .iter() + .filter(|opts| !opts.contains(&"wifi".to_string())) + .cloned() + .collect::>(), + Chip::Esp32s2 => default_options + .iter() + .filter(|opts| !opts.contains(&"ble".to_string())) + .cloned() + .collect::>(), + _ => default_options, + } +} + +fn generate( + workspace: &Path, + project_path: &Path, + project_name: &str, + chip: Chip, + options: &[String], +) -> Result<()> { + let mut args = vec![ + "run", + "--release", + "--", + "--headless", + &format!("--chip={chip}"), + &format!("--output-path={}", project_path.display()), + ] + .iter() + .map(|arg| arg.to_string()) + .collect::>(); + + for option in options { + args.extend(["-o".to_string(), option.to_owned()]); + } + + args.push(project_name.to_string()); + + Command::new("cargo") + .args(args) + .current_dir(workspace) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .output()?; + + Ok(()) +}