xref: /aosp_15_r20/build/make/shell_utils.sh (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
2*9e94795aSAndroid Build Coastguard Worker#
3*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*9e94795aSAndroid Build Coastguard Worker#
7*9e94795aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
8*9e94795aSAndroid Build Coastguard Worker#
9*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*9e94795aSAndroid Build Coastguard Worker# limitations under the License.
14*9e94795aSAndroid Build Coastguard Worker
15*9e94795aSAndroid Build Coastguard Workerfunction gettop
16*9e94795aSAndroid Build Coastguard Worker{
17*9e94795aSAndroid Build Coastguard Worker    local TOPFILE=build/make/core/envsetup.mk
18*9e94795aSAndroid Build Coastguard Worker    # The ${TOP-} expansion allows this to work even with set -u
19*9e94795aSAndroid Build Coastguard Worker    if [ -n "${TOP:-}" -a -f "${TOP:-}/$TOPFILE" ] ; then
20*9e94795aSAndroid Build Coastguard Worker        # The following circumlocution ensures we remove symlinks from TOP.
21*9e94795aSAndroid Build Coastguard Worker        (cd "$TOP"; PWD= /bin/pwd)
22*9e94795aSAndroid Build Coastguard Worker    else
23*9e94795aSAndroid Build Coastguard Worker        if [ -f $TOPFILE ] ; then
24*9e94795aSAndroid Build Coastguard Worker            # The following circumlocution (repeated below as well) ensures
25*9e94795aSAndroid Build Coastguard Worker            # that we record the true directory name and not one that is
26*9e94795aSAndroid Build Coastguard Worker            # faked up with symlink names.
27*9e94795aSAndroid Build Coastguard Worker            PWD= /bin/pwd
28*9e94795aSAndroid Build Coastguard Worker        else
29*9e94795aSAndroid Build Coastguard Worker            local HERE=$PWD
30*9e94795aSAndroid Build Coastguard Worker            local T=
31*9e94795aSAndroid Build Coastguard Worker            while [ \( ! \( -f $TOPFILE \) \) -a \( "$PWD" != "/" \) ]; do
32*9e94795aSAndroid Build Coastguard Worker                \cd ..
33*9e94795aSAndroid Build Coastguard Worker                T=`PWD= /bin/pwd -P`
34*9e94795aSAndroid Build Coastguard Worker            done
35*9e94795aSAndroid Build Coastguard Worker            \cd "$HERE"
36*9e94795aSAndroid Build Coastguard Worker            if [ -f "$T/$TOPFILE" ]; then
37*9e94795aSAndroid Build Coastguard Worker                echo "$T"
38*9e94795aSAndroid Build Coastguard Worker            fi
39*9e94795aSAndroid Build Coastguard Worker        fi
40*9e94795aSAndroid Build Coastguard Worker    fi
41*9e94795aSAndroid Build Coastguard Worker}
42*9e94795aSAndroid Build Coastguard Worker
43*9e94795aSAndroid Build Coastguard Worker# Asserts that the root of the tree can be found.
44*9e94795aSAndroid Build Coastguard Workerif [ -z "${IMPORTING_ENVSETUP:-}" ] ; then
45*9e94795aSAndroid Build Coastguard Workerfunction require_top
46*9e94795aSAndroid Build Coastguard Worker{
47*9e94795aSAndroid Build Coastguard Worker    TOP=$(gettop)
48*9e94795aSAndroid Build Coastguard Worker    if [[ ! $TOP ]] ; then
49*9e94795aSAndroid Build Coastguard Worker        echo "Can not locate root of source tree. $(basename $0) must be run from within the Android source tree or TOP must be set." >&2
50*9e94795aSAndroid Build Coastguard Worker        exit 1
51*9e94795aSAndroid Build Coastguard Worker    fi
52*9e94795aSAndroid Build Coastguard Worker}
53*9e94795aSAndroid Build Coastguard Workerfi
54*9e94795aSAndroid Build Coastguard Worker
55*9e94795aSAndroid Build Coastguard Worker# Asserts that the lunch variables have been set
56*9e94795aSAndroid Build Coastguard Workerif [ -z "${IMPORTING_ENVSETUP:-}" ] ; then
57*9e94795aSAndroid Build Coastguard Workerfunction require_lunch
58*9e94795aSAndroid Build Coastguard Worker{
59*9e94795aSAndroid Build Coastguard Worker    if [[ ! $TARGET_PRODUCT || ! $TARGET_RELEASE || ! $TARGET_BUILD_VARIANT  ]] ; then
60*9e94795aSAndroid Build Coastguard Worker        echo "Please run lunch and try again." >&2
61*9e94795aSAndroid Build Coastguard Worker        exit 1
62*9e94795aSAndroid Build Coastguard Worker    fi
63*9e94795aSAndroid Build Coastguard Worker}
64*9e94795aSAndroid Build Coastguard Workerfi
65*9e94795aSAndroid Build Coastguard Worker
66*9e94795aSAndroid Build Coastguard Worker# This function sets up the build environment to be appropriate for Cog.
67*9e94795aSAndroid Build Coastguard Workerfunction setup_cog_env_if_needed() {
68*9e94795aSAndroid Build Coastguard Worker  local top=$(gettop)
69*9e94795aSAndroid Build Coastguard Worker
70*9e94795aSAndroid Build Coastguard Worker  # return early if not in a cog workspace
71*9e94795aSAndroid Build Coastguard Worker  if [[ ! "$top" =~ ^/google/cog ]]; then
72*9e94795aSAndroid Build Coastguard Worker    return 0
73*9e94795aSAndroid Build Coastguard Worker  fi
74*9e94795aSAndroid Build Coastguard Worker
75*9e94795aSAndroid Build Coastguard Worker  setup_cog_symlink
76*9e94795aSAndroid Build Coastguard Worker
77*9e94795aSAndroid Build Coastguard Worker  export ANDROID_BUILD_ENVIRONMENT_CONFIG="googler-cog"
78*9e94795aSAndroid Build Coastguard Worker
79*9e94795aSAndroid Build Coastguard Worker  # Running repo command within Cog workspaces is not supported, so override
80*9e94795aSAndroid Build Coastguard Worker  # it with this function. If the user is running repo within a Cog workspace,
81*9e94795aSAndroid Build Coastguard Worker  # we'll fail with an error, otherwise, we run the original repo command with
82*9e94795aSAndroid Build Coastguard Worker  # the given args.
83*9e94795aSAndroid Build Coastguard Worker  if ! ORIG_REPO_PATH=`which repo`; then
84*9e94795aSAndroid Build Coastguard Worker    return 0
85*9e94795aSAndroid Build Coastguard Worker  fi
86*9e94795aSAndroid Build Coastguard Worker  function repo {
87*9e94795aSAndroid Build Coastguard Worker    if [[ "${PWD}" == /google/cog/* ]]; then
88*9e94795aSAndroid Build Coastguard Worker      echo -e "\e[01;31mERROR:\e[0mrepo command is disallowed within Cog workspaces."
89*9e94795aSAndroid Build Coastguard Worker      kill -INT $$ # exits the script without exiting the user's shell
90*9e94795aSAndroid Build Coastguard Worker    fi
91*9e94795aSAndroid Build Coastguard Worker    ${ORIG_REPO_PATH} "$@"
92*9e94795aSAndroid Build Coastguard Worker  }
93*9e94795aSAndroid Build Coastguard Worker}
94*9e94795aSAndroid Build Coastguard Worker
95*9e94795aSAndroid Build Coastguard Worker# creates a symlink for the out/ dir when inside a cog workspace.
96*9e94795aSAndroid Build Coastguard Workerfunction setup_cog_symlink() {
97*9e94795aSAndroid Build Coastguard Worker  local out_dir=$(getoutdir)
98*9e94795aSAndroid Build Coastguard Worker  local top=$(gettop)
99*9e94795aSAndroid Build Coastguard Worker
100*9e94795aSAndroid Build Coastguard Worker  # return early if out dir is already a symlink
101*9e94795aSAndroid Build Coastguard Worker  if [[ -L "$out_dir" ]]; then
102*9e94795aSAndroid Build Coastguard Worker    return 0
103*9e94795aSAndroid Build Coastguard Worker  fi
104*9e94795aSAndroid Build Coastguard Worker
105*9e94795aSAndroid Build Coastguard Worker  # return early if out dir is not in the workspace
106*9e94795aSAndroid Build Coastguard Worker  if [[ ! "$out_dir" =~ ^$top/ ]]; then
107*9e94795aSAndroid Build Coastguard Worker    return 0
108*9e94795aSAndroid Build Coastguard Worker  fi
109*9e94795aSAndroid Build Coastguard Worker
110*9e94795aSAndroid Build Coastguard Worker  local link_destination="${HOME}/.cog/android-build-out"
111*9e94795aSAndroid Build Coastguard Worker
112*9e94795aSAndroid Build Coastguard Worker  # remove existing out/ dir if it exists
113*9e94795aSAndroid Build Coastguard Worker  if [[ -d "$out_dir" ]]; then
114*9e94795aSAndroid Build Coastguard Worker    echo "Detected existing out/ directory in the Cog workspace which is not supported. Repairing workspace by removing it and creating the symlink to ~/.cog/android-build-out"
115*9e94795aSAndroid Build Coastguard Worker    if ! rm -rf "$out_dir"; then
116*9e94795aSAndroid Build Coastguard Worker      echo "Failed to remove existing out/ directory: $out_dir" >&2
117*9e94795aSAndroid Build Coastguard Worker      kill -INT $$ # exits the script without exiting the user's shell
118*9e94795aSAndroid Build Coastguard Worker    fi
119*9e94795aSAndroid Build Coastguard Worker  fi
120*9e94795aSAndroid Build Coastguard Worker
121*9e94795aSAndroid Build Coastguard Worker  # create symlink
122*9e94795aSAndroid Build Coastguard Worker  echo "Creating symlink: $out_dir -> $link_destination"
123*9e94795aSAndroid Build Coastguard Worker  mkdir -p ${link_destination}
124*9e94795aSAndroid Build Coastguard Worker  if ! ln -s "$link_destination" "$out_dir"; then
125*9e94795aSAndroid Build Coastguard Worker    echo "Failed to create cog symlink: $out_dir -> $link_destination" >&2
126*9e94795aSAndroid Build Coastguard Worker    kill -INT $$ # exits the script without exiting the user's shell
127*9e94795aSAndroid Build Coastguard Worker  fi
128*9e94795aSAndroid Build Coastguard Worker}
129*9e94795aSAndroid Build Coastguard Worker
130*9e94795aSAndroid Build Coastguard Workerfunction getoutdir
131*9e94795aSAndroid Build Coastguard Worker{
132*9e94795aSAndroid Build Coastguard Worker    local top=$(gettop)
133*9e94795aSAndroid Build Coastguard Worker    local out_dir="${OUT_DIR:-}"
134*9e94795aSAndroid Build Coastguard Worker    if [[ -z "${out_dir}" ]]; then
135*9e94795aSAndroid Build Coastguard Worker        if [[ -n "${OUT_DIR_COMMON_BASE:-}" && -n "${top}" ]]; then
136*9e94795aSAndroid Build Coastguard Worker            out_dir="${OUT_DIR_COMMON_BASE}/$(basename ${top})"
137*9e94795aSAndroid Build Coastguard Worker        else
138*9e94795aSAndroid Build Coastguard Worker            out_dir="out"
139*9e94795aSAndroid Build Coastguard Worker        fi
140*9e94795aSAndroid Build Coastguard Worker    fi
141*9e94795aSAndroid Build Coastguard Worker    if [[ "${out_dir}" != /* ]]; then
142*9e94795aSAndroid Build Coastguard Worker        out_dir="${top}/${out_dir}"
143*9e94795aSAndroid Build Coastguard Worker    fi
144*9e94795aSAndroid Build Coastguard Worker    echo "${out_dir}"
145*9e94795aSAndroid Build Coastguard Worker}
146*9e94795aSAndroid Build Coastguard Worker
147*9e94795aSAndroid Build Coastguard Worker# Pretty print the build status and duration
148*9e94795aSAndroid Build Coastguard Workerfunction _wrap_build()
149*9e94795aSAndroid Build Coastguard Worker{
150*9e94795aSAndroid Build Coastguard Worker    if [[ "${ANDROID_QUIET_BUILD:-}" == true ]]; then
151*9e94795aSAndroid Build Coastguard Worker      "$@"
152*9e94795aSAndroid Build Coastguard Worker      return $?
153*9e94795aSAndroid Build Coastguard Worker    fi
154*9e94795aSAndroid Build Coastguard Worker    local start_time=$(date +"%s")
155*9e94795aSAndroid Build Coastguard Worker    "$@"
156*9e94795aSAndroid Build Coastguard Worker    local ret=$?
157*9e94795aSAndroid Build Coastguard Worker    local end_time=$(date +"%s")
158*9e94795aSAndroid Build Coastguard Worker    local tdiff=$(($end_time-$start_time))
159*9e94795aSAndroid Build Coastguard Worker    local hours=$(($tdiff / 3600 ))
160*9e94795aSAndroid Build Coastguard Worker    local mins=$((($tdiff % 3600) / 60))
161*9e94795aSAndroid Build Coastguard Worker    local secs=$(($tdiff % 60))
162*9e94795aSAndroid Build Coastguard Worker    local ncolors=$(tput colors 2>/dev/null)
163*9e94795aSAndroid Build Coastguard Worker    if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
164*9e94795aSAndroid Build Coastguard Worker        color_failed=$'\E'"[0;31m"
165*9e94795aSAndroid Build Coastguard Worker        color_success=$'\E'"[0;32m"
166*9e94795aSAndroid Build Coastguard Worker        color_warning=$'\E'"[0;33m"
167*9e94795aSAndroid Build Coastguard Worker        color_reset=$'\E'"[00m"
168*9e94795aSAndroid Build Coastguard Worker    else
169*9e94795aSAndroid Build Coastguard Worker        color_failed=""
170*9e94795aSAndroid Build Coastguard Worker        color_success=""
171*9e94795aSAndroid Build Coastguard Worker        color_reset=""
172*9e94795aSAndroid Build Coastguard Worker    fi
173*9e94795aSAndroid Build Coastguard Worker
174*9e94795aSAndroid Build Coastguard Worker    echo
175*9e94795aSAndroid Build Coastguard Worker    if [ $ret -eq 0 ] ; then
176*9e94795aSAndroid Build Coastguard Worker        echo -n "${color_success}#### build completed successfully "
177*9e94795aSAndroid Build Coastguard Worker    else
178*9e94795aSAndroid Build Coastguard Worker        echo -n "${color_failed}#### failed to build some targets "
179*9e94795aSAndroid Build Coastguard Worker    fi
180*9e94795aSAndroid Build Coastguard Worker    if [ $hours -gt 0 ] ; then
181*9e94795aSAndroid Build Coastguard Worker        printf "(%02d:%02d:%02d (hh:mm:ss))" $hours $mins $secs
182*9e94795aSAndroid Build Coastguard Worker    elif [ $mins -gt 0 ] ; then
183*9e94795aSAndroid Build Coastguard Worker        printf "(%02d:%02d (mm:ss))" $mins $secs
184*9e94795aSAndroid Build Coastguard Worker    elif [ $secs -gt 0 ] ; then
185*9e94795aSAndroid Build Coastguard Worker        printf "(%d seconds)" $secs
186*9e94795aSAndroid Build Coastguard Worker    fi
187*9e94795aSAndroid Build Coastguard Worker    echo " ####${color_reset}"
188*9e94795aSAndroid Build Coastguard Worker    echo
189*9e94795aSAndroid Build Coastguard Worker    return $ret
190*9e94795aSAndroid Build Coastguard Worker}
191*9e94795aSAndroid Build Coastguard Worker
192*9e94795aSAndroid Build Coastguard Worker
193*9e94795aSAndroid Build Coastguard Workerfunction log_tool_invocation()
194*9e94795aSAndroid Build Coastguard Worker{
195*9e94795aSAndroid Build Coastguard Worker    if [[ -z $ANDROID_TOOL_LOGGER ]]; then
196*9e94795aSAndroid Build Coastguard Worker        return
197*9e94795aSAndroid Build Coastguard Worker    fi
198*9e94795aSAndroid Build Coastguard Worker
199*9e94795aSAndroid Build Coastguard Worker    LOG_TOOL_TAG=$1
200*9e94795aSAndroid Build Coastguard Worker    LOG_START_TIME=$(date +%s.%N)
201*9e94795aSAndroid Build Coastguard Worker    trap '
202*9e94795aSAndroid Build Coastguard Worker        exit_code=$?;
203*9e94795aSAndroid Build Coastguard Worker        # Remove the trap to prevent duplicate log.
204*9e94795aSAndroid Build Coastguard Worker        trap - EXIT;
205*9e94795aSAndroid Build Coastguard Worker        $ANDROID_TOOL_LOGGER \
206*9e94795aSAndroid Build Coastguard Worker                --tool_tag="${LOG_TOOL_TAG}" \
207*9e94795aSAndroid Build Coastguard Worker                --start_timestamp="${LOG_START_TIME}" \
208*9e94795aSAndroid Build Coastguard Worker                --end_timestamp="$(date +%s.%N)" \
209*9e94795aSAndroid Build Coastguard Worker                --tool_args="$*" \
210*9e94795aSAndroid Build Coastguard Worker                --exit_code="${exit_code}" \
211*9e94795aSAndroid Build Coastguard Worker                ${ANDROID_TOOL_LOGGER_EXTRA_ARGS} \
212*9e94795aSAndroid Build Coastguard Worker           > /dev/null 2>&1 &
213*9e94795aSAndroid Build Coastguard Worker        exit ${exit_code}
214*9e94795aSAndroid Build Coastguard Worker    ' SIGINT SIGTERM SIGQUIT EXIT
215*9e94795aSAndroid Build Coastguard Worker}
216*9e94795aSAndroid Build Coastguard Worker
217