diff --git a/scripts/setup_go_workspace_for_soong.sh b/scripts/setup_go_workspace_for_soong.sh index e2fb9fa37..6374aae7f 100755 --- a/scripts/setup_go_workspace_for_soong.sh +++ b/scripts/setup_go_workspace_for_soong.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -# Copyright 2017 Google Inc. All rights reserved. +# Copyright 2019 Google Inc. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,23 +15,174 @@ set -e # See the License for the specific language governing permissions and # limitations under the License. -#mounts the components of soong into a directory structure that Go tools and editors expect +# Mounts the components of soong into a directory structure that Go tools +# and editors expect. -#move to the script's directory -cd "$(dirname $0)" -SCRIPT_PATH="$PWD" -#find the root of the Repo checkout -cd "${SCRIPT_PATH}"/../../.. -ANDROID_PATH="${PWD}" -OUTPUT_PATH="$(echo ${GOPATH} | sed 's/\:.*//')" #if GOPATH contains multiple paths, use the first one - -if [ -z "${OUTPUT_PATH}" ]; then - echo "Error; could not determine the desired location at which to create a Go-compatible workspace. Please update GOPATH to specify the desired destination directory" +##################################################################### +# Print the message to stderr with the prefix ERROR and abort this +# script. +##################################################################### +function log_FATAL() { + echo "ERROR:" "$*" >&2 exit 1 -fi +} -function confirm() { +##################################################################### +# Print the message to stderr with the prefix WARN +##################################################################### +function log_WARN() { + echo "WARN:" "$*" >&2 +} + + +##################################################################### +# Print the message with the prefix INFO. +##################################################################### +function log_INFO() { + echo "INFO:" "$*" +} + + +##################################################################### +# Find the root project directory of this repo. This is done by +# finding the directory of where this script lives and then go up one +# directory to check the ".repo" directory exist. If not, keep going +# up until we find the ".repo" file or we reached to the filesystem +# root. Project root directory is printed to stdout. +##################################################################### +function root_dir() ( + local dir + if ! dir="$("${readlink}" -e $(dirname "$0"))"; then + log_FATAL "failed to read the script's current directory." + fi + + dir=${dir}/../../.. + if ! dir="$("${readlink}" -e "${dir}")"; then + log_FATAL "Cannot find the root project directory" + fi + + echo "${dir}" +) + + +##################################################################### +# executes a shell command by printing out to the screen first and +# then evaluating the command. +##################################################################### +function execute() { + echo "$@" + eval "$@" +} + + +##################################################################### +# Returns the source directory of a passed in path from BIND_PATHS +# array. +##################################################################### +function bind_path_src_dir() ( + local -r bind_path="$1" + echo "${bind_path/%|*/}" +) + + +##################################################################### +# Returns the destination directory of a passed in path from +# BIND_PATHS array. +##################################################################### +function bind_path_dst_dir() ( + local -r bind_path="$1" + echo "${bind_path/#*|}" +) + + +##################################################################### +# Executes the bindfs command in linux. Expects $1 to be src +# directory and $2 to be destination directory. +##################################################################### +function linux_bind_dir() ( + execute bindfs "$1" "$2" +) + +##################################################################### +# Executes the fusermount -u command in linux. Expects $1 to be the +# destination directory. +##################################################################### +function linux_unbind_dir() ( + execute fusermount -u "$1" +) + +##################################################################### +# Executes the bindfs command in darwin. Expects $1 to be src +# directory and $2 to be destination directory. +##################################################################### +function darwin_bind_dir() ( + execute bindfs -o allow_recursion -n "$1" "$2" +) + + +##################################################################### +# Execute the umount command in darwin to unbind a directory. Expects +# $1 to be the destination directory +##################################################################### +function darwin_unbind_dir() ( + execute umount -f "$1" +) + + +##################################################################### +# Bind all the paths that are specified in the BIND_PATHS array. +##################################################################### +function bind_all() ( + local src_dir + local dst_dir + + for path in ${BIND_PATHS[@]}; do + src_dir=$(bind_path_src_dir "${path}") + + dst_dir=$(bind_path_dst_dir "${path}") + mkdir -p "${dst_dir}" + + "${bind_dir}" ${src_dir} "${dst_dir}" + done + + echo + log_INFO "Created GOPATH-compatible directory structure at ${OUTPUT_PATH}." +) + + +##################################################################### +# Unbind all the paths that are specified in the BIND_PATHS array. +##################################################################### +function unbind_all() ( + local dst_dir + local exit_code=0 + + # need to go into reverse since several parent directory may have been + # first before the child one. + for (( i=${#BIND_PATHS[@]}-1; i>=0; i-- )); do + dst_dir=$(bind_path_dst_dir "${BIND_PATHS[$i]}") + + # continue to unmount even one of them fails + if ! "${unbind_dir}" "${dst_dir}"; then + log_WARN "Failed to umount ${dst_dir}." + exit_code=1 + fi + done + + if [[ ${exit_code} -ne 0 ]]; then + exit ${exit_code} + fi + + echo + log_INFO "Unmounted the GOPATH-compatible directory structure at ${OUTPUT_PATH}." +) + + +##################################################################### +# Asks the user to create the GOPATH-compatible directory structure. +##################################################################### +function confirm() ( while true; do echo "Will create GOPATH-compatible directory structure at ${OUTPUT_PATH}" echo -n "Ok [Y/n]?" @@ -42,48 +193,162 @@ function confirm() { if [ "${decision}" == "n" ]; then return 1 else - echo "Invalid choice ${decision}; choose either 'y' or 'n'" + log_WARN "Invalid choice ${decision}; choose either 'y' or 'n'" fi fi done +) + + +##################################################################### +# Help function. +##################################################################### +function help() ( + cat </dev/null; then + log_FATAL "missing $1" + fi + } -function bindOne() { - #causes $newPath to mirror $existingPath - existingPath="$1" - newPath="$2" - mkdir -p "$newPath" - case $(uname -s) in + local bins + case "${os_type}" in Darwin) - echoAndDo bindfs -o allow_recursion -n "${existingPath}" "${newPath}" + bins=("bindfs" "greadlink") ;; Linux) - echoAndDo bindfs "${existingPath}" "${newPath}" + bins=("bindfs" "fusermount") ;; + *) + log_FATAL "${os_type} is not a recognized system." esac + + for bin in "${bins[@]}"; do + check "${bin}" + done +) + + +function main() { + parse_arguments "$@" + + check_exec_existence + + if [[ "${ACTION}" == "bind" ]]; then + if confirm; then + echo + bind_all + else + echo "skipping due to user request" + exit 1 + fi + else + echo + unbind_all + fi } -function echoAndDo() { - echo "$@" - eval "$@" -} +readonly os_type="$(uname -s)" +case "${os_type}" in + Darwin) + bind_dir=darwin_bind_dir + unbind_dir=darwin_unbind_dir + readlink=greadlink + ;; + Linux) + bind_dir=linux_bind_dir + unbind_dir=linux_unbind_dir + readlink=readlink + ;; + *) + log_FATAL "${os_type} is not a recognized system." +esac +readonly bind_dir +readonly unbind_dir +readonly readlink -if confirm; then - echo - bindAll -else - echo "skipping due to user request" - exit 1 + +if ! ANDROID_PATH="$(root_dir)"; then + log_FATAL "failed to find the root of the repo checkout" fi +readonly ANDROID_PATH + +#if GOPATH contains multiple paths, use the first one +if ! OUTPUT_PATH="$(echo ${GOPATH} | sed 's/\:.*//')"; then + log_FATAL "failed to extract the first GOPATH environment variable" +fi +readonly OUTPUT_PATH +if [ -z "${OUTPUT_PATH}" ]; then + log_FATAL "Could not determine the desired location at which to create a" \ + "Go-compatible workspace. Please update GOPATH to specify the" \ + "desired destination directory." +fi + +# Below are the paths to bind from src to dst. The paths are separated by | +# where the left side is the source and the right side is destination. +readonly BIND_PATHS=( + "${ANDROID_PATH}/build/blueprint|${OUTPUT_PATH}/src/github.com/google/blueprint" + "${ANDROID_PATH}/build/soong|${OUTPUT_PATH}/src/android/soong" + "${ANDROID_PATH}/art/build|${OUTPUT_PATH}/src/android/soong/art" + "${ANDROID_PATH}/external/golang-protobuf|${OUTPUT_PATH}/src/github.com/golang/protobuf" + "${ANDROID_PATH}/external/llvm/soong|${OUTPUT_PATH}/src/android/soong/llvm" + "${ANDROID_PATH}/external/clang/soong|${OUTPUT_PATH}/src/android/soong/clang" +) + +main "$@"