golang.org/x/build@v0.0.0-20240506185731-218518f32b70/env/wasip1-wasm-wasmtime/install.sh (about) 1 #!/usr/bin/env bash 2 3 # Copied from 4 # https://github.com/volta-cli/volta/blob/master/dev/unix/volta-install.sh 5 6 # LICENSE: 7 8 # BSD 2-CLAUSE LICENSE 9 # 10 # Copyright (c) 2017, The Wasmtime Contributors. 11 # All rights reserved. 12 # 13 # This product includes: 14 # 15 # Contributions from LinkedIn Corporation 16 # Copyright (c) 2017, LinkedIn Corporation. 17 # 18 # Redistribution and use in source and binary forms, with or without 19 # modification, are permitted provided that the following conditions are met: 20 # 21 # 1. Redistributions of source code must retain the above copyright notice, this 22 # list of conditions and the following disclaimer. 23 # 2. Redistributions in binary form must reproduce the above copyright notice, 24 # this list of conditions and the following disclaimer in the documentation 25 # and/or other materials provided with the distribution. 26 # 27 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 28 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 31 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 34 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 # 38 # The views and conclusions contained in the software and documentation are those 39 # of the authors and should not be interpreted as representing official policies, 40 # either expressed or implied, of the FreeBSD Project. 41 42 get_latest_release() { 43 curl --silent "https://api.github.com/repos/bytecodealliance/wasmtime/releases/latest" | \ 44 grep tag_name | \ 45 cut -d '"' -f 4 46 } 47 48 release_url() { 49 echo "https://github.com/bytecodealliance/wasmtime/releases" 50 } 51 52 download_release_from_repo() { 53 local version="$1" 54 local arch="$2" 55 local os_info="$3" 56 local tmpdir="$4" 57 58 local filename="wasmtime-$version-$arch-$os_info.tar.xz" 59 local download_file="$tmpdir/$filename" 60 local archive_url="$(release_url)/download/$version/$filename" 61 info $archive_url 62 63 curl --progress-bar --show-error --location --fail "$archive_url" \ 64 --output "$download_file" && echo "$download_file" 65 } 66 67 usage() { 68 cat >&2 <<END_USAGE 69 wasmtime-install: The installer for Wasmtime 70 71 USAGE: 72 wasmtime-install [FLAGS] [OPTIONS] 73 74 FLAGS: 75 -h, --help Prints help information 76 77 OPTIONS: 78 --dev Compile and install Wasmtime locally, using the dev target 79 --release Compile and install Wasmtime locally, using the release target 80 --version <version> Install a specific release version of Wasmtime 81 END_USAGE 82 } 83 84 info() { 85 local action="$1" 86 local details="$2" 87 command printf '\033[1;32m%12s\033[0m %s\n' "$action" "$details" 1>&2 88 } 89 90 error() { 91 command printf '\033[1;31mError\033[0m: %s\n\n' "$1" 1>&2 92 } 93 94 warning() { 95 command printf '\033[1;33mWarning\033[0m: %s\n\n' "$1" 1>&2 96 } 97 98 request() { 99 command printf '\033[1m%s\033[0m\n' "$1" 1>&2 100 } 101 102 eprintf() { 103 command printf '%s\n' "$1" 1>&2 104 } 105 106 bold() { 107 command printf '\033[1m%s\033[0m' "$1" 108 } 109 110 # If file exists, echo it 111 echo_fexists() { 112 [ -f "$1" ] && echo "$1" 113 } 114 115 detect_profile() { 116 local shellname="$1" 117 local uname="$2" 118 119 if [ -f "$PROFILE" ]; then 120 echo "$PROFILE" 121 return 122 fi 123 124 # try to detect the current shell 125 case "$shellname" in 126 bash) 127 # Shells on macOS default to opening with a login shell, while Linuxes 128 # default to a *non*-login shell, so if this is macOS we look for 129 # `.bash_profile` first; if it's Linux, we look for `.bashrc` first. The 130 # `*` fallthrough covers more than just Linux: it's everything that is not 131 # macOS (Darwin). It can be made narrower later if need be. 132 case $uname in 133 Darwin) 134 echo_fexists "$HOME/.bash_profile" || echo_fexists "$HOME/.bashrc" 135 ;; 136 *) 137 echo_fexists "$HOME/.bashrc" || echo_fexists "$HOME/.bash_profile" 138 ;; 139 esac 140 ;; 141 zsh) 142 echo "$HOME/.zshrc" 143 ;; 144 fish) 145 echo "$HOME/.config/fish/config.fish" 146 ;; 147 *) 148 # Fall back to checking for profile file existence. Once again, the order 149 # differs between macOS and everything else. 150 local profiles 151 case $uname in 152 Darwin) 153 profiles=( .profile .bash_profile .bashrc .zshrc .config/fish/config.fish ) 154 ;; 155 *) 156 profiles=( .profile .bashrc .bash_profile .zshrc .config/fish/config.fish ) 157 ;; 158 esac 159 160 for profile in "${profiles[@]}"; do 161 echo_fexists "$HOME/$profile" && break 162 done 163 ;; 164 esac 165 } 166 167 # generate shell code to source the loading script and modify the path for the input profile 168 build_path_str() { 169 local profile="$1" 170 local profile_install_dir="$2" 171 172 if [[ $profile =~ \.fish$ ]]; then 173 # fish uses a little different syntax to modify the PATH 174 cat <<END_FISH_SCRIPT 175 176 set -gx WASMTIME_HOME "$profile_install_dir" 177 178 string match -r ".wasmtime" "\$PATH" > /dev/null; or set -gx PATH "\$WASMTIME_HOME/bin" \$PATH 179 END_FISH_SCRIPT 180 else 181 # bash and zsh 182 cat <<END_BASH_SCRIPT 183 184 export WASMTIME_HOME="$profile_install_dir" 185 186 export PATH="\$WASMTIME_HOME/bin:\$PATH" 187 END_BASH_SCRIPT 188 fi 189 } 190 191 # check for issue with WASMTIME_HOME 192 # if it is set, and exists, but is not a directory, the install will fail 193 wasmtime_home_is_ok() { 194 if [ -n "${WASMTIME_HOME-}" ] && [ -e "$WASMTIME_HOME" ] && ! [ -d "$WASMTIME_HOME" ]; then 195 error "\$WASMTIME_HOME is set but is not a directory ($WASMTIME_HOME)." 196 eprintf "Please check your profile scripts and environment." 197 return 1 198 fi 199 return 0 200 } 201 202 update_profile() { 203 local install_dir="$1" 204 205 local profile_install_dir=$(echo "$install_dir" | sed "s:^$HOME:\$HOME:") 206 local detected_profile="$(detect_profile $(basename "/$SHELL") $(uname -s) )" 207 local path_str="$(build_path_str "$detected_profile" "$profile_install_dir")" 208 info 'Editing' "user profile ($detected_profile)" 209 210 if [ -z "${detected_profile-}" ] ; then 211 error "No user profile found." 212 eprintf "Tried \$PROFILE ($PROFILE), ~/.bashrc, ~/.bash_profile, ~/.zshrc, ~/.profile, and ~/.config/fish/config.fish." 213 eprintf '' 214 eprintf "You can either create one of these and try again or add this to the appropriate file:" 215 eprintf "$path_str" 216 return 1 217 else 218 if ! command grep -qc 'WASMTIME_HOME' "$detected_profile"; then 219 command printf "$path_str" >> "$detected_profile" 220 else 221 warning "Your profile ($detected_profile) already mentions Wasmtime and has not been changed." 222 fi 223 fi 224 } 225 226 # Check if it is OK to upgrade to the new version 227 upgrade_is_ok() { 228 local will_install_version="$1" 229 local install_dir="$2" 230 local is_dev_install="$3" 231 232 local wasmtime_bin="$install_dir/wasmtime" 233 234 if [[ -n "$install_dir" && -x "$wasmtime_bin" ]]; then 235 local prev_version="$( ($wasmtime_bin --version 2>/dev/null || echo 0.1) | sed -E 's/^.*([0-9]+\.[0-9]+\.[0-9]+).*$/\1/')" 236 # if this is a local dev install, skip the equality check 237 # if installing the same version, this is a no-op 238 if [ "$is_dev_install" != "true" ] && [ "$prev_version" == "$will_install_version" ]; then 239 eprintf "Version $will_install_version already installed" 240 return 1 241 fi 242 # in the future, check $prev_version for incompatible upgrades 243 fi 244 return 0 245 } 246 247 # returns the os name to be used in the packaged release, 248 # including the openssl info if necessary 249 parse_os_info() { 250 local uname_str="$1" 251 local openssl_version="$2" 252 253 case "$uname_str" in 254 Linux) 255 echo "linux" 256 ;; 257 Darwin) 258 echo "macos" 259 ;; 260 *) 261 return 1 262 esac 263 return 0 264 } 265 266 parse_os_pretty() { 267 local uname_str="$1" 268 269 case "$uname_str" in 270 Linux) 271 echo "Linux" 272 ;; 273 Darwin) 274 echo "macOS" 275 ;; 276 *) 277 echo "$uname_str" 278 esac 279 } 280 281 # return true(0) if the element is contained in the input arguments 282 # called like: 283 # if element_in "foo" "${array[@]}"; then ... 284 element_in() { 285 local match="$1"; 286 shift 287 288 local element; 289 # loop over the input arguments and return when a match is found 290 for element in "$@"; do 291 [ "$element" == "$match" ] && return 0 292 done 293 return 1 294 } 295 296 create_tree() { 297 local install_dir="$1" 298 299 info 'Creating' "directory layout" 300 301 # .wasmtime/ 302 # bin/ 303 304 mkdir -p "$install_dir" 305 mkdir -p "$install_dir"/bin 306 } 307 308 install_version() { 309 local version_to_install="$1" 310 local install_dir="$2" 311 312 if ! wasmtime_home_is_ok; then 313 exit 1 314 fi 315 316 case "$version_to_install" in 317 latest) 318 local latest_version="$(get_latest_release)" 319 info 'Installing' "latest version of Wasmtime ($latest_version)" 320 install_release "$latest_version" "$install_dir" 321 ;; 322 local-dev) 323 info 'Installing' "Wasmtime locally after compiling" 324 install_local "dev" "$install_dir" 325 ;; 326 local-release) 327 info 'Installing' "Wasmtime locally after compiling with '--release'" 328 install_local "release" "$install_dir" 329 ;; 330 *) 331 # assume anything else is a specific version 332 info 'Installing' "Wasmtime version $version_to_install" 333 install_release "$version_to_install" "$install_dir" 334 ;; 335 esac 336 337 if [ "$?" == 0 ] 338 then 339 update_profile "$install_dir" && 340 info "Finished" 'installation. Open a new terminal to start using Wasmtime!' 341 fi 342 } 343 344 # parse the 'version = "X.Y.Z"' line from the input Cargo.toml contents 345 # and return the version string 346 parse_cargo_version() { 347 local contents="$1" 348 349 while read -r line 350 do 351 if [[ "$line" =~ ^version\ =\ \"(.*)\" ]] 352 then 353 echo "${BASH_REMATCH[1]}" 354 return 0 355 fi 356 done <<< "$contents" 357 358 error "Could not determine the current version from Cargo.toml" 359 return 1 360 } 361 362 install_release() { 363 local version="$1" 364 local install_dir="$2" 365 local is_dev_install="false" 366 367 info 'Checking' "for existing Wasmtime installation" 368 if upgrade_is_ok "$version" "$install_dir" "$is_dev_install" 369 then 370 download_archive="$(download_release "$version"; exit "$?")" 371 exit_status="$?" 372 if [ "$exit_status" != 0 ] 373 then 374 error "Could not download Wasmtime version '$version'. See $(release_url) for a list of available releases" 375 return "$exit_status" 376 fi 377 378 install_from_file "$download_archive" "$install_dir" 379 else 380 # existing legacy install, or upgrade problem 381 return 1 382 fi 383 } 384 385 install_local() { 386 local dev_or_release="$1" 387 local install_dir="$2" 388 # this is a local install, so skip the version equality check 389 local is_dev_install="true" 390 391 info 'Checking' "for existing Wasmtime installation" 392 install_version="$(parse_cargo_version "$(<Cargo.toml)" )" || return 1 393 if no_legacy_install && upgrade_is_ok "$install_version" "$install_dir" "$is_dev_install" 394 then 395 # compile and package the binaries, then install from that local archive 396 compiled_archive="$(compile_and_package "$dev_or_release")" && 397 install_from_file "$compiled_archive" "$install_dir" 398 else 399 # existing legacy install, or upgrade problem 400 return 1 401 fi 402 } 403 404 compile_and_package() { 405 local dev_or_release="$1" 406 407 local release_output 408 409 # get the directory of this script 410 # (from https://stackoverflow.com/a/246128) 411 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 412 413 # call the release script to create the packaged archive file 414 # '2> >(tee /dev/stderr)' copies stderr to stdout, to collect it and parse the filename 415 release_output="$( "$DIR/release.sh" "--$dev_or_release" 2> >(tee /dev/stderr) )" 416 [ "$?" != 0 ] && return 1 417 418 # parse the release filename and return that 419 if [[ "$release_output" =~ release\ in\ file\ (target[^\ ]+) ]]; then 420 echo "${BASH_REMATCH[1]}" 421 else 422 error "Could not determine output filename" 423 return 1 424 fi 425 } 426 427 download_release() { 428 local version="$1" 429 430 local arch="$(get_architecture)" 431 local uname_str="$(uname -s)" 432 local os_info 433 os_info="$(parse_os_info "$uname_str")" 434 if [ "$?" != 0 ]; then 435 error "The current operating system ($uname_str) does not appear to be supported by Wasmtime." 436 return 1 437 fi 438 local pretty_os_name="$(parse_os_pretty "$uname_str")" 439 440 info 'Fetching' "archive for $pretty_os_name, version $version" 441 # store the downloaded archive in a temporary directory 442 local download_dir="$(mktemp -d)" 443 download_release_from_repo "$version" "$arch" "$os_info" "$download_dir" 444 } 445 446 install_from_file() { 447 local archive="$1" 448 local copy_to="$2" 449 local extract_to="$(dirname $archive)" 450 local extracted_path="$extract_to/$(basename $archive .tar.xz)" 451 452 create_tree "$copy_to" 453 454 info 'Extracting' "Wasmtime binaries" 455 # extract the files to the temp directory 456 tar -xvf "$archive" -C "$extract_to" 457 458 # copy the files to the specified directory 459 # binaries go into the bin folder 460 cp "$extracted_path/wasmtime" "$copy_to/bin" 461 462 # the others directly into the specified folder 463 cp "$extracted_path/LICENSE" "$extracted_path/README.md" "$copy_to" 464 } 465 466 get_architecture() { 467 local arch="$(uname -m)" 468 case "$arch" in 469 # macOS on aarch64 says "arm64" instead. 470 arm64) 471 arch=aarch64 472 ;; 473 esac 474 echo "$arch" 475 } 476 477 check_architecture() { 478 local version="$1" 479 local arch="$2" 480 local os="$3" 481 482 # Local version always allowed. 483 if [[ "$version" == "local"* ]]; then 484 return 0 485 fi 486 487 # Otherwise, check the matrix of OS/architecture support. 488 case "$arch/$os" in 489 aarch64/Linux) 490 return 0 491 ;; 492 aarch64/Darwin) 493 return 0 494 ;; 495 s390x/Linux) 496 return 0 497 ;; 498 x86_64/*) 499 return 0 500 ;; 501 esac 502 503 error "Sorry! Wasmtime currently only provides pre-built binaries for x86_64 (Linux, macOS, Windows), aarch64 (Linux, macOS), and s390x (Linux)." 504 return 1 505 } 506 507 508 # return if sourced (for testing the functions above) 509 return 0 2>/dev/null 510 511 # default to installing the latest available version 512 version_to_install="latest" 513 514 # install to WASMTIME_HOME, defaulting to ~/.wasmtime 515 install_dir="${WASMTIME_HOME:-"$HOME/.wasmtime"}" 516 517 # parse command line options 518 while [ $# -gt 0 ] 519 do 520 arg="$1" 521 522 case "$arg" in 523 -h|--help) 524 usage 525 exit 0 526 ;; 527 --dev) 528 shift # shift off the argument 529 version_to_install="local-dev" 530 ;; 531 --release) 532 shift # shift off the argument 533 version_to_install="local-release" 534 ;; 535 --version) 536 shift # shift off the argument 537 version_to_install="$1" 538 shift # shift off the value 539 ;; 540 *) 541 error "unknown option: '$arg'" 542 usage 543 exit 1 544 ;; 545 esac 546 done 547 548 check_architecture "$version_to_install" "$(get_architecture)" "$(uname)" || exit 1 549 550 install_version "$version_to_install" "$install_dir"