No more FIXME .bp; auto fix env!("CARGO_PKG_*")
* Find and change Rust expressions like env!("CARGO_PKG_*")
* The workaround of missing CARGO_PKG_* environment variables
continues with safer and simpler management.
* After each upgrade of Rust crates, automatically find and
change the env!("CARGO_PKG_*") expressions to the values
found in Cargo.toml.
* regen_bp.sh can be called any time in a crate's directory
to find and fix the env!(...) expression again.
* No more FIXME crates
* With the new cargo2anroid.py --patch option,
the 3 crates no longer need manual edit on their .bp files.
* libloading can be handled by cargo2android.py now.
* Skip manually written .bp file
* Do not call cargo2anroid.py if its signature is
not found at header of Android.bp.
* Reshape the code into modular functions.
Bug: 172299943
Bug: 172093078
Test: run in all external/rust/crates/*; check changes in new .bp.
Test: run regen_bp.sh on affected and other rust crates
Change-Id: I207d23d3bd2e609a4d949cd722e682c2dd06c071
diff --git a/regen_bp.sh b/regen_bp.sh
index 2ade8e4..963442b 100755
--- a/regen_bp.sh
+++ b/regen_bp.sh
@@ -14,71 +14,127 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This script is used by external_updater to replace a package. Don't
-# invoke directly.
-
-set -e
-
-# Call this in two ways:
-# (1) in a .../external/* rust directory with .bp and Cargo.toml,
-# development/scripts/cargo2android.py must be in PATH
+# This script is used by external_updater to replace a package.
+# It can also be invoked directly. It is used in two ways:
+# (1) in a .../external/* rust directory with .bp and Cargo.toml;
+# cargo2android.py must be in PATH
# (2) in a tmp new directory with .bp and Cargo.toml,
# and $1 equals to the rust Android source tree root,
# and $2 equals to the rust sub-directory path name under external.
-if [ "$1" == "" ]; then
- external_dir=`pwd`
- C2A=`which cargo2android.py`
- if [ "$C2A" == "" ]; then
- echo "ERROR: cannot find cargo2android.py in PATH"
- exit 1
+
+set -e
+
+function main() {
+ check_files $*
+ update_files_with_cargo_pkg_vars
+ # Save Cargo.lock if it existed before this update.
+ [ ! -f Cargo.lock ] || mv Cargo.lock Cargo.lock.saved
+ echo "Updating Android.bp: $C2A $FLAGS"
+ $C2A $FLAGS
+ copy_cargo_out_files $*
+ rm -rf target.tmp cargo.out Cargo.lock
+ # Restore Cargo.lock if it existed before this update.
+ [ ! -f Cargo.lock.saved ] || mv Cargo.lock.saved Cargo.lock
+}
+
+function abort() {
+ echo "$1" >&2
+ exit 1
+}
+
+function check_files() {
+ if [ "$1" == "" ]; then
+ EXTERNAL_DIR=`pwd`
+ C2A=`which cargo2android.py ||
+ abort "ERROR: cannot find cargo2android.py in PATH"`
+ else
+ EXTERNAL_DIR="$2" # e.g. rust/crates/bytes
+ C2A="$1/development/scripts/cargo2android.py"
+ [ -f "$C2A" ] || abort "ERROR: cannot find $C2A"
fi
-else
- external_dir="$2" # e.g. rust/crates/bytes
- C2A="$1/development/scripts/cargo2android.py"
- if [ ! -f $C2A ]; then
- echo "ERROR: cannot find $C2A"
- exit 1
+ LINE1=`head -1 Android.bp || abort "ERROR: cannot find Android.bp"`
+ if [[ ! "$LINE1" =~ ^.*cargo2android.py.*$ ]]; then
+ echo 'Android.bp header does not contain "cargo2android.py"; skip regen_bp'
+ exit 0
fi
-fi
+ FLAGS=`echo "$LINE1" | sed -e 's:^.*cargo2android.py ::;s:\.$::'`
+ [ -f Cargo.toml ] || abort "ERROR: cannot find ./Cargo.toml."
+}
-# Save Cargo.lock if it existed before this update.
-if [ -f Cargo.lock ]; then
- mv Cargo.lock Cargo.lock.saved
-fi
+function copy_cargo_out_files() {
+ if [ -d $2/out ]; then
+ # copy files generated by cargo build to out directory
+ PKGNAME=`basename $2`
+ for f in $2/out/*
+ do
+ OUTF=`basename $f`
+ SRC=`ls ./target.tmp/*/debug/build/$PKGNAME-*/out/$OUTF ||
+ ls ./target.tmp/debug/build/$PKGNAME-*/out/$OUTF || true`
+ if [ "$SRC" != "" ]; then
+ echo "Copying $SRC to out/$OUTF"
+ mkdir -p out
+ cp $SRC out/$OUTF
+ fi
+ done
+ fi
+}
-LINE1=`head -1 Android.bp`
-FLAGS=`echo $LINE1 | sed -e 's:^.*cargo2android.py ::;s:\.$::'`
-CMD="$C2A $FLAGS"
-echo "Updating Android.bp: $CMD"
-$CMD
+function update_files_with_cargo_pkg_vars() {
+ FILES=`grep -r -l --include \*.rs \
+ --exclude-dir .git --exclude build.rs \
+ --exclude-dir target.tmp --exclude-dir target \
+ -E 'env!\("CARGO_PKG_(NAME|VERSION|AUTHORS|DESCRIPTION)"\)' * || true`
+ if [ "$FILES" != "" ]; then
+ printf "INFO: to update FILES: %s\n" "`echo ${FILES} | paste -s -d' '`"
+ # Find in ./Cargo.toml the 'name', 'version', 'authors', 'description'
+ # strings and use them to replace env!("CARGO_PKG_*") in $FILES.
+ grep_cargo_key_values
+ update_files
+ fi
+}
-if [ -d $2/out ]; then
- # copy files generated by cargo build to out directory
- PKGNAME=`basename $2`
- for f in $2/out/*
- do
- OUTF=`basename $f`
- SRC=`ls ./target.tmp/x86_64-unknown-linux-gnu/debug/build/$PKGNAME-*/out/$OUTF ||
- ls ./target.tmp/debug/build/$PKGNAME-*/out/$OUTF || true`
- if [ "$SRC" != "" ]; then
- echo "Copying $SRC to out/$OUTF"
- mkdir -p out
- cp $SRC out/$OUTF
- fi
- done
-fi
-rm -rf target.tmp cargo.out Cargo.lock
+function grep_one_key_value()
+{
+ # Grep the first key $1 in Cargo.toml and return its value.
+ grep "^$1 = " Cargo.toml | head -1 | sed -e "s:^$1 = ::" \
+ || abort "ERROR: Cannot find '$1' in ./Cargo.toml"
+}
-# Restore Cargo.lock if it existed before this update.
-if [ -f Cargo.lock.saved ]; then
- mv Cargo.lock.saved Cargo.lock
-fi
+function grep_cargo_key_values()
+{
+ NAME=`grep_one_key_value name`
+ VERSION=`grep_one_key_value version`
+ AUTHORS=`grep_one_key_value authors`
+ DESCRIPTION=`grep_one_key_value description`
+ if [ "$DESCRIPTION" == "\"\"\"" ]; then
+ # Old Cargo.toml description format, found only in the 'shlex' crate.
+ DESCRIPTION=`printf '"%s-%s"' "$NAME" "$VERSION"`
+ printf "WARNING: use %s for its CARGO_PKG_DESCRIPTION." "$DESCRIPTION"
+ fi
+ # CARGO_PKG_AUTHORS uses ':' as the separator.
+ AUTHORS="$AUTHORS.join(\":\")"
+}
-# Some .bp files have manual changes that cannot be fixed by post_update.sh.
-# Add a note to force a manual edit.
-case $external_dir in
- */libloading|*/libsqlite3-sys|*/unicode-xid)
- echo "FIXME: Copy manual changes from old version!" >> Android.bp
-esac
+function build_sed_cmd()
+{
+ # Replace '\' with '\\' to keep escape sequence in the sed command.
+ # NAME and VERSION are simple stings without escape sequence.
+ s1=`printf "$1" "NAME" "$NAME"`
+ s2=`printf "$1" "VERSION" "$VERSION"`
+ s3=`printf "$1" "AUTHORS" "${AUTHORS//\\\\/\\\\\\\\}"`
+ s4=`printf "$1" "DESCRIPTION" "${DESCRIPTION//\\\\/\\\\\\\\}"`
+ echo "$s1;$s2;$s3;$s4"
+}
-exit 0
+function update_files()
+{
+ # Replace option_env!("...") with Some("...")
+ # Replace env!("...") with string literal "..."
+ # Do not replace run-time std::env::var("....") with
+ # (Ok("...".to_string()) as std::result::Result<...>)
+ local cmd=`build_sed_cmd 's%%option_env!("CARGO_PKG_%s")%%Some(%s)%%g'`
+ cmd="$cmd;"`build_sed_cmd 's%%env!("CARGO_PKG_%s")%%%s%%g'`
+ sed -i -e "$cmd" $FILES
+}
+
+main $*