#!/bin/sh set -e root_dir=$(dirname "$0") root_dir=$(cd "$root_dir/.." && pwd) if [ ! -f "$root_dir/LICENSE.txt" ]; then echo "Couldn't find the root dir" exit 1 fi configuration=Release set_rustflags=y test_gen=y test_instrs=y test_build_no_std=y test_features=y test_current=y test_msrv=y test_code_asm=y gen_cov=n kcov=kcov cov_out=$root_dir/cov-out cov_out_rust=$cov_out/rust cov_out_rust_tmp=$cov_out_rust/tmp cov_out_rust_merged=$cov_out_rust/merged # Minimum supported Rust version msrv="1.54.0" new_func() { echo echo "****************************************************************" echo "$1" echo "****************************************************************" echo } generator_check() { new_func "Run generator, verify no diff" dotnet run -c $configuration --project "$root_dir/src/csharp/Intel/Generator/Generator.csproj" git diff --exit-code } test_valid_invalid_instructions() { new_func "Decode valid and invalid instructions" valid_file=$(mktemp) invalid_file=$(mktemp) # The C# code needs a formatter so add masm feature dotnet build -c:$configuration -p:IcedFeatureFlags="DECODER ENCODER OPCODE_INFO INSTR_INFO MASM" "$root_dir/src/csharp/Intel/IcedFuzzer/IcedFuzzer/IcedFuzzer.csproj" if [ "$gen_cov" = "y" ]; then release_flag= fzgt_output_dir=debug else release_flag="--release" fzgt_output_dir=release fi cargo build --color always $release_flag --manifest-path "$root_dir/src/rust/iced-x86-fzgt/Cargo.toml" fzgt_exe="$root_dir/src/rust/iced-x86-fzgt/target/$fzgt_output_dir/iced-x86-fzgt" for bitness in 16 32 64; do echo "==== ${bitness}-bit: Generating valid/invalid files ====" dotnet run -c:$configuration --no-build --project "$root_dir/src/csharp/Intel/IcedFuzzer/IcedFuzzer/IcedFuzzer.csproj" -- -$bitness -oil "$invalid_file" -ovlc "$valid_file" echo "==== ${bitness}-bit: Testing valid instructions ====" cov_test "test_valid_$bitness" "$fzgt_exe" -b $bitness -f "$valid_file" echo "==== ${bitness}-bit: Testing invalid instructions ====" cov_test "test_invalid_$bitness" "$fzgt_exe" -b $bitness -f "$invalid_file" --invalid done for bitness in 16 32 64; do echo "==== ${bitness}-bit (AMD): Generating valid/invalid files ====" dotnet run -c:$configuration --no-build --project "$root_dir/src/csharp/Intel/IcedFuzzer/IcedFuzzer/IcedFuzzer.csproj" -- -$bitness -oil "$invalid_file" -ovlc "$valid_file" --amd echo "==== ${bitness}-bit (AMD): Testing valid instructions ====" cov_test "test_amd_valid_$bitness" "$fzgt_exe" -b $bitness -f "$valid_file" --amd echo "==== ${bitness}-bit (AMD): Testing invalid instructions ====" cov_test "test_amd_invalid_$bitness" "$fzgt_exe" -b $bitness -f "$invalid_file" --invalid --amd done rm "$valid_file" rm "$invalid_file" } build_no_std() { new_func "Build no_std" curr_dir=$(pwd) cd "$root_dir/src/rust/iced-x86" echo "==== BUILD DEBUG ====" cargo check --color always --no-default-features --features "no_std decoder encoder block_encoder op_code_info instr_info gas intel masm nasm fast_fmt serde code_asm mvex" cd "$curr_dir" } build_features() { new_func "Build one feature at a time" curr_dir=$(pwd) cd "$root_dir/src/rust/iced-x86" set -- \ "std decoder" \ "std decoder mvex" \ "std encoder" \ "std encoder block_encoder" \ "std encoder op_code_info" \ "std instr_info" \ "std gas" \ "std intel" \ "std masm" \ "std nasm" \ "std fast_fmt" \ "std serde" \ "std code_asm" for features in "$@"; do echo "==== $features ====" cargo check --color always --release --no-default-features --features "$features" done set -- \ "no_vex" \ "no_evex" \ "no_xop" \ "no_d3now" \ "no_vex no_evex no_xop no_d3now" for features in "$@"; do echo "==== $features ====" cargo check --color always --release --features "$features" done set -- \ "no_std decoder" \ "no_std decoder mvex" \ "no_std encoder" \ "no_std encoder block_encoder" \ "no_std encoder op_code_info" \ "no_std instr_info" \ "no_std gas" \ "no_std intel" \ "no_std masm" \ "no_std nasm" \ "no_std fast_fmt" \ "no_std serde" \ "no_std code_asm" for features in "$@"; do echo "==== $features ====" cargo check --color always --release --no-default-features --features "$features" done set -- \ "std decoder" \ "std decoder mvex" \ "std decoder encoder" \ "std decoder encoder block_encoder" \ "std decoder encoder op_code_info" \ "std decoder instr_info" \ "std decoder gas" \ "std decoder intel" \ "std decoder masm" \ "std decoder nasm" \ "std decoder fast_fmt" \ "std decoder serde" \ "std decoder code_asm" for features in "$@"; do echo "==== TEST $features ====" cargo check --color always --release --tests --no-default-features --features "$features" done set -- \ "no_vex" \ "no_evex" \ "no_xop" \ "no_d3now" \ "no_vex no_evex no_xop no_d3now" for features in "$@"; do echo "==== TEST $features ====" cargo check --color always --release --tests --features "$features" done cd "$curr_dir" } cov_test() { cov_test_dir=$1 shift if [ "$gen_cov" = "y" ]; then # Don't include: tests, big generated files "$kcov" --verify --exclude-pattern=/tests/,/test/,/test_utils/,fn_asm_impl.rs,fn_asm_pub.rs --include-pattern=/iced-x86/ "$cov_out_rust_tmp/$cov_test_dir" "$@" else "$@" fi } cargo_test_cov() { cov_test_dir=$1 shift if [ "$gen_cov" = "y" ]; then test_exe=$(cargo test --color always --no-run --message-format=json "$@" | grep -- '"name":"iced-x86"' | tail -1 | sed -e 's/.*"executable":"\([^"]\+\)".*/\1/') if [ ! -x "$test_exe" ]; then echo "Couldn't get the test executable name, got '$test_exe'" echo "json output:" cargo test --color always --no-run --message-format=json "$@" exit 1 fi cov_test "$cov_test_dir" "$test_exe" else cargo test --color always "$@" fi } build_test_current_version() { new_func "Build, test (current version)" curr_dir=$(pwd) cd "$root_dir/src/rust/iced-x86" echo "Rust version" rustc --version echo "==== CLIPPY RELEASE --tests ====" cargo clippy --color always --release --features "serde code_asm mvex" --tests echo "==== FORMAT CHECK ====" cargo fmt -- --color always --check echo "==== DOC ====" cargo doc --color always --features "serde code_asm mvex" echo "==== BUILD RELEASE ====" cargo check --color always --release --features "serde code_asm mvex" echo "==== TEST ====" extra_args="" if [ "$test_code_asm" != "y" ]; then extra_args="-- --skip lib.rs" fi cargo test --color always --features "serde $test_code_asm_feat mvex" $extra_args # Make sure the two read-mem methods behave the same # Also test serde code. It needs encoder to also test 'db x,y,z', see serde tests echo "==== TEST DEBUG: std decoder encoder serde __internal_flip ====" cargo_test_cov test_internal_flip --tests --no-default-features --features "std decoder encoder serde __internal_flip" echo "==== TEST DEBUG ====" cargo_test_cov test_debug --tests --features "serde $test_code_asm_feat mvex" echo "==== BUILD RELEASE wasm32-unknown-unknown ====" cargo check --color always --target wasm32-unknown-unknown --release --features "serde code_asm mvex" echo "==== PUBLISH DRY-RUN ====" # It fails on Windows (GitHub CI) without this, claiming that some random number of Rust files are dirty. # Redirect to /dev/null so it won't hang (waiting for us to scroll) if it finds modified lines git status > /dev/null git diff > /dev/null cargo publish --color always --features "serde code_asm mvex" --dry-run cd "$curr_dir" } build_test_msrv() { new_func "Build minimum supported Rust version: $msrv" curr_dir=$(pwd) cd "$root_dir/src/rust/iced-x86" echo "*** If this fails, install Rust $msrv" echo "==== BUILD DEBUG ====" cargo +$msrv check --color always --features "serde code_asm mvex" echo "==== BUILD DEBUG default features ====" # Build with default features since that's what most people probably use cargo +$msrv check --color always # We don't test it since we only guarantee that the crate can be built. Testing is for iced devs. # We test it when using the latest rustc, but not rustc MSRV. # This also speeds up CI since code_asm feature's tests take a very long time to compile. cd "$curr_dir" } clear_test_vars() { test_gen=n test_instrs=n test_build_no_std=n test_features=n test_current=n test_msrv=n } while [ "$#" -gt 0 ]; do case $1 in --no-tests) clear_test_vars ;; --quick-check) clear_test_vars test_current=y test_code_asm=n ;; --no-dotnet) test_gen=n test_instrs=n ;; --no-gen) test_gen=n ;; --no-instrs) test_instrs=n ;; --no-no_std) test_build_no_std=n ;; --no-features) test_features=n ;; --no-current) test_current=n ;; --no-msrv) test_msrv=n ;; --test-gen) test_gen=y ;; --test-instrs) test_instrs=y ;; --test-no_std) test_build_no_std=y ;; --test-features) test_features=y ;; --test-current) test_current=y ;; --test-msrv) test_msrv=y ;; --coverage) gen_cov=y ;; --no-set-rustflags) set_rustflags=n ;; *) echo "Unknown arg: $1"; exit 1 ;; esac shift done echo echo "==================================================" echo "Rust build" echo "==================================================" echo if [ "$set_rustflags" = "y" ]; then export RUSTFLAGS="-D warnings" fi echo "rustup show" rustup show if [ "$gen_cov" = "y" ]; then mkdir -p "$cov_out" rm -rf "$cov_out_rust" mkdir -p "$cov_out_rust_tmp" "$kcov" --version fi if [ "$test_code_asm" = "y" ]; then test_code_asm_feat="code_asm" else test_code_asm_feat="" fi if [ "$test_gen" = "y" ] || [ "$test_instrs" = "y" ]; then echo "dotnet version (if this fails, install .NET or use --no-dotnet)" dotnet --version fi if [ "$test_gen" = "y" ]; then generator_check fi if [ "$test_instrs" = "y" ]; then test_valid_invalid_instructions fi if [ "$test_build_no_std" = "y" ]; then build_no_std fi if [ "$test_features" = "y" ]; then build_features fi if [ "$test_current" = "y" ]; then build_test_current_version fi if [ "$test_msrv" = "y" ]; then build_test_msrv fi if [ "$gen_cov" = "y" ]; then "$kcov" --merge "$cov_out_rust_merged" "$cov_out_rust_tmp/"* fi