aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/setup_go_workspace_for_soong.sh
blob: 6374aae7fbb84233120e1fd8bdad7e9dba24d5b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
#!/bin/bash
set -e

# 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.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# 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.


#####################################################################
# Print the message to stderr with the prefix ERROR and abort this
# script.
#####################################################################
function log_FATAL() {
  echo "ERROR:" "$*" >&2
  exit 1
}

#####################################################################
# 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]?"
    read decision
    if [ "${decision}" == "y" -o "${decision}" == "Y" -o "${decision}" == "" ]; then
      return 0
    else
      if [ "${decision}" == "n" ]; then
        return 1
      else
        log_WARN "Invalid choice ${decision}; choose either 'y' or 'n'"
      fi
    fi
  done
)


#####################################################################
# Help function.
#####################################################################
function help() (
  cat <<EOF
Mounts the components of soong into a directory structure that Go tools
and editors expect.

  --help
    This help

  --bind
    Create the directory structure that Go tools and editors expect by
    binding the one to aosp build directory.

  --unbind
    Reverse operation of bind.

If no flags were specified, the --bind one is selected by default.
EOF
)


#####################################################################
# Parse the arguments passed in to this script.
#####################################################################
function parse_arguments() {
  while [[ -n "$1" ]]; do
    case "$1" in
          --bind)
            ACTION="bind"
            shift
            ;;
          --unbind)
            ACTION="unbind"
            shift
            ;;
          --help )
            help
            shift
            exit 0
            ;;
          *)
            log_WARN "Unknown option: $1"
            help
            exit 1
            ;;
    esac
  done

  if [[ -z "${ACTION}" ]]; then
    ACTION=bind
  fi
}


#####################################################################
# Verifies that a list of required binaries are installed in the
# host in order to run this script.
#####################################################################
function check_exec_existence() (
  function check() {
    if ! hash "$1" &>/dev/null; then
      log_FATAL "missing $1"
    fi
  }

  local bins
  case "${os_type}" in
    Darwin)
      bins=("bindfs" "greadlink")
      ;;
    Linux)
      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
}

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 ! 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 "$@"