From 17385b2bafdc5d38a91d8460415ff31914b212ff Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 10 Jun 2021 07:23:44 -0700 Subject: [PATCH] Refactor Makefile.toml and use it as the source of truth for (almost) all CI (#783) * Split Makefile into smaller files * Add a tidy task for non-fmt/lint checks * Move test-ffi into tests.toml * Move all CI jobs to Makefile.toml, refactor Makefile.toml * build -> check * install cargo make in ci * Fix error * fix CONTRIBUTING * tyop * Fix makefile * fix * fix wasm, dirs * switch to duckscript * Cache cargo-make * fix duckscript * Fix syntax * cache cargo-readme too * better action name * don't double-install * improve cargo tidy * include exes * syntax * fix npm duckscript * rm tidy-minus-fmt --- .cargo/config.toml | 32 +- .github/workflows/build-test.yml | 212 +++++++++--- CONTRIBUTING.md | 3 +- Makefile.toml | 540 ++++--------------------------- tools/scripts/data.toml | 76 +++++ tools/scripts/tests.toml | 69 ++++ tools/scripts/tidy.toml | 101 ++++++ tools/scripts/valgrind.toml | 64 ++++ tools/scripts/wasm.toml | 232 +++++++++++++ 9 files changed, 764 insertions(+), 565 deletions(-) create mode 100644 tools/scripts/data.toml create mode 100644 tools/scripts/tests.toml create mode 100644 tools/scripts/tidy.toml create mode 100644 tools/scripts/valgrind.toml create mode 100644 tools/scripts/wasm.toml diff --git a/.cargo/config.toml b/.cargo/config.toml index c15ffe23df7..ac07f28e9e5 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,25 +4,8 @@ [alias] -### INDIVIDUAL TEST AND LINT TASKS ### - -# Build and run all code paths except docs -test-all = "test --all-features --all-targets" - -# Build and run all docs tests -test-docs = "test --all-features --doc" - -# Build and run docs tests with default features -test-docs-defaults = "test --doc" - -# Check for formatting on all code -fmt-check = "fmt -- --check" - -# Check for license headers -license-check = "make license-header-check" - -# Check for generated README.md -readme-check = "make generated-readme-check" +quick = "make quick" +tidy = "make tidy" # Run Clippy on all code paths # Keep args in sync with `clippy` job in .github/workflows/build-test.yml @@ -30,17 +13,6 @@ readme-check = "make generated-readme-check" # field-reassign-with-default: https://github.com/rust-lang/rust-clippy/issues/6559 (fixed in nightly but not stable) clippy-all = "clippy --all-features --all-targets -- -D warnings -Aclippy::field-reassign-with-default" -### META TASKS ### - -# Run quick version of all lints and tests -quick = "make quick" - -# Run all lints and tests -ci = "make ci" - -# Run all lints and tests -bincode-gen-testdata = "make bincode-gen-testdata" - ### WASM TASKS ### # Re-build standard library with panic=abort. diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e8b896428c0..68154afb9fc 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -6,6 +6,13 @@ name: Build and Test # TODO(#234) re-include cache steps, also using Rust version in cache key +# Note: Each of these jobs, except for the clippy job and the optional benchmarking/coverage +# jobs, maps to a `ci-job-foo` entry in Makefile.toml. If adding further CI jobs, please add them +# as makefile targets as well, and list them under `ci-all`. +# +# Clippy is special because we're using actions-rs/clippy-check which is able to surface clippy failures on +# PR bodies + on: push: branches: [ main ] @@ -15,17 +22,38 @@ on: jobs: # Build job - basic smoke test - build: + check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Load the default Rust toolchain via the rust-toolchain file. run: rustup show + + - name: Get cargo-make version + id: cargo-make-version + run: | + echo "::set-output name=hash::$(cargo search cargo-make | grep '^cargo-make =' | md5sum)" + shell: bash + - name: Attempt to load cached cargo-make + uses: actions/cache@v2 + id: cargo-make-cache + with: + path: | + ~/.cargo/bin/cargo-make + ~/.cargo/bin/cargo-make.exe + key: ${{ runner.os }}-${{ steps.cargo-make-version.outputs.hash }} + - name: Install cargo-make + if: steps.cargo-make-cache.outputs.cache-hit != 'true' + uses: actions-rs/install@v0.1.2 + with: + crate: cargo-make + version: latest + - name: Check uses: actions-rs/cargo@v1.0.1 with: - command: check - args: --all-targets --all-features + command: make + args: ci-job-check # Test job - runs all "cargo make" testing commands test: @@ -39,26 +67,43 @@ jobs: - uses: actions/checkout@v2 - name: Load the default Rust toolchain via the rust-toolchain file. run: rustup show + + - name: Get cargo-make version + id: cargo-make-version + run: | + echo "::set-output name=hash::$(cargo search cargo-make | grep '^cargo-make =' | md5sum)" + shell: bash + - name: Attempt to load cached cargo-make + uses: actions/cache@v2 + id: cargo-make-cache + with: + path: | + ~/.cargo/bin/cargo-make + ~/.cargo/bin/cargo-make.exe + key: ${{ runner.os }}-${{ steps.cargo-make-version.outputs.hash }} + - name: Install cargo-make + if: steps.cargo-make-cache.outputs.cache-hit != 'true' + uses: actions-rs/install@v0.1.2 + with: + crate: cargo-make + version: latest + - name: Build uses: actions-rs/cargo@v1.0.1 with: command: build args: --all-targets --all-features - - name: Test All Targets - uses: actions-rs/cargo@v1.0.1 - with: - command: test-all - - name: Test Docs + - name: Run `cargo make ci-job-test` uses: actions-rs/cargo@v1.0.1 with: - command: test-docs + command: make + args: ci-job-test # Feature coverage job - builds all permutations of features features: runs-on: ubuntu-latest - needs: [build] - + needs: [check] steps: - uses: actions/checkout@v2 - name: Load the default Rust toolchain via the rust-toolchain file. @@ -68,19 +113,37 @@ jobs: with: command: install args: cargo-all-features --version "^1.4" - - name: Test Docs with Default Features - uses: actions-rs/cargo@v1.0.1 + + - name: Get cargo-make version + id: cargo-make-version + run: | + echo "::set-output name=hash::$(cargo search cargo-make | grep '^cargo-make =' | md5sum)" + shell: bash + - name: Attempt to load cached cargo-make + uses: actions/cache@v2 + id: cargo-make-cache + with: + path: | + ~/.cargo/bin/cargo-make + ~/.cargo/bin/cargo-make.exe + key: ${{ runner.os }}-${{ steps.cargo-make-version.outputs.hash }} + - name: Install cargo-make + if: steps.cargo-make-cache.outputs.cache-hit != 'true' + uses: actions-rs/install@v0.1.2 with: - command: test-docs-defaults + crate: cargo-make + version: latest + - name: Build All Feature Permutations uses: actions-rs/cargo@v1.0.1 with: - command: build-all-features + command: make + args: ci-job-features # WASM Tests - runs Node.js tests for WASM bindings wasm: runs-on: ubuntu-latest - needs: [build] + needs: [check] steps: - uses: actions/checkout@v2 @@ -92,11 +155,27 @@ jobs: run: | sudo apt-get install wabt binaryen cargo install twiggy + + - name: Get cargo-make version + id: cargo-make-version + run: | + echo "::set-output name=hash::$(cargo search cargo-make | grep '^cargo-make =' | md5sum)" + shell: bash + - name: Attempt to load cached cargo-make + uses: actions/cache@v2 + id: cargo-make-cache + with: + path: | + ~/.cargo/bin/cargo-make + ~/.cargo/bin/cargo-make.exe + key: ${{ runner.os }}-${{ steps.cargo-make-version.outputs.hash }} - name: Install cargo-make + if: steps.cargo-make-cache.outputs.cache-hit != 'true' uses: actions-rs/install@v0.1.2 with: crate: cargo-make version: latest + - name: Build uses: actions-rs/cargo@v1.0.1 with: @@ -106,14 +185,14 @@ jobs: uses: actions/setup-node@v1 with: node-version: 14.17.0 - - name: Test - run: | - npm install - npm test - working-directory: ./ffi/wasm/test + - name: Build + uses: actions-rs/cargo@v1.0.1 + with: + command: make + args: wasm-test-release - # Lint job - runs all "cargo make" linting commands - lint: + # Fmt job - runs cargo fmt + fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -124,60 +203,91 @@ jobs: - name: Install rustfmt run: rustup component add rustfmt + + - name: Get cargo-make version + id: cargo-make-version + run: | + echo "::set-output name=hash::$(cargo search cargo-make | grep '^cargo-make =' | md5sum)" + shell: bash + - name: Attempt to load cached cargo-make + uses: actions/cache@v2 + id: cargo-make-cache + with: + path: | + ~/.cargo/bin/cargo-make + ~/.cargo/bin/cargo-make.exe + key: ${{ runner.os }}-${{ steps.cargo-make-version.outputs.hash }} - name: Install cargo-make + if: steps.cargo-make-cache.outputs.cache-hit != 'true' uses: actions-rs/install@v0.1.2 with: crate: cargo-make version: latest - - name: Install cargo-readme - uses: actions-rs/install@v0.1.2 - with: - crate: cargo-readme - version: latest - - # TODO(#234) re-include cache steps, also using Rust version in cache key - name: Check Format uses: actions-rs/cargo@v1.0.1 with: - command: fmt-check - - - name: Check License Headers - uses: actions-rs/cargo@v1.0.1 - with: - command: license-check + command: make + args: ci-job-fmt - - name: Check Generated README.md - uses: actions-rs/cargo@v1.0.1 - with: - command: readme-check - # Bincode job - Test that the bincode data provider can be generated correctly. - bincode: + # Tidy job - runs all "cargo make" tidy commands + tidy: runs-on: ubuntu-latest - # Wait for the initial build to finish. Note that this step does not currently re-use any - # artifacts from the build step. It's only waiting on the build to minimize resource use - # in case the build fails. - needs: [build] steps: - uses: actions/checkout@v2 - name: Load the default Rust toolchain via the rust-toolchain file. run: rustup show + - name: Get cargo-make version + id: cargo-make-version + run: | + echo "::set-output name=hash::$(cargo search cargo-make | grep '^cargo-make =' | md5sum)" + shell: bash + - name: Attempt to load cached cargo-make + uses: actions/cache@v2 + id: cargo-make-cache + with: + path: | + ~/.cargo/bin/cargo-make + ~/.cargo/bin/cargo-make.exe + key: ${{ runner.os }}-${{ steps.cargo-make-version.outputs.hash }} - name: Install cargo-make + if: steps.cargo-make-cache.outputs.cache-hit != 'true' uses: actions-rs/install@v0.1.2 with: crate: cargo-make version: latest + - name: Get cargo-readme version + id: cargo-readme-version + run: | + echo "::set-output name=hash::$(cargo search cargo-readme | grep '^cargo-readme =' | md5sum)" + shell: bash + - name: Attempt to load cached cargo-readme + uses: actions/cache@v2 + id: cargo-readme-cache + with: + path: | + ~/.cargo/bin/cargo-readme + ~/.cargo/bin/cargo-readme.exe + key: ${{ runner.os }}-${{ steps.cargo-readme-version.outputs.hash }} + - name: Install cargo-readme + if: steps.cargo-readme-cache.outputs.cache-hit != 'true' + uses: actions-rs/install@v0.1.2 + with: + crate: cargo-readme + version: latest + # TODO(#234) re-include cache steps, also using Rust version in cache key - - name: Build the bincode + - name: Tidy uses: actions-rs/cargo@v1.0.1 with: - command: bincode-gen-testdata + command: make + args: ci-job-tidy # Clippy job (cargo-clippy) - completes and puts warnings inline in PR clippy: @@ -223,7 +333,7 @@ jobs: runs-on: ubuntu-latest - needs: [build] + needs: [check] steps: - uses: actions/checkout@v2 @@ -354,7 +464,7 @@ jobs: # Only run the memory benchmark if the main build succeeded. The memory benchmark does not # rely on any of the build artifacts. - needs: [build] + needs: [check] steps: - uses: actions/checkout@v2 @@ -451,7 +561,7 @@ jobs: runs-on: ubuntu-latest - needs: [build, lint, bincode, benchmark, memory] + needs: [check, tidy, benchmark, memory] ## Only create docs for merges/pushes to main (skip PRs). ## Multiple unfinished PRs should not clobber docs from approved code. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8e8b08cea55..d61ab4951c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,8 +34,9 @@ Each commit and pull request should follow the [style guide][style_guide] and be Handy commands (run from the root directory): +- `cargo tidy` runs tidy-checks (license, fmt, readmes) - `cargo quick` runs the fastest tests and lints. -- `cargo ci` runs all tests and lints. +- `cargo make ci-all` runs all tests and lints ### Structure of commits in a Pull Request diff --git a/Makefile.toml b/Makefile.toml index 0f9239e5a12..454cb066595 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -2,521 +2,95 @@ # called LICENSE at the top level of the ICU4X source tree # (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). +extend = [{ path = "./tools/scripts/data.toml"}, { path = "./tools/scripts/valgrind.toml"}, + { path = "./tools/scripts/tidy.toml"}, { path = "./tools/scripts/wasm.toml"}, + { path = "./tools/scripts/tests.toml"}] + [config] default_to_workspace = false -load_cargo_aliases = true - -### INDIVIDUAL TEST AND LINT TASKS ### -# Note: If a task is purely a cargo alias, define it in .cargo/config.toml - -[tasks.build-all-features] -description = "Build all permutations of all features" -category = "ICU4X Development" -install_crate = { crate_name = "cargo-all-features", binary = "cargo-build-all-features", test_arg = ["--help"] } -install_crate_args = ["--version", "^1.4"] -command = "cargo" -args = ["build-all-features"] - -[tasks.test-capi] -description = "Run C API tests" -category = "ICU4X Development" -script = ''' -cd ffi/capi/examples/pluralrules; -make -cd ../fixeddecimal; -make -cd ../locale; -make -''' - -[tasks.test-cpp] -description = "Run CPP tests" -category = "ICU4X Development" -script = ''' -cd ffi/cpp/examples/pluralrules; -make -cd ../fixeddecimal; -make -''' - -[tasks.license-header-check] -description = "Ensure all the source files have license headers" -category = "ICU4X Development" -script_runner = "@duckscript" -script = ''' -exit_on_error true - -glob_pattern_array = array "./**/*.rs" "./**/*.yml" "./**/*.toml" - -blank_line = set "" - -license_hash_line_1 = set "# This file is part of ICU4X. For terms of use, please see the file" -license_hash_line_2 = set "# called LICENSE at the top level of the ICU4X source tree" -license_hash_line_3 = set "# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE )." -license_hash_array = array ${license_hash_line_1} ${license_hash_line_2} ${license_hash_line_3} ${blank_line} -license_hash_str = array_join ${license_hash_array} "\n" - -license_slash_line_1 = set "// This file is part of ICU4X. For terms of use, please see the file" -license_slash_line_2 = set "// called LICENSE at the top level of the ICU4X source tree" -license_slash_line_3 = set "// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE )." -license_slash_array = array ${license_slash_line_1} ${license_slash_line_2} ${license_slash_line_3} ${blank_line} -license_slash_str = array_join ${license_slash_array} "\n" - -for pattern in ${glob_pattern_array} - handle = glob_array ${pattern} - for path in ${handle} - if not starts_with ${path} "target" # skip paths in target dir - text = readfile ${path} - result_hash = starts_with ${text} ${license_hash_str} - result_slash = starts_with ${text} ${license_slash_str} - not_result_hash = not ${result_hash} - not_result_slash = not ${result_slash} - if ${not_result_hash} and ${not_result_slash} - echo "License header missing in ${path}" - trigger_error "License header missing or misformatted in ${path}." - end - end - end - echo "License headers found in files matching ${pattern}" -end -echo "License header check complete" -''' - -[tasks.generate-readmes] -description = "Automatically generate README.md for each component." -category = "ICU4X Development" -script_runner = "@duckscript" -script = ''' -exit_on_error true - -glob_pattern = set "./**/Cargo.toml" -template = canonicalize README.tpl - -cargo_list = exec cargo --list -if not contains ${cargo_list.stdout} "readme" - trigger_error "Please run 'cargo install cargo-readme' to support generating README.md files" -end - -handle = glob_array ${glob_pattern} -for path in ${handle} - root_dir = dirname ${path} - if not is_empty ${root_dir} - echo "Automatically generating ${root_dir}/README.md" - exec --fail-on-error cargo readme -r ${root_dir} -o README.md -t ${template} - end -end -''' - -[tasks.generated-readme-check] -description = "Check that README.md was properly generated for each component." -category = "ICU4X Development" -dependencies = [ - "generate-readmes" -] -script_runner = "@duckscript" -script = ''' -exit_on_error true - -output = exec git status --porcelain=v1 -uno -output_length = length ${output.stdout} -if greater_than ${output_length} 0 - if contains ${output.stdout} README.md - msg = array "" "" - array_push ${msg} "A README.md file is out-of-sync with lib.rs" - array_push ${msg} "" - array_push ${msg} "If you modified a lib.rs file, please run `cargo make generate-readmes`. If you edited a" - array_push ${msg} "README.md file directly, please also update the corresponding lib.rs." - array_push ${msg} "" - array_push ${msg} "The modified files were:" - array_push ${msg} "${output.stdout}" - msg = array_join ${msg} "\n" - trigger_error ${msg} - end -end -''' - -### META TASKS ### - -[tasks.test-ffi] -description = "Run FFI tests" -category = "ICU4X Development" -dependencies = [ - "test-capi", - "test-cpp", -] [tasks.quick] description = "Run quick version of all lints and tests" category = "ICU4X Development" dependencies = [ - "test-all", + "test-all-features", "fmt-check", "clippy-all", - "license-header-check", - "generated-readme-check", + "tidy-minus-fmt", "test-ffi", ] -[tasks.ci] -description = "Run all lints and tests" +[tasks.tidy] +description = "Run fmt and other tidy checks" category = "ICU4X Development" dependencies = [ - "quick", - "test-docs-defaults", - "test-docs", - "build-all-features", - "bincode-gen-testdata", + "fmt", + "ci-job-tidy", ] -### WASM TASKS ### - -[tasks.wasm-build-dev] -description = "Build WASM FFI into the target directory (dev mode)" -category = "ICU4X WASM" -install_crate = { rustup_component_name = "rust-src" } -toolchain = "nightly-2021-02-28" -command = "cargo" -args = ["wasm-build-dev", "--package", "icu_capi"] - -[tasks.wasm-build-release] -description = "Build WASM FFI into the target directory (release mode)" -category = "ICU4X WASM" -install_crate = { rustup_component_name = "rust-src" } -toolchain = "nightly-2021-02-28" -# We don't care about panics in release mode because most incorrect inputs are handled by result types. -env = { "RUSTFLAGS" = "-C panic=abort -C opt-level=s" } +[tasks.ci-job-check] +description = "Run all tests for the CI 'check' job" +category = "ICU4X Development" command = "cargo" -args = ["wasm-build-release", "--package", "icu_capi"] - -[tasks.wasm-dir] -description = "Make the WASM package directory" -category = "ICU4X WASM" -command = "mkdir" -args = ["-p", "wasmpkg"] - -[tasks.wasm-wasm-dev] -description = "Copy the WASM files from dev into wasmpkg" -category = "ICU4X WASM" -command = "cp" -args = ["${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/wasm32-unknown-unknown/debug/icu_capi.wasm", "wasmpkg/"] -dependencies = ["wasm-build-dev", "wasm-dir"] - -[tasks.wasm-wasm-release] -description = "Copy the WASM files from release into wasmpkg" -category = "ICU4X WASM" -command = "cp" -args = ["${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/wasm32-unknown-unknown/release/icu_capi.wasm", "wasmpkg/"] -dependencies = ["wasm-build-release", "wasm-dir"] - -[tasks.wasm-wat] -description = "Create WebAssembly Text files from the WASM files" -category = "ICU4X WASM" -dependencies = ["wasm-wasm-release"] -script_runner = "@duckscript" -script = ''' -exit_on_error true - -wasm2wat = which wasm2wat -assert ${wasm2wat} "Could not find 'wasm2wat' in path.\n*** Please run 'npm install -g wabt' ***" - -mkdir wasmpkg/wat - -handle = glob_array wasmpkg/*.wasm -for src_path in ${handle} - path_no_extension = substring ${src_path} -5 - basename = substring ${path_no_extension} 8 - out_path = concat wasmpkg/wat/ ${basename} ".wat" - - out_exists = is_path_exists ${out_path} - up_to_date = set false - if ${out_exists} - src_time = get_last_modified_time ${src_path} - out_time = get_last_modified_time ${out_path} - up_to_date = less_than ${src_time} ${out_time} - end +args = ["check", "--all-targets", "--all-features"] - if not ${up_to_date} - echo Writing ${out_path} - output = exec ${wasm2wat} ${src_path} -o ${out_path} - stdout = trim ${output.stdout} - stderr = trim ${output.stderr} - if ${stdout} or ${stderr} or ${output.code} - echo ${stdout}\n${stderr}\nexit code: ${output.code} - assert_fail "wasm2wat printed warnings (shown above)" - end - end -end -''' - -[tasks.wasm-dcmp] -description = "Create WebAssembly decompiled code files from the WASM files" -category = "ICU4X WASM" -dependencies = ["wasm-wasm-release"] -script_runner = "@duckscript" -script = ''' -exit_on_error true - -wasm-decompile = which wasm-decompile -assert ${wasm-decompile} "Could not find 'wasm-decompile' in path.\n*** Please run 'npm install -g wabt' ***" - -mkdir wasmpkg/wasm-decompile - -handle = glob_array wasmpkg/*.wasm -for src_path in ${handle} - path_no_extension = substring ${src_path} -5 - basename = substring ${path_no_extension} 8 - out_path = concat wasmpkg/wasm-decompile/ ${basename} ".dcmp" - - out_exists = is_path_exists ${out_path} - up_to_date = set false - if ${out_exists} - src_time = get_last_modified_time ${src_path} - out_time = get_last_modified_time ${out_path} - up_to_date = less_than ${src_time} ${out_time} - end - - if not ${up_to_date} - echo Writing ${out_path} - output = exec ${wasm-decompile} ${src_path} -o ${out_path} - stdout = trim ${output.stdout} - stderr = trim ${output.stderr} - if ${stdout} or ${stderr} or ${output.code} - echo ${stdout}\n${stderr}\nexit code: ${output.code} - assert_fail "wasm-decompile printed warnings (shown above)" - end - end -end -''' - -[tasks.wasm-opt] -description = "Create optimized WASM files from the WASM files" -category = "ICU4X WASM" -dependencies = ["wasm-wasm-release"] -script_runner = "@duckscript" -script = ''' -exit_on_error true - -wasm-opt = which wasm-opt -assert ${wasm-opt} "Could not find 'wasm-opt' in path.\n*** Please run 'npm install -g wasm-opt' ***" - -mkdir wasmpkg/wasm-opt - -handle = glob_array wasmpkg/*.wasm -for src_path in ${handle} - path_no_extension = substring ${src_path} -5 - basename = substring ${path_no_extension} 8 - out_path = concat wasmpkg/wasm-opt/ ${basename} "+opt.wasm" - - out_exists = is_path_exists ${out_path} - up_to_date = set false - if ${out_exists} - src_time = get_last_modified_time ${src_path} - out_time = get_last_modified_time ${out_path} - up_to_date = less_than ${src_time} ${out_time} - end - - if not ${up_to_date} - echo Writing ${out_path} - output = exec ${wasm-opt} -Os ${src_path} -o ${out_path} - stdout = trim ${output.stdout} - stderr = trim ${output.stderr} - if ${stdout} or ${stderr} or ${output.code} - echo ${stdout}\n${stderr}\nexit code: ${output.code} - assert_fail "wasm-opt printed warnings (shown above)" - end - end -end -''' - -[tasks.wasm-twiggy-dominators] -description = "Create Twiggy Dominator files from the WASM files" -category = "ICU4X WASM" -script_runner = "@duckscript" -script = ''' -exit_on_error true - -twiggy = which twiggy -assert ${twiggy} "Could not find 'twiggy' in path.\n*** Please run 'cargo install twiggy' ***" - -mkdir wasmpkg/twiggy - -handle = glob_array wasmpkg/*.wasm -for src_path in ${handle} - path_no_extension = substring ${src_path} -5 - basename = substring ${path_no_extension} 8 - out_path = concat wasmpkg/twiggy/ ${basename} "+twiggy.txt" - - out_exists = is_path_exists ${out_path} - up_to_date = set false - if ${out_exists} - src_time = get_last_modified_time ${src_path} - out_time = get_last_modified_time ${out_path} - up_to_date = less_than ${src_time} ${out_time} - end - - if not ${up_to_date} - echo Writing ${out_path} - exec --fail-on-error ${twiggy} dominators ${src_path} -o ${out_path} - end -end -''' -dependencies = ["wasm-wasm-release"] - -[tasks.wasm-dev] -description = "All-in-one command to build dev-mode WASM FFI to wasmpkg" -category = "ICU4X WASM" +[tasks.ci-job-test] +description = "Run all tests for the CI 'test' job" +category = "CI" dependencies = [ - "wasm-wasm-dev", + "test-all-features", + "test-ffi", + "test-docs-default", + "test-docs", + "bincode-gen-testdata", ] -[tasks.wasm-release] -description = "All-in-one command to build release-mode WASM FFI to wasmpkg" -category = "ICU4X WASM" +[tasks.ci-job-features] +description = "Run all tests for the CI 'features' job" +category = "CI" dependencies = [ - "wasm-wasm-release", - "wasm-wat", - "wasm-dcmp", - "wasm-opt", - "wasm-twiggy-dominators", + "build-all-features", ] -[tasks.wasm-clean] -description = "Clean up WASM build artifacts" -category = "ICU4X WASM" -command = "rm" -args = ["-rf", "wasmpkg"] - -### VALGRIND TASKS ### - -[tasks.valgrind-build] -description = "Pre-build artifacts for use with the Valgrind task" -category = "ICU4X Valgrind" -command = "cargo" -toolchain = "nightly-2021-02-28" -args = ["build", "--examples", "--features", "icu_benchmark_macros/rust_global_allocator", "--profile", "bench", "-Z", "unstable-options"] - -[tasks.valgrind] -description = "Build ICU4X example files with default features and run through Valgrind" -category = "ICU4X Valgrind" +[tasks.ci-job-fmt] +description = "Run all tests for the CI 'fmt' job" +category = "CI" dependencies = [ - "valgrind-build", -] -script_runner = "@duckscript" -script = ''' -exit_on_error true - -valgrind = which valgrind -assert ${valgrind} "Could not find 'valgrind' in path.\n***\nRead about Valgrind: https://valgrind.org/\nInstall on Ubuntu: `apt-get install valgrind`\n***" - -mkdir benchmarks -mkdir benchmarks/valgrind - -# Re-run the build command only to generate the JSON output (--message-format=json) -output = exec cargo +nightly-2021-02-28 build --examples --message-format=json --features icu_benchmark_macros/rust_global_allocator --profile bench -Z unstable-options -if ${output.code} - trigger_error "Build failed! To debug, build examples with `--features icu_benchmark_macros/rust_global_allocator`" -end - -# Parse the JSON messages from --message-format=json line by line -trimmed_stdout = trim ${output.stdout} -json_messages = split ${trimmed_stdout} "\n" -for json_message in ${json_messages} - json_obj = json_parse ${json_message} - - # The following two JSON keys determine whether this is an example artifact - is_compiler_artifact = eq ${json_obj.reason} "compiler-artifact" - is_example = eq ${json_obj.target.kind[0]} "example" - if ${is_compiler_artifact} and ${is_example} - - # Run the example through Valgrind and save the output in the benchmarks folder - out_file = concat "benchmarks/valgrind/" ${json_obj.target.name} ".out" - set_env LD_BIND_NOW "y" - vg_output = exec ${valgrind} --tool=callgrind --zero-before=_start --callgrind-out-file=${out_file} ${json_obj.executable} - if ${vg_output.code} - echo ${vg_output.stdout} - echo ${vg_output.stderr} - trigger_error "Valgrind failed; see output above" - else - # Display the summary line - grep_output = exec grep "summary" ${out_file} - summary_line = trim ${grep_output.stdout} - ir_count = substring ${summary_line} 9 - echo ${ir_count} "Ir:" ${json_obj.target.name} - end - end -end -''' - -### DATA TASKS ### - -[tasks.testdata-download] -description = "Download fresh CLDR JSON, overwriting the existing CLDR JSON." -category = "ICU4X Data" -command = "cargo" -args = [ - "run", - "--bin=icu4x-testdata-download", - "--", - "-v", + "fmt-check", ] -[tasks.testdata-build-json] -description = "Build ICU4X JSON from the downloaded CLDR JSON, overwriting the existing ICU4X JSON." -category = "ICU4X Data" -command = "cargo" -args = [ - "run", - "--bin=icu4x-datagen", - "--", - "-v", - "--cldr-testdata", - "--out-testdata", - "--all-keys", - "--test-locales", - "--syntax=json", - "--pretty", - "--overwrite", +[tasks.ci-job-tidy] +description = "Run all tests for the CI 'tidy' job" +category = "CI" +dependencies = [ + "license-header-check", + "generated-readme-check", ] -[tasks.testdata] -description = "Download fresh data and then build ICU4X JSON from it" -category = "ICU4X Data" +[tasks.ci-job-wasm] +description = "Run all tests for the CI 'wasm' job" +category = "CI" dependencies = [ - "testdata-download", - "testdata-build-json", + "wasm-test-release", ] -[tasks.bincode-clean] -description = "Clean out the bincode data." -category = "ICU4X Data" -script_runner = "@duckscript" -script = ''' -# Use duckscript, rather than a unix command, so that this works on Windows. -rm -r ./provider/testdata/data/bincode -''' - -[tasks.bincode-gen-testdata-no-clean] -description = "Generate bincode testdata without removing the old data" -category = "ICU4X Data" -command = "cargo" -args = [ - "run", - "--bin=icu4x-datagen", - "--", - "-v", - "--cldr-testdata", - "--out-testdata", - "--all-keys", - "--test-locales", - "--syntax=bincode", -] +[tasks.ci-all] +# Note that updating this list will not update what is run on CI, +# it simply exists as a shortcut to run everything locally +description = "Locally run all CI jobs" +category = "ICU4X Development" +dependencies = [ + "ci-job-check", + "ci-job-tidy", + "ci-job-fmt", + "ci-job-features", + "ci-job-test", + "ci-job-wasm", + + # CI runs this a little differently to allow for lint failures to show + # up on PRs + "clippy-all", -[tasks.bincode-gen-testdata] -description = "Generate bincode for the testdata" -category = "ICU4X Data" -run_task = [ - # Running "bincode-clean" first ensures that this command won't fail because the data - # already exists at that location. - { name = ["bincode-clean", "bincode-gen-testdata-no-clean"] }, + # benchmarking and coverage jobs not included ] diff --git a/tools/scripts/data.toml b/tools/scripts/data.toml new file mode 100644 index 00000000000..07dce0a7fe6 --- /dev/null +++ b/tools/scripts/data.toml @@ -0,0 +1,76 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# This is a cargo-make file included in the toplevel Makefile.toml + +[tasks.testdata-download] +description = "Download fresh CLDR JSON, overwriting the existing CLDR JSON." +category = "ICU4X Data" +command = "cargo" +args = [ + "run", + "--bin=icu4x-testdata-download", + "--", + "-v", +] + +[tasks.testdata-build-json] +description = "Build ICU4X JSON from the downloaded CLDR JSON, overwriting the existing ICU4X JSON." +category = "ICU4X Data" +command = "cargo" +args = [ + "run", + "--bin=icu4x-datagen", + "--", + "-v", + "--cldr-testdata", + "--out-testdata", + "--all-keys", + "--test-locales", + "--syntax=json", + "--pretty", + "--overwrite", +] + +[tasks.testdata] +description = "Download fresh data and then build ICU4X JSON from it" +category = "ICU4X Data" +dependencies = [ + "testdata-download", + "testdata-build-json", +] + +[tasks.bincode-clean] +description = "Clean out the bincode data." +category = "ICU4X Data" +script_runner = "@duckscript" +script = ''' +# Use duckscript, rather than a unix command, so that this works on Windows. +rm -r ./provider/testdata/data/bincode +''' + +[tasks.bincode-gen-testdata-no-clean] +description = "Generate bincode testdata without removing the old data" +category = "ICU4X Data" +command = "cargo" +args = [ + "run", + "--bin=icu4x-datagen", + "--", + "-v", + "--cldr-testdata", + "--out-testdata", + "--all-keys", + "--test-locales", + "--syntax=bincode", +] + +[tasks.bincode-gen-testdata] +description = "Generate bincode for the testdata" +category = "ICU4X Data" +run_task = [ + # Running "bincode-clean" first ensures that this command won't fail because the data + # already exists at that location. + { name = ["bincode-clean", "bincode-gen-testdata-no-clean"] }, +] diff --git a/tools/scripts/tests.toml b/tools/scripts/tests.toml new file mode 100644 index 00000000000..85e00590cfc --- /dev/null +++ b/tools/scripts/tests.toml @@ -0,0 +1,69 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# This is a cargo-make file included in the toplevel Makefile.toml + +[tasks.build-all-features] +description = "Build all permutations of all features" +category = "ICU4X Development" +install_crate = { crate_name = "cargo-all-features", binary = "cargo-build-all-features", test_arg = ["--help"] } +install_crate_args = ["--version", "^1.4"] +command = "cargo" +args = ["build-all-features"] + +[tasks.fmt-check] +description = "Build all permutations of all features" +category = "ICU4X Development" +command = "cargo" +args = ["fmt", "--", "--check"] + +[tasks.test-all-features] +description = "Run all Rust tests with all features and targets" +category = "ICU4X Development" +command = "cargo" +args = ["test", "--all-features", "--all-targets"] + +[tasks.test-docs] +description = "Run all Rust doctests with all features" +category = "ICU4X Development" +command = "cargo" +args = ["test", "--all-features", "--doc"] + +[tasks.test-docs-default] +description = "Run all Rust doctests with default features" +category = "ICU4X Development" +command = "cargo" +args = ["test", "--doc"] + +[tasks.test-ffi] +description = "Run FFI tests" +category = "ICU4X Development" +dependencies = [ + "test-capi", + "test-cpp", +] + +[tasks.test-capi] +description = "Run C API tests" +category = "ICU4X Development" +script_runner = "@duckscript" +script = ''' +cd ffi/capi/examples/pluralrules; +exec make +cd ../fixeddecimal; +exec make +cd ../locale; +exec make +''' + +[tasks.test-cpp] +description = "Run CPP tests" +category = "ICU4X Development" +script_runner = "@duckscript" +script = ''' +cd ffi/cpp/examples/pluralrules; +exec make +cd ../fixeddecimal; +exec make +''' diff --git a/tools/scripts/tidy.toml b/tools/scripts/tidy.toml new file mode 100644 index 00000000000..667fef4e923 --- /dev/null +++ b/tools/scripts/tidy.toml @@ -0,0 +1,101 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# This is a cargo-make file included in the toplevel Makefile.toml + +[tasks.license-header-check] +description = "Ensure all the source files have license headers" +category = "ICU4X Development" +script_runner = "@duckscript" +script = ''' +exit_on_error true + +glob_pattern_array = array "./**/*.rs" "./**/*.yml" "./**/*.toml" + +blank_line = set "" + +license_hash_line_1 = set "# This file is part of ICU4X. For terms of use, please see the file" +license_hash_line_2 = set "# called LICENSE at the top level of the ICU4X source tree" +license_hash_line_3 = set "# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE )." +license_hash_array = array ${license_hash_line_1} ${license_hash_line_2} ${license_hash_line_3} ${blank_line} +license_hash_str = array_join ${license_hash_array} "\n" + +license_slash_line_1 = set "// This file is part of ICU4X. For terms of use, please see the file" +license_slash_line_2 = set "// called LICENSE at the top level of the ICU4X source tree" +license_slash_line_3 = set "// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE )." +license_slash_array = array ${license_slash_line_1} ${license_slash_line_2} ${license_slash_line_3} ${blank_line} +license_slash_str = array_join ${license_slash_array} "\n" + +for pattern in ${glob_pattern_array} + handle = glob_array ${pattern} + for path in ${handle} + if not starts_with ${path} "target" # skip paths in target dir + text = readfile ${path} + result_hash = starts_with ${text} ${license_hash_str} + result_slash = starts_with ${text} ${license_slash_str} + not_result_hash = not ${result_hash} + not_result_slash = not ${result_slash} + if ${not_result_hash} and ${not_result_slash} + echo "License header missing in ${path}" + trigger_error "License header missing or misformatted in ${path}." + end + end + end + echo "License headers found in files matching ${pattern}" +end +echo "License header check complete" +''' + +[tasks.generate-readmes] +description = "Automatically generate README.md for each component." +category = "ICU4X Development" +script_runner = "@duckscript" +script = ''' +exit_on_error true + +glob_pattern = set "./**/Cargo.toml" +template = canonicalize README.tpl + +cargo_list = exec cargo --list +if not contains ${cargo_list.stdout} "readme" + trigger_error "Please run 'cargo install cargo-readme' to support generating README.md files" +end + +handle = glob_array ${glob_pattern} +for path in ${handle} + root_dir = dirname ${path} + if not is_empty ${root_dir} + echo "Automatically generating ${root_dir}/README.md" + exec --fail-on-error cargo readme -r ${root_dir} -o README.md -t ${template} + end +end +''' + +[tasks.generated-readme-check] +description = "Check that README.md was properly generated for each component." +category = "ICU4X Development" +dependencies = [ + "generate-readmes" +] +script_runner = "@duckscript" +script = ''' +exit_on_error true + +output = exec git status --porcelain=v1 -uno +output_length = length ${output.stdout} +if greater_than ${output_length} 0 + if contains ${output.stdout} README.md + msg = array "" "" + array_push ${msg} "A README.md file is out-of-sync with lib.rs" + array_push ${msg} "" + array_push ${msg} "If you modified a lib.rs file, please run `cargo make generate-readmes`. If you edited a" + array_push ${msg} "README.md file directly, please also update the corresponding lib.rs." + array_push ${msg} "" + array_push ${msg} "The modified files were:" + array_push ${msg} "${output.stdout}" + msg = array_join ${msg} "\n" + trigger_error ${msg} + end +end +''' \ No newline at end of file diff --git a/tools/scripts/valgrind.toml b/tools/scripts/valgrind.toml new file mode 100644 index 00000000000..cd1da8ac705 --- /dev/null +++ b/tools/scripts/valgrind.toml @@ -0,0 +1,64 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# This is a cargo-make file included in the toplevel Makefile.toml + +[tasks.valgrind-build] +description = "Pre-build artifacts for use with the Valgrind task" +category = "ICU4X Valgrind" +command = "cargo" +toolchain = "nightly-2021-02-28" +args = ["build", "--examples", "--features", "icu_benchmark_macros/rust_global_allocator", "--profile", "bench", "-Z", "unstable-options"] + +[tasks.valgrind] +description = "Build ICU4X example files with default features and run through Valgrind" +category = "ICU4X Valgrind" +dependencies = [ + "valgrind-build", +] +script_runner = "@duckscript" +script = ''' +exit_on_error true + +valgrind = which valgrind +assert ${valgrind} "Could not find 'valgrind' in path.\n***\nRead about Valgrind: https://valgrind.org/\nInstall on Ubuntu: `apt-get install valgrind`\n***" + +mkdir benchmarks +mkdir benchmarks/valgrind + +# Re-run the build command only to generate the JSON output (--message-format=json) +output = exec cargo +nightly-2021-02-28 build --examples --message-format=json --features icu_benchmark_macros/rust_global_allocator --profile bench -Z unstable-options +if ${output.code} + trigger_error "Build failed! To debug, build examples with `--features icu_benchmark_macros/rust_global_allocator`" +end + +# Parse the JSON messages from --message-format=json line by line +trimmed_stdout = trim ${output.stdout} +json_messages = split ${trimmed_stdout} "\n" +for json_message in ${json_messages} + json_obj = json_parse ${json_message} + + # The following two JSON keys determine whether this is an example artifact + is_compiler_artifact = eq ${json_obj.reason} "compiler-artifact" + is_example = eq ${json_obj.target.kind[0]} "example" + if ${is_compiler_artifact} and ${is_example} + + # Run the example through Valgrind and save the output in the benchmarks folder + out_file = concat "benchmarks/valgrind/" ${json_obj.target.name} ".out" + set_env LD_BIND_NOW "y" + vg_output = exec ${valgrind} --tool=callgrind --zero-before=_start --callgrind-out-file=${out_file} ${json_obj.executable} + if ${vg_output.code} + echo ${vg_output.stdout} + echo ${vg_output.stderr} + trigger_error "Valgrind failed; see output above" + else + # Display the summary line + grep_output = exec grep "summary" ${out_file} + summary_line = trim ${grep_output.stdout} + ir_count = substring ${summary_line} 9 + echo ${ir_count} "Ir:" ${json_obj.target.name} + end + end +end +''' diff --git a/tools/scripts/wasm.toml b/tools/scripts/wasm.toml new file mode 100644 index 00000000000..5a80e781841 --- /dev/null +++ b/tools/scripts/wasm.toml @@ -0,0 +1,232 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# This is a cargo-make file included in the toplevel Makefile.toml + +[tasks.wasm-build-dev] +description = "Build WASM FFI into the target directory (dev mode)" +category = "ICU4X WASM" +install_crate = { rustup_component_name = "rust-src" } +toolchain = "nightly-2021-02-28" +command = "cargo" +args = ["wasm-build-dev", "--package", "icu_capi"] + +[tasks.wasm-build-release] +description = "Build WASM FFI into the target directory (release mode)" +category = "ICU4X WASM" +install_crate = { rustup_component_name = "rust-src" } +toolchain = "nightly-2021-02-28" +# We don't care about panics in release mode because most incorrect inputs are handled by result types. +env = { "RUSTFLAGS" = "-C panic=abort -C opt-level=s" } +command = "cargo" +args = ["wasm-build-release", "--package", "icu_capi"] + +[tasks.wasm-dir] +description = "Make the WASM package directory" +category = "ICU4X WASM" +command = "mkdir" +args = ["-p", "wasmpkg"] + +[tasks.wasm-wasm-dev] +description = "Copy the WASM files from dev into wasmpkg" +category = "ICU4X WASM" +command = "cp" +args = ["${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/wasm32-unknown-unknown/debug/icu_capi.wasm", "wasmpkg/"] +dependencies = ["wasm-build-dev", "wasm-dir"] + +[tasks.wasm-wasm-release] +description = "Copy the WASM files from release into wasmpkg" +category = "ICU4X WASM" +command = "cp" +args = ["${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/target/wasm32-unknown-unknown/release/icu_capi.wasm", "wasmpkg/"] +dependencies = ["wasm-build-release", "wasm-dir"] + +[tasks.wasm-wat] +description = "Create WebAssembly Text files from the WASM files" +category = "ICU4X WASM" +dependencies = ["wasm-wasm-release"] +script_runner = "@duckscript" +script = ''' +exit_on_error true + +wasm2wat = which wasm2wat +assert ${wasm2wat} "Could not find 'wasm2wat' in path.\n*** Please run 'npm install -g wabt' ***" + +mkdir wasmpkg/wat + +handle = glob_array wasmpkg/*.wasm +for src_path in ${handle} + path_no_extension = substring ${src_path} -5 + basename = substring ${path_no_extension} 8 + out_path = concat wasmpkg/wat/ ${basename} ".wat" + + out_exists = is_path_exists ${out_path} + up_to_date = set false + if ${out_exists} + src_time = get_last_modified_time ${src_path} + out_time = get_last_modified_time ${out_path} + up_to_date = less_than ${src_time} ${out_time} + end + + if not ${up_to_date} + echo Writing ${out_path} + output = exec ${wasm2wat} ${src_path} -o ${out_path} + stdout = trim ${output.stdout} + stderr = trim ${output.stderr} + if ${stdout} or ${stderr} or ${output.code} + echo ${stdout}\n${stderr}\nexit code: ${output.code} + assert_fail "wasm2wat printed warnings (shown above)" + end + end +end +''' + +[tasks.wasm-dcmp] +description = "Create WebAssembly decompiled code files from the WASM files" +category = "ICU4X WASM" +dependencies = ["wasm-wasm-release"] +script_runner = "@duckscript" +script = ''' +exit_on_error true + +wasm-decompile = which wasm-decompile +assert ${wasm-decompile} "Could not find 'wasm-decompile' in path.\n*** Please run 'npm install -g wabt' ***" + +mkdir wasmpkg/wasm-decompile + +handle = glob_array wasmpkg/*.wasm +for src_path in ${handle} + path_no_extension = substring ${src_path} -5 + basename = substring ${path_no_extension} 8 + out_path = concat wasmpkg/wasm-decompile/ ${basename} ".dcmp" + + out_exists = is_path_exists ${out_path} + up_to_date = set false + if ${out_exists} + src_time = get_last_modified_time ${src_path} + out_time = get_last_modified_time ${out_path} + up_to_date = less_than ${src_time} ${out_time} + end + + if not ${up_to_date} + echo Writing ${out_path} + output = exec ${wasm-decompile} ${src_path} -o ${out_path} + stdout = trim ${output.stdout} + stderr = trim ${output.stderr} + if ${stdout} or ${stderr} or ${output.code} + echo ${stdout}\n${stderr}\nexit code: ${output.code} + assert_fail "wasm-decompile printed warnings (shown above)" + end + end +end +''' + +[tasks.wasm-opt] +description = "Create optimized WASM files from the WASM files" +category = "ICU4X WASM" +dependencies = ["wasm-wasm-release"] +script_runner = "@duckscript" +script = ''' +exit_on_error true + +wasm-opt = which wasm-opt +assert ${wasm-opt} "Could not find 'wasm-opt' in path.\n*** Please run 'npm install -g wasm-opt' ***" + +mkdir wasmpkg/wasm-opt + +handle = glob_array wasmpkg/*.wasm +for src_path in ${handle} + path_no_extension = substring ${src_path} -5 + basename = substring ${path_no_extension} 8 + out_path = concat wasmpkg/wasm-opt/ ${basename} "+opt.wasm" + + out_exists = is_path_exists ${out_path} + up_to_date = set false + if ${out_exists} + src_time = get_last_modified_time ${src_path} + out_time = get_last_modified_time ${out_path} + up_to_date = less_than ${src_time} ${out_time} + end + + if not ${up_to_date} + echo Writing ${out_path} + output = exec ${wasm-opt} -Os ${src_path} -o ${out_path} + stdout = trim ${output.stdout} + stderr = trim ${output.stderr} + if ${stdout} or ${stderr} or ${output.code} + echo ${stdout}\n${stderr}\nexit code: ${output.code} + assert_fail "wasm-opt printed warnings (shown above)" + end + end +end +''' + +[tasks.wasm-twiggy-dominators] +description = "Create Twiggy Dominator files from the WASM files" +category = "ICU4X WASM" +script_runner = "@duckscript" +script = ''' +exit_on_error true + +twiggy = which twiggy +assert ${twiggy} "Could not find 'twiggy' in path.\n*** Please run 'cargo install twiggy' ***" + +mkdir wasmpkg/twiggy + +handle = glob_array wasmpkg/*.wasm +for src_path in ${handle} + path_no_extension = substring ${src_path} -5 + basename = substring ${path_no_extension} 8 + out_path = concat wasmpkg/twiggy/ ${basename} "+twiggy.txt" + + out_exists = is_path_exists ${out_path} + up_to_date = set false + if ${out_exists} + src_time = get_last_modified_time ${src_path} + out_time = get_last_modified_time ${out_path} + up_to_date = less_than ${src_time} ${out_time} + end + + if not ${up_to_date} + echo Writing ${out_path} + exec --fail-on-error ${twiggy} dominators ${src_path} -o ${out_path} + end +end +''' +dependencies = ["wasm-wasm-release"] + +[tasks.wasm-dev] +description = "All-in-one command to build dev-mode WASM FFI to wasmpkg" +category = "ICU4X WASM" +dependencies = [ + "wasm-wasm-dev", +] + +[tasks.wasm-release] +description = "All-in-one command to build release-mode WASM FFI to wasmpkg" +category = "ICU4X WASM" +dependencies = [ + "wasm-wasm-release", + "wasm-wat", + "wasm-dcmp", + "wasm-opt", + "wasm-twiggy-dominators", +] + +[tasks.wasm-test-release] +description = "Run WASM tests in release mode" +category = "ICU4X WASM" +script_runner = "@duckscript" +script = ''' +cd ./ffi/wasm/test; +exec npm install; +exec npm test; +''' +dependencies = ["wasm-release"] + +[tasks.wasm-clean] +description = "Clean up WASM build artifacts" +category = "ICU4X WASM" +command = "rm" +args = ["-rf", "wasmpkg"]