• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#     cargo2android.py 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.
28C2A_WRAPPER="/google/bin/releases/android-rust/cargo2android/sandbox.par"
29
30function main() {
31  check_files $*
32  update_files_with_cargo_pkg_vars
33  # Save Cargo.lock if it existed before this update.
34  [ ! -f Cargo.lock ] || mv Cargo.lock Cargo.lock.saved
35  echo "Updating Android.bp: $C2A_WRAPPER -- $FLAGS"
36  $C2A_WRAPPER -- $FLAGS
37  copy_cargo_out_files $*
38  rm -rf target.tmp cargo.out Cargo.lock
39  # Restore Cargo.lock if it existed before this update.
40  [ ! -f Cargo.lock.saved ] || mv Cargo.lock.saved Cargo.lock
41}
42
43function abort() {
44  echo "$1" >&2
45  exit 1
46}
47
48function check_files() {
49  if [ "$1" == "" ]; then
50    EXTERNAL_DIR=`pwd`
51  else
52    EXTERNAL_DIR="$2"  # e.g. rust/crates/bytes
53  fi
54  [ -f "$C2A_WRAPPER" ] || abort "ERROR: cannot find $C2A_WRAPPER"
55  LINE1=`head -1 Android.bp || abort "ERROR: cannot find Android.bp"`
56  if [[ ! "$LINE1" =~ ^.*cargo2android.py.*$ ]]; then
57    echo 'Android.bp header does not contain "cargo2android.py"; skip regen_bp'
58    exit 0
59  fi
60  FLAGS=`echo "$LINE1" | sed -e 's:^.*cargo2android.py ::;s:\.$::'`
61  [ -f Cargo.toml ] || abort "ERROR: cannot find ./Cargo.toml."
62}
63
64function copy_cargo_out_files() {
65  if [ -d $2/out ]; then
66    # copy files generated by cargo build to out directory
67    PKGNAME=`basename $2`
68    for f in $2/out/*
69    do
70      OUTF=`basename $f`
71      SRC=`ls ./target.tmp/*/debug/build/$PKGNAME-*/out/$OUTF ||
72           ls ./target.tmp/debug/build/$PKGNAME-*/out/$OUTF || true`
73      if [ "$SRC" != "" ]; then
74        echo "Copying $SRC to out/$OUTF"
75        mkdir -p out
76        cp $SRC out/$OUTF
77      fi
78    done
79  fi
80}
81
82function update_files_with_cargo_pkg_vars() {
83  FILES=`grep -r -l --include \*.rs \
84    --exclude-dir .git --exclude build.rs \
85    --exclude-dir target.tmp --exclude-dir target \
86    -E 'env!\("CARGO_PKG_(NAME|VERSION|AUTHORS|DESCRIPTION)"\)' * || true`
87  if [ "$FILES" != "" ]; then
88    printf "INFO: to update FILES: %s\n" "`echo ${FILES} | paste -s -d' '`"
89    # Find in ./Cargo.toml the 'name', 'version', 'authors', 'description'
90    # strings and use them to replace env!("CARGO_PKG_*") in $FILES.
91    grep_cargo_key_values
92    update_files
93  fi
94}
95
96function grep_one_key_value()
97{
98  # Grep the first key $1 in Cargo.toml and return its value.
99  grep "^$1 = " Cargo.toml | head -1 | sed -e "s:^$1 = ::" \
100    || abort "ERROR: Cannot find '$1' in ./Cargo.toml"
101}
102
103function grep_cargo_key_values()
104{
105  NAME=`grep_one_key_value name`
106  VERSION=`grep_one_key_value version`
107  AUTHORS=`grep_one_key_value authors`
108  DESCRIPTION=`grep_one_key_value description`
109  if [ "$DESCRIPTION" == "\"\"\"" ]; then
110    # Old Cargo.toml description format, found only in the 'shlex' crate.
111    DESCRIPTION=`printf '"%s-%s"' "$NAME" "$VERSION"`
112    printf "WARNING: use %s for its CARGO_PKG_DESCRIPTION." "$DESCRIPTION"
113  fi
114  # CARGO_PKG_AUTHORS uses ':' as the separator.
115  AUTHORS="$AUTHORS.join(\":\")"
116}
117
118function build_sed_cmd()
119{
120  # Replace '\' with '\\' to keep escape sequence in the sed command.
121  # NAME and VERSION are simple stings without escape sequence.
122  s1=`printf "$1" "NAME" "$NAME"`
123  s2=`printf "$1" "VERSION" "$VERSION"`
124  s3=`printf "$1" "AUTHORS" "${AUTHORS//\\\\/\\\\\\\\}"`
125  s4=`printf "$1" "DESCRIPTION" "${DESCRIPTION//\\\\/\\\\\\\\}"`
126  echo "$s1;$s2;$s3;$s4"
127}
128
129function update_files()
130{
131  # Replace option_env!("...") with Some("...")
132  # Replace env!("...") with string literal "..."
133  # Do not replace run-time std::env::var("....") with
134  #   (Ok("...".to_string()) as std::result::Result<...>)
135  local cmd=`build_sed_cmd 's%%option_env!("CARGO_PKG_%s")%%Some(%s)%%g'`
136  cmd="$cmd;"`build_sed_cmd 's%%env!("CARGO_PKG_%s")%%%s%%g'`
137  sed -i -e "$cmd" $FILES
138}
139
140main $*
141