blob: 963442bc807f6ee487ecae775c1836b2e0bb878d [file] [log] [blame]
#!/bin/bash
#
# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# 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.
# 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.
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
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
FLAGS=`echo "$LINE1" | sed -e 's:^.*cargo2android.py ::;s:\.$::'`
[ -f Cargo.toml ] || abort "ERROR: cannot find ./Cargo.toml."
}
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
}
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
}
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"
}
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(\":\")"
}
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"
}
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 $*