cbindgen
1 #!/usr/bin/env bash 2 # 3 # Run cbindgen in each appropriate crate (the ones with a ffi interface), 4 # and inspect the output for changes. 5 # 6 # This script will, by default, replace the headers 7 # if the warnings have not changed. 8 # You can replace the old headers _and_ the old saved warnings 9 # with the "--force" option. 10 # You can use "--check" to make any changes (to headers or warnings) a failure. 11 # 12 # Our cbindgen configurations require nightly rust—otherwise, we can't 13 # expand macros. If $RUSTC_NIGHTLY is set, or if $RUSTC is nightly, 14 # or if "rustc" is nightly, we'll use that. Otherwise, we'll try to 15 # ask `rustup` if there is a nightly toolchain. 16 17 # TODO: Use maint/common helpers once they are merged. 18 19 set -eou pipefail 20 21 TOPLEVEL=$(realpath "$(dirname "$0")"/..) 22 23 : "${CBINDGEN_RUSTC:=}" 24 : "${RUSTC:=rustc}" 25 26 replace=1 27 emit_all_warnings=0 28 fail_on_change=0 29 overwrite_warnings=0 30 31 function usage() 32 { 33 cat <<EOF 34 cbindgen: Run cbindgen in appropriate crates, and inspect outputs for changes. 35 36 Usage: 37 cbindgen [opts] 38 39 Options: 40 -h: Print this message. 41 -v: Do not suppress expected warnings. 42 43 -f: Overwrite files, even if there are new warnings. 44 -c: Give a nonzero exit status if any files have changed; do not overwrite. 45 EOF 46 } 47 48 if command -v gnu-getopt >/dev/null; then 49 # If gnu-getopt is present, the platform getopt is unlikely to be good. 50 GETOPT=gnu-getopt 51 else 52 GETOPT=getopt 53 fi 54 55 set +e 56 options=$("$GETOPT" -ohfvc --long help,force,verbose,check -- "$@") 57 status="$?" 58 set -e 59 if test "$status" != 0; then 60 usage 61 exit 1 62 fi 63 64 eval set -- "$options" 65 66 while true; do 67 case "$1" in 68 -h | --help) 69 usage 70 exit 1 71 ;; 72 -f | --force) 73 overwrite_warnings=1 74 shift 75 ;; 76 -v | --verbose) 77 emit_all_warnings=1 78 shift 79 ;; 80 -c | --check) 81 fail_on_change=1 82 replace=0 83 shift 84 ;; 85 --) 86 shift 87 break 88 ;; 89 esac 90 done 91 92 # First, find a suitable rustc. 93 if test "$CBINDGEN_RUSTC" != ""; then 94 # Supposedly we have one. Use that. 95 : 96 elif $RUSTC --version |grep -q nightly; then 97 # Our rustc is apparently nightly. That'll do. 98 CBINDGEN_RUSTC="$RUSTC" 99 else 100 # Maybe rustup can help us? 101 # 102 # TODO: If we start to see differences depending on the version 103 # of nightly, we may want to change this to instead look at a 104 # particular version of nightly. 105 : "${CBINDGEN_TOOLCHAIN:=nightly}" 106 CBINDGEN_RUSTC=$(rustup "+$CBINDGEN_TOOLCHAIN" which rustc) 107 fi 108 109 ANY_DIFFERENCES=0 110 SUGGEST_FORCE=0 111 112 for cratedir in $("$TOPLEVEL/maint/list_crates" --subdir); do 113 crate=$(basename "$cratedir") 114 if ! test -e "$cratedir/cbindgen.toml"; then 115 # no cbindgen.toml here; we don't run in this crate. 116 continue 117 fi 118 119 echo "$crate ..." 120 pushd "$TOPLEVEL/$cratedir">/dev/null 121 122 set +e 123 RUSTC="${CBINDGEN_RUSTC}" cbindgen --lockfile ../../Cargo.lock >"$crate.h.tmp" 2>cbindgen.warnings.tmp 124 status="$?" 125 set -e 126 if test "$emit_all_warnings" = 1 || test "$status" != 0; then 127 cat cbindgen.warnings.tmp 1>&2 128 if "$status" != 0; then 129 echo "cbindgen failed with status $status: See warnings above." 130 exit "$status" 131 fi 132 fi 133 echo "/* Generated by $(cbindgen --version) */" >>"$crate.h.tmp" 134 135 changed_this_time=0 136 new_warnings_this_time=0 137 if diff -uN "$crate.h" "$crate.h.tmp"; then 138 echo " (No changes in the header)" 139 else 140 changed_this_time=1 141 ANY_DIFFERENCES=1 142 fi 143 if diff -uN "cbindgen.warnings" "cbindgen.warnings.tmp"; then 144 echo " (No changes in the warnings)" 145 else 146 new_warnings_this_time=1 147 changed_this_time=1 148 ANY_DIFFERENCES=1 149 fi 150 151 if test "$changed_this_time" = 1 && test "$replace" = 1; then 152 if test "$new_warnings_this_time" = 1 && test "$overwrite_warnings" = 0; then 153 # TODO: Possibly we should only refuse to overwrite when there 154 # are _new_ warnings; not when warnings have gone away or been 155 # re-ordered. 156 echo " CHANGED WARNINGS; not overwriting." 157 SUGGEST_FORCE=1 158 else 159 echo " Overwriting warnings and header file." 160 mv -f cbindgen.warnings.tmp cbindgen.warnings 161 mv -f "$crate.h.tmp" "$crate.h" 162 fi 163 fi 164 165 popd>/dev/null 166 done 167 168 if test "$ANY_DIFFERENCES" = 1; then 169 echo " ------------------------------ " 170 echo "At least one file changed; see above for diffs." 171 if test "$replace" = 0; then 172 echo "(Running in 'check' mode, so nothing was changed.)" 173 elif test "$SUGGEST_FORCE" = 1; then 174 echo "(Did not overwrite files in which the warnings changed.)" 175 echo "Make sure to look over the list of warnings, and then run with -f" 176 fi 177 if test "$fail_on_change" = 1; then 178 exit 2 179 fi 180 fi