Build Script or other Process for Simple Cargo Project?

I am curious how people manage builds with rust. I'm using a shell script to build my wink command. It is slow because it does almost everything that is possible in this context, but it is also helpful. Is there a more standard process or tool for managing builds, something more generic to enable and disable parts of the process?

#!/bin/sh -x

clear

export RUST_BACKTRACE=full # or 1
rustup update

projdir=/mnt/c/temp/wink    # directory containing cargo.toml
linbld=/tmp/wink.build      # WSL path to directory for building Linux binary
winbld='C:\temp\wink.build' # Windows path to directory for building Windows binary
lwinbld=`wslpath $winbld`   # WSL path to directory for building Windows binary
linstall=~/bin              # WSL binary install path

cd $projdir                 # avoid specifying project path for all commands

                            # error out quickly if compile is not possible
cmd="cargo check -v --workspace --all-features"
result=$( $cmd 3>&1 1>&2 2>&3 | tee /dev/fd/2 )

if [ "$?" -ne "0" ]; then
    echo cargo check failed with non-zero exit code
    echo To reproduce: cd `pwd` \; $cmd
    cd - > /dev/null # revert to the previous directory
    exit 2
fi

# sometimes cargo check fails the first time; in which case, run it again.

if echo $result | egrep -qi "error|warning"; then
    result=$( $cmd 3>&1 1>&2 2>&3 | tee /dev/fd/2 )
    
    if [ "$?" -ne "0" ]; then
        echo cargo check failed the second run with a non-zero exit code
        echo To reproduce: cd `pwd` \; $cmd # and look for error/warning
        cd - > /dev/null # revert to the previous directory
        exit 2
    fi

    if echo $result | egrep -qi "error|warning"; then
        echo cargo check failed the second run with an error or warning
        echo $result | egrep -i "error|warning"
        echo To reproduce: cd `pwd` \; $cmd # and look for error/warning
        cd - > /dev/null # revert to the previous directory
        exit 2
    fi
fi

cmd='find . -name *.rs -exec rustfmt -l -v {} ;'
result=$( $cmd 3>&1 1>&2 2>&3 | tee /dev/fd/2 )

if [ "$?" -ne "0" ] || echo $result | egrep -qi "error|warning"; then
    echo cargo fmt failed
    echo To reproduce: cd `pwd` \; $cmd # and look for error/warning
    cd - > /dev/null # revert to the previous directory
    exit 3
fi

# this file is more manageable this way
rustfmt -l -v --config max_width=2500 ./src/wsl/inv/invocablecategory.rs
set +x
    
for f in "$(find . -iname \*.rs -print)"; do
    ls -l $f
    wc -clw $f
done

set -x
cargo update -v 
cmd='cargo-clippy -v'
result=$( $cmd 3>&1 1>&2 2>&3 | tee /dev/fd/2 )

if [ "$?" -ne "0" ] || echo $result | egrep -qi "error|warning"; then
    echo cargo-clippy failed
    echo To reproduce: cd `pwd` ; $cmd
    cd - > /dev/null # revert to the previous directory
    exit 4
fi

# excludes --doc
# --all-targets is a bit excessive... //--show-output is unnecessary // --no-fail-fast
cmd="cargo test -v --workspace --all-features --target-dir $linbld -- --nocapture -- -epdv word a b c"
result=$( $cmd 3>&1 1>&2 2>&3 | tee /dev/fd/2 )

if [ "$?" -ne "0" ] || echo $result | egrep -qi "could not compile|warning|test result. FAILED|error. test failed"; then
    echo cargo test failed
    echo To reproduce: cd `pwd` \; $cmd
    cd - > /dev/null # revert to the previous directory
    exit 5
fi

#cargo clean --target-dir /tmp/wink.build       # kills build performance and result in err/warn that may cause script to abort   
# -release determines  binary build path below 
cmd="cargo build -v --target-dir $linbld --release"
result=`$cmd 3>&1 1>&2 2>&3 | tee /dev/fd/2`

if [ "$?" -ne "0" ] || echo $result | sed -e s'/error.format/3rror.format/g' | egrep -qi "error|warning"; then
    echo cargo build failed
    echo To reproduce: cd `pwd` \; $cmd
    cd - > /dev/null # revert to the previous directory
    exit 6
fi

cargo doc -v --target-dir $linbld               # --open to open in browser
ls -l ${linbld}/release/wink            # show WSL binary file size and build date
rm ${linstall}/wink                     # remove installed WSL binary
cp ${linbld}/release/wink $linstall     # install new WSL binary
cargo.exe build --release --target-dir "$winbld" # --release affects binary path below 
`wslpath ${winbld}`/release/wink.exe -ep > ${linbld}/doc/wink/wink.json # export JSON to docs
ls -l ${linbld}/doc/wink/wink.json      # show JSON file size and touch time
cp ${linbld}/doc/wink/wink.json .       # copy JSON to project root for github
path=`cmd.exe /c echo %USERPROFILE% | sed -e 's/\r//g'` # install Windows binary to this directory in %PATH%
path=`wslpath $path | sed -e 's/\r//g'`/AppData/Local/Microsoft/WindowsApps 
cp ${lwinbld}/release/wink.exe $path # install Windows binary
set +x
${linstall}/wink $@ # run Linux build with parameters supplied on command line
cp /mnt/c/temp/wink/wince $linstall # install any updates to this wince shell script
cd - > /dev/null # revert to the previous directory
exit 0

You could take a look at the cargo xtask pattern. I recently published some code that uses a xtask to build a frontend in wasm using trunk, and then build the backend and run it!

It uses duct for "shell like" scripting.

You can take a look at my xtask source file to see how this looks!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.