blob: 73c12750aeb2781eaeaf43d8da1157950b9e5b8e [file] [log] [blame]
Joe Onorato344e4042022-12-05 15:15:36 -08001# Copyright (C) 2022 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15function gettop
16{
17 local TOPFILE=build/make/core/envsetup.mk
18 # The ${TOP-} expansion allows this to work even with set -u
19 if [ -n "${TOP:-}" -a -f "${TOP:-}/$TOPFILE" ] ; then
20 # The following circumlocution ensures we remove symlinks from TOP.
21 (cd "$TOP"; PWD= /bin/pwd)
22 else
23 if [ -f $TOPFILE ] ; then
24 # The following circumlocution (repeated below as well) ensures
25 # that we record the true directory name and not one that is
26 # faked up with symlink names.
27 PWD= /bin/pwd
28 else
29 local HERE=$PWD
30 local T=
31 while [ \( ! \( -f $TOPFILE \) \) -a \( "$PWD" != "/" \) ]; do
32 \cd ..
33 T=`PWD= /bin/pwd -P`
34 done
35 \cd "$HERE"
36 if [ -f "$T/$TOPFILE" ]; then
37 echo "$T"
38 fi
39 fi
40 fi
41}
42
Joe Onorato23124752024-05-14 15:06:48 -070043# Asserts that the root of the tree can be found.
Joe Onorato344e4042022-12-05 15:15:36 -080044if [ -z "${IMPORTING_ENVSETUP:-}" ] ; then
45function require_top
46{
47 TOP=$(gettop)
48 if [[ ! $TOP ]] ; then
Joe Onorato1b9ab292024-05-17 12:16:43 -070049 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
Joe Onorato344e4042022-12-05 15:15:36 -080050 exit 1
51 fi
52}
53fi
54
Joe Onorato23124752024-05-14 15:06:48 -070055# Asserts that the lunch variables have been set
56if [ -z "${IMPORTING_ENVSETUP:-}" ] ; then
57function require_lunch
58{
59 if [[ ! $TARGET_PRODUCT || ! $TARGET_RELEASE || ! $TARGET_BUILD_VARIANT ]] ; then
60 echo "Please run lunch and try again." >&2
61 exit 1
62 fi
63}
64fi
65
Sam Lewis51193302025-08-22 11:37:33 -070066function set_network_file_system_type_env_var() {
67 local top=$(gettop)
68 local out_dir=$(getoutdir)
69 local cartfs_mount_point=$(cartfs_mount_point)
70
71 local nfs_type=local
72
Sam Lewis54ee0cc2025-08-25 12:46:35 -070073 # The options are:
Sam Lewis15aeee22025-09-04 10:51:01 -070074 # - cog-cartfs-symlink: out is a symlink to a CartFS path in a Cog workspace.
75 # - local-cartfs-symlink: out is a symlink to a CartFS path in a local workspace.
Sam Lewis54ee0cc2025-08-25 12:46:35 -070076 # - cog-symlink: $top starts with /google/cog.
77 # - abfs: .abfs.sock exists in the workspace.
Sam Lewis51193302025-08-22 11:37:33 -070078 if [[ -n "$cartfs_mount_point" && -L "$out_dir" && "$(readlink "$out_dir")" =~ ^/google/cartfs/mount ]]; then
Sam Lewis15aeee22025-09-04 10:51:01 -070079 if [[ "$top" =~ ^/google/cog ]]; then
80 nfs_type=cog-cartfs-symlink
81 else
82 nfs_type=local-cartfs-symlink
83 fi
Sam Lewis54ee0cc2025-08-25 12:46:35 -070084 elif [[ "$top" =~ ^/google/cog ]]; then
85 nfs_type=cog-symlink
86 elif [[ -f "$top/.abfs.sock" ]]; then
87 nfs_type=abfs
Sam Lewis51193302025-08-22 11:37:33 -070088 fi
89
90 export NETWORK_FILE_SYSTEM_TYPE=$nfs_type
91}
92
Sam Lewis2404c4a2024-09-23 20:06:02 +000093# This function sets up the build environment to be appropriate for Cog.
94function setup_cog_env_if_needed() {
95 local top=$(gettop)
96
97 # return early if not in a cog workspace
98 if [[ ! "$top" =~ ^/google/cog ]]; then
99 return 0
100 fi
101
Martin Simard49706bf2025-07-07 10:27:00 -0700102 clean_deleted_workspaces_in_cartfs
103
Sam Lewis2404c4a2024-09-23 20:06:02 +0000104 setup_cog_symlink
105
106 export ANDROID_BUILD_ENVIRONMENT_CONFIG="googler-cog"
107
108 # Running repo command within Cog workspaces is not supported, so override
109 # it with this function. If the user is running repo within a Cog workspace,
110 # we'll fail with an error, otherwise, we run the original repo command with
111 # the given args.
112 if ! ORIG_REPO_PATH=`which repo`; then
113 return 0
114 fi
115 function repo {
116 if [[ "${PWD}" == /google/cog/* ]]; then
117 echo -e "\e[01;31mERROR:\e[0mrepo command is disallowed within Cog workspaces."
118 kill -INT $$ # exits the script without exiting the user's shell
119 fi
120 ${ORIG_REPO_PATH} "$@"
121 }
122}
123
124# creates a symlink for the out/ dir when inside a cog workspace.
125function setup_cog_symlink() {
126 local out_dir=$(getoutdir)
127 local top=$(gettop)
128
Sam Lewisa7939b22025-03-10 12:00:35 -0700129 # return early if out dir is already a symlink.
Sam Lewis2404c4a2024-09-23 20:06:02 +0000130 if [[ -L "$out_dir" ]]; then
Sam Lewisa7939b22025-03-10 12:00:35 -0700131 destination=$(readlink "$out_dir")
132 # ensure the destination exists.
133 mkdir -p "$destination"
Sam Lewis2404c4a2024-09-23 20:06:02 +0000134 return 0
135 fi
136
137 # return early if out dir is not in the workspace
138 if [[ ! "$out_dir" =~ ^$top/ ]]; then
139 return 0
140 fi
141
142 local link_destination="${HOME}/.cog/android-build-out"
143
Martin Simard49706bf2025-07-07 10:27:00 -0700144 # When cartfs is mounted, use it as the destination for output directory.
145 local cartfs_mount_point=$(cartfs_mount_point)
146 if [[ -n "$cartfs_mount_point" ]]; then
147 local cog_workspace_name="$(basename "$(dirname "${top}")")"
148 link_destination="${cartfs_mount_point}/${cog_workspace_name}/out"
149 fi
150
Sam Lewis1513eab2024-09-24 19:47:08 +0000151 # remove existing out/ dir if it exists
Sam Lewis2404c4a2024-09-23 20:06:02 +0000152 if [[ -d "$out_dir" ]]; then
Sam Lewis1513eab2024-09-24 19:47:08 +0000153 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"
154 if ! rm -rf "$out_dir"; then
155 echo "Failed to remove existing out/ directory: $out_dir" >&2
Sam Lewis2404c4a2024-09-23 20:06:02 +0000156 kill -INT $$ # exits the script without exiting the user's shell
157 fi
158 fi
159
160 # create symlink
161 echo "Creating symlink: $out_dir -> $link_destination"
162 mkdir -p ${link_destination}
163 if ! ln -s "$link_destination" "$out_dir"; then
164 echo "Failed to create cog symlink: $out_dir -> $link_destination" >&2
165 kill -INT $$ # exits the script without exiting the user's shell
166 fi
167}
168
Joe Onorato344e4042022-12-05 15:15:36 -0800169function getoutdir
170{
171 local top=$(gettop)
172 local out_dir="${OUT_DIR:-}"
173 if [[ -z "${out_dir}" ]]; then
174 if [[ -n "${OUT_DIR_COMMON_BASE:-}" && -n "${top}" ]]; then
175 out_dir="${OUT_DIR_COMMON_BASE}/$(basename ${top})"
176 else
177 out_dir="out"
178 fi
179 fi
180 if [[ "${out_dir}" != /* ]]; then
181 out_dir="${top}/${out_dir}"
182 fi
183 echo "${out_dir}"
184}
185
Joe Onorato1b9ab292024-05-17 12:16:43 -0700186# Pretty print the build status and duration
187function _wrap_build()
188{
189 if [[ "${ANDROID_QUIET_BUILD:-}" == true ]]; then
190 "$@"
191 return $?
192 fi
193 local start_time=$(date +"%s")
194 "$@"
195 local ret=$?
196 local end_time=$(date +"%s")
197 local tdiff=$(($end_time-$start_time))
198 local hours=$(($tdiff / 3600 ))
199 local mins=$((($tdiff % 3600) / 60))
200 local secs=$(($tdiff % 60))
201 local ncolors=$(tput colors 2>/dev/null)
202 if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
203 color_failed=$'\E'"[0;31m"
204 color_success=$'\E'"[0;32m"
205 color_warning=$'\E'"[0;33m"
206 color_reset=$'\E'"[00m"
207 else
208 color_failed=""
209 color_success=""
210 color_reset=""
211 fi
212
213 echo
214 if [ $ret -eq 0 ] ; then
215 echo -n "${color_success}#### build completed successfully "
216 else
217 echo -n "${color_failed}#### failed to build some targets "
218 fi
219 if [ $hours -gt 0 ] ; then
Alexander Koskovicha20a7fb2024-10-13 21:33:23 -0400220 printf "(%02d:%02d:%02d (hh:mm:ss))" $hours $mins $secs
Joe Onorato1b9ab292024-05-17 12:16:43 -0700221 elif [ $mins -gt 0 ] ; then
Alexander Koskovicha20a7fb2024-10-13 21:33:23 -0400222 printf "(%02d:%02d (mm:ss))" $mins $secs
Joe Onorato1b9ab292024-05-17 12:16:43 -0700223 elif [ $secs -gt 0 ] ; then
Alexander Koskovicha20a7fb2024-10-13 21:33:23 -0400224 printf "(%d seconds)" $secs
Joe Onorato1b9ab292024-05-17 12:16:43 -0700225 fi
226 echo " ####${color_reset}"
227 echo
228 return $ret
229}
230
231
Joe Onorato1f6eddb2024-05-31 15:04:44 -0700232function log_tool_invocation()
233{
234 if [[ -z $ANDROID_TOOL_LOGGER ]]; then
235 return
236 fi
237
238 LOG_TOOL_TAG=$1
239 LOG_START_TIME=$(date +%s.%N)
240 trap '
241 exit_code=$?;
242 # Remove the trap to prevent duplicate log.
243 trap - EXIT;
244 $ANDROID_TOOL_LOGGER \
245 --tool_tag="${LOG_TOOL_TAG}" \
246 --start_timestamp="${LOG_START_TIME}" \
247 --end_timestamp="$(date +%s.%N)" \
248 --tool_args="$*" \
249 --exit_code="${exit_code}" \
250 ${ANDROID_TOOL_LOGGER_EXTRA_ARGS} \
251 > /dev/null 2>&1 &
252 exit ${exit_code}
253 ' SIGINT SIGTERM SIGQUIT EXIT
254}
Joe Onorato344e4042022-12-05 15:15:36 -0800255
Joe Onorato029c50a2024-12-09 09:38:01 -0800256# Import the build variables supplied as arguments into this shell's environment.
257# For absolute variables, prefix the variable name with a '/'. For example:
258# import_build_vars OUT_DIR DIST_DIR /HOST_OUT_EXECUTABLES
259# Returns nonzero if the build command failed. Stderr is passed through.
260function import_build_vars()
261{
262 require_top
263 local script
264 script=$(cd $TOP && build/soong/bin/get_build_vars "$@")
265 local ret=$?
266 if [ $ret -ne 0 ] ; then
267 return $ret
268 fi
269 eval "$script"
270 return $?
271}
Martin Simard49706bf2025-07-07 10:27:00 -0700272
273function cartfs_mount_point() {
Martin Simardde9366e2025-09-12 07:56:42 -0700274 # Make sure findmnt is installed.
275 if ! command -v findmnt &> /dev/null; then
276 return
277 fi
278
Martin Simard96c7e3e2025-07-08 09:06:20 -0700279 local cartfs_user_id="$(id -u cartfs 2>/dev/null)"
280 local cartfs_mount_point="$(findmnt -t fuse -O "user_id=${cartfs_user_id}" | tail -n +2 | awk '{print $1}')"
281 # Making sure $cartfs_user_id is not empty since findmnt will return mounts
282 # started by root when it is.
283 if [[ -n "$cartfs_user_id" ]] && [[ -n "$cartfs_mount_point" ]] && findmnt "$cartfs_mount_point" >/dev/null 2>&1; then
Martin Simard49706bf2025-07-07 10:27:00 -0700284 echo "$cartfs_mount_point"
Martin Simard49706bf2025-07-07 10:27:00 -0700285 fi
286}
287
288# Deletes cartfs folders that are mapped to deleted workspaces.
289function clean_deleted_workspaces_in_cartfs() {
290 local cartfs_mount_point=$(cartfs_mount_point)
291 if [[ -n "$cartfs_mount_point" ]]; then
292 local folders_list
293 folders_list=$(find "$cartfs_mount_point" -maxdepth 1 -type d)
294 if [[ -n "$folders_list" ]]; then
Martin Simard96c7e3e2025-07-08 09:06:20 -0700295 local log_file="${HOME}/.cartfs/cartfs_workspace_deletion.log"
296 mkdir -p "$(dirname "${log_file}")"
Martin Simard49706bf2025-07-07 10:27:00 -0700297 while read -r folder; do
298 if [[ "$folder" != "$cartfs_mount_point" ]]; then
299 local workspace_name="$(basename "${folder}")"
300 local workspaces_path="$(dirname "$(dirname "${top}")")"
301 local full_path="${workspaces_path}/${workspace_name}"
302 if [[ ! -d "${full_path}" ]]; then
Martin Simard96c7e3e2025-07-08 09:06:20 -0700303 local log_timestamp=$(date +"%Y-%m-%d %H:%M:%S")
304 echo "${log_timestamp}: The workspace ${workspace_name} does not exist, deleting ${folder} from cartfs" >> "${log_file}"
Martin Simard49706bf2025-07-07 10:27:00 -0700305 rm -Rf "${folder}"
306 fi
307 fi
308 done <<< "$folders_list"
309 fi
310 fi
311}