1#!/bin/bash 2set -e 3 4# Copyright 2019 Google Inc. All rights reserved. 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18# Mounts the components of soong into a directory structure that Go tools 19# and editors expect. 20 21 22##################################################################### 23# Print the message to stderr with the prefix ERROR and abort this 24# script. 25##################################################################### 26function log_FATAL() { 27 echo "ERROR:" "$*" >&2 28 exit 1 29} 30 31##################################################################### 32# Print the message to stderr with the prefix WARN 33##################################################################### 34function log_WARN() { 35 echo "WARN:" "$*" >&2 36} 37 38 39##################################################################### 40# Print the message with the prefix INFO. 41##################################################################### 42function log_INFO() { 43 echo "INFO:" "$*" 44} 45 46 47##################################################################### 48# Find the root project directory of this repo. This is done by 49# finding the directory of where this script lives and then go up one 50# directory to check the ".repo" directory exist. If not, keep going 51# up until we find the ".repo" file or we reached to the filesystem 52# root. Project root directory is printed to stdout. 53##################################################################### 54function root_dir() ( 55 local dir 56 if ! dir="$("${readlink}" -e $(dirname "$0"))"; then 57 log_FATAL "failed to read the script's current directory." 58 fi 59 60 dir=${dir}/../../.. 61 if ! dir="$("${readlink}" -e "${dir}")"; then 62 log_FATAL "Cannot find the root project directory" 63 fi 64 65 echo "${dir}" 66) 67 68 69##################################################################### 70# executes a shell command by printing out to the screen first and 71# then evaluating the command. 72##################################################################### 73function execute() { 74 echo "$@" 75 eval "$@" 76} 77 78 79##################################################################### 80# Returns the source directory of a passed in path from BIND_PATHS 81# array. 82##################################################################### 83function bind_path_src_dir() ( 84 local -r bind_path="$1" 85 echo "${bind_path/%|*/}" 86) 87 88 89##################################################################### 90# Returns the destination directory of a passed in path from 91# BIND_PATHS array. 92##################################################################### 93function bind_path_dst_dir() ( 94 local -r bind_path="$1" 95 echo "${bind_path/#*|}" 96) 97 98 99##################################################################### 100# Executes the bindfs command in linux. Expects $1 to be src 101# directory and $2 to be destination directory. 102##################################################################### 103function linux_bind_dir() ( 104 execute bindfs "$1" "$2" 105) 106 107##################################################################### 108# Executes the fusermount -u command in linux. Expects $1 to be the 109# destination directory. 110##################################################################### 111function linux_unbind_dir() ( 112 execute fusermount -u "$1" 113) 114 115##################################################################### 116# Executes the bindfs command in darwin. Expects $1 to be src 117# directory and $2 to be destination directory. 118##################################################################### 119function darwin_bind_dir() ( 120 execute bindfs -o allow_recursion -n "$1" "$2" 121) 122 123 124##################################################################### 125# Execute the umount command in darwin to unbind a directory. Expects 126# $1 to be the destination directory 127##################################################################### 128function darwin_unbind_dir() ( 129 execute umount -f "$1" 130) 131 132 133##################################################################### 134# Bind all the paths that are specified in the BIND_PATHS array. 135##################################################################### 136function bind_all() ( 137 local src_dir 138 local dst_dir 139 140 for path in ${BIND_PATHS[@]}; do 141 src_dir=$(bind_path_src_dir "${path}") 142 143 dst_dir=$(bind_path_dst_dir "${path}") 144 mkdir -p "${dst_dir}" 145 146 "${bind_dir}" ${src_dir} "${dst_dir}" 147 done 148 149 echo 150 log_INFO "Created GOPATH-compatible directory structure at ${OUTPUT_PATH}." 151) 152 153 154##################################################################### 155# Unbind all the paths that are specified in the BIND_PATHS array. 156##################################################################### 157function unbind_all() ( 158 local dst_dir 159 local exit_code=0 160 161 # need to go into reverse since several parent directory may have been 162 # first before the child one. 163 for (( i=${#BIND_PATHS[@]}-1; i>=0; i-- )); do 164 dst_dir=$(bind_path_dst_dir "${BIND_PATHS[$i]}") 165 166 # continue to unmount even one of them fails 167 if ! "${unbind_dir}" "${dst_dir}"; then 168 log_WARN "Failed to umount ${dst_dir}." 169 exit_code=1 170 fi 171 done 172 173 if [[ ${exit_code} -ne 0 ]]; then 174 exit ${exit_code} 175 fi 176 177 echo 178 log_INFO "Unmounted the GOPATH-compatible directory structure at ${OUTPUT_PATH}." 179) 180 181 182##################################################################### 183# Asks the user to create the GOPATH-compatible directory structure. 184##################################################################### 185function confirm() ( 186 while true; do 187 echo "Will create GOPATH-compatible directory structure at ${OUTPUT_PATH}" 188 echo -n "Ok [Y/n]?" 189 read decision 190 if [ "${decision}" == "y" -o "${decision}" == "Y" -o "${decision}" == "" ]; then 191 return 0 192 else 193 if [ "${decision}" == "n" ]; then 194 return 1 195 else 196 log_WARN "Invalid choice ${decision}; choose either 'y' or 'n'" 197 fi 198 fi 199 done 200) 201 202 203##################################################################### 204# Help function. 205##################################################################### 206function help() ( 207 cat <<EOF 208Mounts the components of soong into a directory structure that Go tools 209and editors expect. 210 211 --help 212 This help 213 214 --bind 215 Create the directory structure that Go tools and editors expect by 216 binding the one to aosp build directory. 217 218 --unbind 219 Reverse operation of bind. 220 221If no flags were specified, the --bind one is selected by default. 222EOF 223) 224 225 226##################################################################### 227# Parse the arguments passed in to this script. 228##################################################################### 229function parse_arguments() { 230 while [[ -n "$1" ]]; do 231 case "$1" in 232 --bind) 233 ACTION="bind" 234 shift 235 ;; 236 --unbind) 237 ACTION="unbind" 238 shift 239 ;; 240 --help ) 241 help 242 shift 243 exit 0 244 ;; 245 *) 246 log_WARN "Unknown option: $1" 247 help 248 exit 1 249 ;; 250 esac 251 done 252 253 if [[ -z "${ACTION}" ]]; then 254 ACTION=bind 255 fi 256} 257 258 259##################################################################### 260# Verifies that a list of required binaries are installed in the 261# host in order to run this script. 262##################################################################### 263function check_exec_existence() ( 264 function check() { 265 if ! hash "$1" &>/dev/null; then 266 log_FATAL "missing $1" 267 fi 268 } 269 270 local bins 271 case "${os_type}" in 272 Darwin) 273 bins=("bindfs" "greadlink") 274 ;; 275 Linux) 276 bins=("bindfs" "fusermount") 277 ;; 278 *) 279 log_FATAL "${os_type} is not a recognized system." 280 esac 281 282 for bin in "${bins[@]}"; do 283 check "${bin}" 284 done 285) 286 287 288function main() { 289 parse_arguments "$@" 290 291 check_exec_existence 292 293 if [[ "${ACTION}" == "bind" ]]; then 294 if confirm; then 295 echo 296 bind_all 297 else 298 echo "skipping due to user request" 299 exit 1 300 fi 301 else 302 echo 303 unbind_all 304 fi 305} 306 307readonly os_type="$(uname -s)" 308case "${os_type}" in 309 Darwin) 310 bind_dir=darwin_bind_dir 311 unbind_dir=darwin_unbind_dir 312 readlink=greadlink 313 ;; 314 Linux) 315 bind_dir=linux_bind_dir 316 unbind_dir=linux_unbind_dir 317 readlink=readlink 318 ;; 319 *) 320 log_FATAL "${os_type} is not a recognized system." 321esac 322readonly bind_dir 323readonly unbind_dir 324readonly readlink 325 326 327if ! ANDROID_PATH="$(root_dir)"; then 328 log_FATAL "failed to find the root of the repo checkout" 329fi 330readonly ANDROID_PATH 331 332#if GOPATH contains multiple paths, use the first one 333if ! OUTPUT_PATH="$(echo ${GOPATH} | sed 's/\:.*//')"; then 334 log_FATAL "failed to extract the first GOPATH environment variable" 335fi 336readonly OUTPUT_PATH 337if [ -z "${OUTPUT_PATH}" ]; then 338 log_FATAL "Could not determine the desired location at which to create a" \ 339 "Go-compatible workspace. Please update GOPATH to specify the" \ 340 "desired destination directory." 341fi 342 343# Below are the paths to bind from src to dst. The paths are separated by | 344# where the left side is the source and the right side is destination. 345readonly BIND_PATHS=( 346 "${ANDROID_PATH}/build/blueprint|${OUTPUT_PATH}/src/github.com/google/blueprint" 347 "${ANDROID_PATH}/build/soong|${OUTPUT_PATH}/src/android/soong" 348 "${ANDROID_PATH}/art/build|${OUTPUT_PATH}/src/android/soong/art" 349 "${ANDROID_PATH}/external/golang-protobuf|${OUTPUT_PATH}/src/github.com/golang/protobuf" 350 "${ANDROID_PATH}/external/llvm/soong|${OUTPUT_PATH}/src/android/soong/llvm" 351 "${ANDROID_PATH}/external/clang/soong|${OUTPUT_PATH}/src/android/soong/clang" 352 "${ANDROID_PATH}/external/robolectric-shadows/soong|${OUTPUT_PATH}/src/android/soong/robolectric" 353) 354 355main "$@" 356