1#!/bin/bash 2# 3# Copyright (C) 2020 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17# This script is used by external_updater to replace a package. 18# It can also be invoked directly. It is used in two ways: 19# (1) in a .../external/* rust directory with .bp and Cargo.toml; 20# cargo_embargo must be in PATH 21# (2) in a tmp new directory with .bp and Cargo.toml, 22# and $1 equals to the rust Android source tree root, 23# and $2 equals to the rust sub-directory path name under external. 24 25set -e 26 27# Wrapper around cargo2android. 28SANDBOX="/google/bin/releases/android-rust/cargo2android/sandbox.par" 29SANDBOX_FLAGS="--updater" 30SANDBOX_RULESMK_FLAGS="--rulesmk" 31 32function main() { 33 check_files $* 34 update_files_with_cargo_pkg_vars 35 # Save Cargo.lock if it existed before this update. 36 [ ! -f Cargo.lock ] || mv Cargo.lock Cargo.lock.saved 37 if [[ "$CARGO_EMBARGO" = 'true' ]]; then 38 echo "Updating Android.bp or rules.mk: cargo_embargo generate cargo_embargo.json" 39 cargo_embargo generate cargo_embargo.json 40 fi 41 if [[ "$C2R" = 'true' ]]; then 42 echo "Updating rules.mk: cargo2rulesmk.py $C2R_SCRIPT_FLAGS" 43 cargo2rulesmk.py $C2R_SCRIPT_FLAGS 44 fi 45 copy_cargo_out_files $* 46 rm -rf target.tmp cargo.metadata cargo.out Cargo.lock 47 # Restore Cargo.lock if it existed before this update. 48 [ ! -f Cargo.lock.saved ] || mv Cargo.lock.saved Cargo.lock 49} 50 51function abort() { 52 echo "$1" >&2 53 exit 1 54} 55 56function check_files() { 57 if [ "$1" == "" ]; then 58 EXTERNAL_DIR=`pwd` 59 else 60 EXTERNAL_DIR="$2" # e.g. rust/crates/bytes 61 fi 62 [ -f "$SANDBOX" ] || abort "ERROR: cannot find $SANDBOX" 63 if [ -f Android.bp ]; then 64 LINE1=`head -1 Android.bp` 65 if [[ "$LINE1" =~ ^.*cargo_embargo.*$ ]]; then 66 CARGO_EMBARGO='true' 67 fi 68 fi 69 [ -f Cargo.toml ] || abort "ERROR: cannot find ./Cargo.toml." 70 71 if [ -f rules.mk ]; then 72 LINE1=`head -1 rules.mk` 73 if [[ "$LINE1" =~ ^.*cargo_embargo.*$ ]]; then 74 CARGO_EMBARGO='true' 75 elif [[ "$LINE1" =~ ^.*cargo2rulesmk.py.*$ ]]; then 76 C2R='true' 77 C2R_SCRIPT_FLAGS=`echo "$LINE1" | sed -e 's:^.*cargo2rulesmk.py ::;s:\.$::'` 78 fi 79 fi 80 81 if [ ! "$CARGO_EMBARGO" = 'true' ] && [ ! "$C2R" = 'true']; then 82 echo 'No need to run cargo_embargo or cargo2rules.mk.py; skip regen_bp' 83 exit 0 84 fi 85} 86 87function copy_cargo_out_files() { 88 if [ -d $2/out ]; then 89 # copy files generated by cargo build to out directory 90 PKGNAME=`basename $2` 91 for f in $2/out/* 92 do 93 OUTF=`basename $f` 94 SRC=`ls ./target.tmp/*/debug/build/$PKGNAME-*/out/$OUTF || 95 ls ./target.tmp/debug/build/$PKGNAME-*/out/$OUTF || true` 96 if [ "$SRC" != "" ]; then 97 echo "Copying $SRC to out/$OUTF" 98 mkdir -p out 99 cp $SRC out/$OUTF 100 fi 101 done 102 fi 103} 104 105function update_files_with_cargo_pkg_vars() { 106 FILES=`grep -r -l --include \*.rs \ 107 --exclude-dir .git --exclude build.rs \ 108 --exclude-dir target.tmp --exclude-dir target \ 109 -E 'env!\("CARGO_PKG_(NAME|VERSION|AUTHORS|DESCRIPTION)"\)' * || true` 110 if [ "$FILES" != "" ]; then 111 printf "INFO: to update FILES: %s\n" "`echo ${FILES} | paste -s -d' '`" 112 # Find in ./Cargo.toml the 'name', 'version', 'authors', 'description' 113 # strings and use them to replace env!("CARGO_PKG_*") in $FILES. 114 grep_cargo_key_values 115 update_files 116 fi 117} 118 119function grep_one_key_value() 120{ 121 # Grep the first key $1 in Cargo.toml and return its value. 122 grep "^$1 = " Cargo.toml | head -1 | sed -e "s:^$1 = ::" \ 123 || abort "ERROR: Cannot find '$1' in ./Cargo.toml" 124} 125 126function grep_cargo_key_values() 127{ 128 NAME=`grep_one_key_value name` 129 VERSION=`grep_one_key_value version` 130 AUTHORS=`grep_one_key_value authors` 131 DESCRIPTION=`grep_one_key_value description` 132 if [ "$DESCRIPTION" == "\"\"\"" ]; then 133 # Old Cargo.toml description format, found only in the 'shlex' crate. 134 DESCRIPTION=`printf '"%s-%s"' "$NAME" "$VERSION"` 135 printf "WARNING: use %s for its CARGO_PKG_DESCRIPTION." "$DESCRIPTION" 136 fi 137 # CARGO_PKG_AUTHORS uses ':' as the separator. 138 AUTHORS="$AUTHORS.join(\":\")" 139} 140 141function build_sed_cmd() 142{ 143 # Replace '\' with '\\' to keep escape sequence in the sed command. 144 # NAME and VERSION are simple stings without escape sequence. 145 s1=`printf "$1" "NAME" "$NAME"` 146 s2=`printf "$1" "VERSION" "$VERSION"` 147 s3=`printf "$1" "AUTHORS" "${AUTHORS//\\\\/\\\\\\\\}"` 148 s4=`printf "$1" "DESCRIPTION" "${DESCRIPTION//\\\\/\\\\\\\\}"` 149 echo "$s1;$s2;$s3;$s4" 150} 151 152function update_files() 153{ 154 # Replace option_env!("...") with Some("...") 155 # Replace env!("...") with string literal "..." 156 # Do not replace run-time std::env::var("....") with 157 # (Ok("...".to_string()) as std::result::Result<...>) 158 local cmd=`build_sed_cmd 's%%option_env!("CARGO_PKG_%s")%%Some(%s)%%g'` 159 cmd="$cmd;"`build_sed_cmd 's%%env!("CARGO_PKG_%s")%%%s%%g'` 160 sed -i -e "$cmd" $FILES 161} 162 163main $* 164