]> git.proxmox.com Git - rustc.git/blob - src/etc/rustup.sh
Imported Upstream version 1.0.0~beta
[rustc.git] / src / etc / rustup.sh
1 #!/bin/sh
2 # Copyright 2014 The Rust Project Developers. See the COPYRIGHT
3 # file at the top-level directory of this distribution and at
4 # http://rust-lang.org/COPYRIGHT.
5 #
6 # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7 # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8 # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9 # option. This file may not be copied, modified, or distributed
10 # except according to those terms.
11
12
13 msg() {
14 echo "rustup: $1"
15 }
16
17 step_msg() {
18 msg
19 msg "$1"
20 msg
21 }
22
23 warn() {
24 echo "rustup: WARNING: $1"
25 }
26
27 err() {
28 echo "rustup: error: $1"
29 exit 1
30 }
31
32 need_ok() {
33 if [ $? -ne 0 ]
34 then
35 err "$1"
36 fi
37 }
38
39
40 putvar() {
41 local T
42 eval T=\$$1
43 eval TLEN=\${#$1}
44 if [ $TLEN -gt 35 ]
45 then
46 printf "rustup: %-20s := %.35s ...\n" $1 "$T"
47 else
48 printf "rustup: %-20s := %s %s\n" $1 "$T" "$2"
49 fi
50 }
51
52 probe() {
53 local V=$1
54 shift
55 local P
56 local T
57 for P
58 do
59 T=$(which $P 2>&1)
60 if [ $? -eq 0 ]
61 then
62 VER0=$($P --version 2>/dev/null | head -1 \
63 | sed -e 's/[^0-9]*\([vV]\?[0-9.]\+[^ ]*\).*/\1/' )
64 if [ $? -eq 0 -a "x${VER0}" != "x" ]
65 then
66 VER="($VER0)"
67 else
68 VER=""
69 fi
70 break
71 else
72 VER=""
73 T=""
74 fi
75 done
76 eval $V=\$T
77 putvar $V "$VER"
78 }
79
80 probe_need() {
81 local V=$1
82 probe $*
83 eval VV=\$$V
84 if [ -z "$VV" ]
85 then
86 err "needed, but unable to find any of: $*"
87 fi
88 }
89
90
91 valopt() {
92 VAL_OPTIONS="$VAL_OPTIONS $1"
93
94 local OP=$1
95 local DEFAULT=$2
96 shift
97 shift
98 local DOC="$*"
99 if [ $HELP -eq 0 ]
100 then
101 local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
102 local V="CFG_${UOP}"
103 eval $V="$DEFAULT"
104 for arg in $CFG_ARGS
105 do
106 if echo "$arg" | grep -q -- "--$OP="
107 then
108 val=$(echo "$arg" | cut -f2 -d=)
109 eval $V=$val
110 fi
111 done
112 putvar $V
113 else
114 if [ -z "$DEFAULT" ]
115 then
116 DEFAULT="<none>"
117 fi
118 OP="${OP}=[${DEFAULT}]"
119 printf " --%-30s %s\n" "$OP" "$DOC"
120 fi
121 }
122
123 opt() {
124 BOOL_OPTIONS="$BOOL_OPTIONS $1"
125
126 local OP=$1
127 local DEFAULT=$2
128 shift
129 shift
130 local DOC="$*"
131 local FLAG=""
132
133 if [ $DEFAULT -eq 0 ]
134 then
135 FLAG="enable"
136 else
137 FLAG="disable"
138 DOC="don't $DOC"
139 fi
140
141 if [ $HELP -eq 0 ]
142 then
143 for arg in $CFG_ARGS
144 do
145 if [ "$arg" = "--${FLAG}-${OP}" ]
146 then
147 OP=$(echo $OP | tr 'a-z-' 'A-Z_')
148 FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
149 local V="CFG_${FLAG}_${OP}"
150 eval $V=1
151 putvar $V
152 fi
153 done
154 else
155 if [ ! -z "$META" ]
156 then
157 OP="$OP=<$META>"
158 fi
159 printf " --%-30s %s\n" "$FLAG-$OP" "$DOC"
160 fi
161 }
162
163 flag() {
164 BOOL_OPTIONS="$BOOL_OPTIONS $1"
165
166 local OP=$1
167 shift
168 local DOC="$*"
169
170 if [ $HELP -eq 0 ]
171 then
172 for arg in $CFG_ARGS
173 do
174 if [ "$arg" = "--${OP}" ]
175 then
176 OP=$(echo $OP | tr 'a-z-' 'A-Z_')
177 local V="CFG_${OP}"
178 eval $V=1
179 putvar $V
180 fi
181 done
182 else
183 if [ ! -z "$META" ]
184 then
185 OP="$OP=<$META>"
186 fi
187 printf " --%-30s %s\n" "$OP" "$DOC"
188 fi
189 }
190
191 validate_opt() {
192 for arg in $CFG_ARGS
193 do
194 isArgValid=0
195 for option in $BOOL_OPTIONS
196 do
197 if test --disable-$option = $arg
198 then
199 isArgValid=1
200 fi
201 if test --enable-$option = $arg
202 then
203 isArgValid=1
204 fi
205 if test --$option = $arg
206 then
207 isArgValid=1
208 fi
209 done
210 for option in $VAL_OPTIONS
211 do
212 if echo "$arg" | grep -q -- "--$option="
213 then
214 isArgValid=1
215 fi
216 done
217 if [ "$arg" = "--help" ]
218 then
219 echo
220 echo "No more help available for Configure options,"
221 echo "check the Wiki or join our IRC channel"
222 break
223 else
224 if test $isArgValid -eq 0
225 then
226 err "Option '$arg' is not recognized"
227 fi
228 fi
229 done
230 }
231
232 create_tmp_dir() {
233 local TMP_DIR=`pwd`/rustup-tmp-install
234
235 rm -Rf "${TMP_DIR}"
236 need_ok "failed to remove temporary installation directory"
237
238 mkdir -p "${TMP_DIR}"
239 need_ok "failed to create create temporary installation directory"
240
241 echo $TMP_DIR
242 }
243
244 # Make `tr` locale independent
245 LC_CTYPE=C
246
247 probe_need CFG_CURL curl
248 probe_need CFG_TAR tar
249 probe_need CFG_FILE file
250
251 probe CFG_SHA256SUM sha256sum
252 probe CFG_SHASUM shasum
253
254 if [ -z "$CFG_SHA256SUM" -a -z "$CFG_SHASUM" ]; then
255 err "unable to find either sha256sum or shasum"
256 fi
257
258 calculate_hash() {
259 if [ -n "$CFG_SHA256SUM" ]; then
260 ${CFG_SHA256SUM} $@
261 else
262 ${CFG_SHASUM} -a 256 $@
263 fi
264 }
265
266 CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
267 CFG_SELF="$0"
268 CFG_ARGS="$@"
269
270 HELP=0
271 if [ "$1" = "--help" ]
272 then
273 HELP=1
274 shift
275 echo
276 echo "Usage: $CFG_SELF [options]"
277 echo
278 echo "Options:"
279 echo
280 else
281 step_msg "processing $CFG_SELF args"
282 fi
283
284 OPTIONS=""
285 BOOL_OPTIONS=""
286 VAL_OPTIONS=""
287
288 flag uninstall "only uninstall from the installation prefix"
289 valopt prefix "" "set installation prefix"
290 valopt date "" "use the YYYY-MM-DD nightly instead of the current nightly"
291 valopt channel "beta" "use the selected release channel [beta]"
292 flag save "save the downloaded nightlies to ~/.rustup"
293
294 if [ $HELP -eq 1 ]
295 then
296 echo
297 exit 0
298 fi
299
300 step_msg "validating $CFG_SELF args"
301 validate_opt
302
303
304 # Platform detection copied from `configure`
305
306 CFG_OSTYPE=$(uname -s)
307 CFG_CPUTYPE=$(uname -m)
308
309 if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
310 then
311 # Darwin's `uname -m` lies and always returns i386. We have to use sysctl
312 # instead.
313 if sysctl hw.optional.x86_64 | grep -q ': 1'
314 then
315 CFG_CPUTYPE=x86_64
316 fi
317 fi
318
319 # The goal here is to come up with the same triple as LLVM would,
320 # at least for the subset of platforms we're willing to target.
321
322 case $CFG_OSTYPE in
323
324 Linux)
325 CFG_OSTYPE=unknown-linux-gnu
326 ;;
327
328 FreeBSD)
329 CFG_OSTYPE=unknown-freebsd
330 ;;
331
332 Darwin)
333 CFG_OSTYPE=apple-darwin
334 ;;
335
336 MINGW32*)
337 CFG_OSTYPE=pc-mingw32
338 ;;
339 # Thad's Cygwin identifiers below
340
341 # Vista 32 bit
342 CYGWIN_NT-6.0)
343 CFG_OSTYPE=pc-mingw32
344 CFG_CPUTYPE=i686
345 ;;
346
347 # Vista 64 bit
348 CYGWIN_NT-6.0-WOW64)
349 CFG_OSTYPE=w64-mingw32
350 CFG_CPUTYPE=x86_64
351 ;;
352
353 # Win 7 32 bit
354 CYGWIN_NT-6.1)
355 CFG_OSTYPE=pc-mingw32
356 CFG_CPUTYPE=i686
357 ;;
358
359 # Win 7 64 bit
360 CYGWIN_NT-6.1-WOW64)
361 CFG_OSTYPE=w64-mingw32
362 CFG_CPUTYPE=x86_64
363 ;;
364
365 # We do not detect other OS such as XP/2003 using 64 bit using uname.
366 # If we want to in the future, we will need to use Cygwin
367 # Chuck's csih helper in /usr/lib/csih/winProductName.exe or alternative.
368 *)
369 err "unknown OS type: $CFG_OSTYPE"
370 ;;
371 esac
372
373
374 case $CFG_CPUTYPE in
375
376 i386 | i486 | i686 | i786 | x86)
377 CFG_CPUTYPE=i686
378 ;;
379
380 xscale | arm)
381 CFG_CPUTYPE=arm
382 ;;
383
384 x86_64 | x86-64 | x64 | amd64)
385 CFG_CPUTYPE=x86_64
386 ;;
387
388 *)
389 err "unknown CPU type: $CFG_CPUTYPE"
390 esac
391
392 # Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation
393 if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ]
394 then
395 "${CFG_FILE}" -L "$SHELL" | grep -q "x86[_-]64"
396 if [ $? != 0 ]; then
397 CFG_CPUTYPE=i686
398 fi
399 fi
400
401 HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
402
403 # Is this a triple we have nightlies for?
404 case $HOST_TRIPLE in
405
406 x86_64-unknown-linux-gnu)
407 ;;
408
409 i686-unknown-linux-gnu)
410 ;;
411
412 x86_64-apple-darwin)
413 ;;
414
415 i686-apple-darwin)
416 ;;
417
418 *)
419 err "rustup.sh doesn't work for host $HOST_TRIPLE"
420
421 esac
422
423 msg "host triple: ${HOST_TRIPLE}"
424
425 CFG_INSTALL_FLAGS=""
426 if [ -n "${CFG_UNINSTALL}" ]
427 then
428 CFG_INSTALL_FLAGS="${CFG_INSTALL_FLAGS} --uninstall"
429 fi
430
431 if [ -n "${CFG_PREFIX}" ]
432 then
433 CFG_INSTALL_FLAGS="${CFG_INSTALL_FLAGS} --prefix=${CFG_PREFIX}"
434 fi
435
436 CFG_TMP_DIR=$(mktemp -d 2>/dev/null \
437 || mktemp -d -t 'rustup-tmp-install' 2>/dev/null \
438 || create_tmp_dir)
439
440 # If we're saving nightlies and we didn't specify which one, grab the latest
441 # version from the perspective of the server. Buildbot has typically finished
442 # building and uploading by ~8UTC, but we want to include a little buffer.
443 #
444 # FIXME It would be better to use the known most recent nightly that has been
445 # built. This is waiting on a change to have buildbot publish metadata that
446 # can be queried.
447 if [ -n "${CFG_SAVE}" -a -z "${CFG_DATE}" ];
448 then
449 CFG_DATE=`TZ=Etc/UTC+9 date "+%Y-%m-%d"`
450 fi
451
452 RUST_URL="https://static.rust-lang.org/dist"
453 case "$CFG_CHANNEL" in
454 nightly)
455 # add a date suffix if we want a particular nightly.
456 if [ -n "${CFG_DATE}" ];
457 then
458 RUST_URL="${RUST_URL}/${CFG_DATE}"
459 fi
460
461 RUST_PACKAGE_NAME=rust-nightly
462 ;;
463 beta)
464 RUST_PACKAGE_NAME=rust-1.0.0-beta
465 ;;
466 *)
467 err "Currently 'beta' and 'nightly' are the only supported channels"
468 esac
469
470 RUST_PACKAGE_NAME_AND_TRIPLE="${RUST_PACKAGE_NAME}-${HOST_TRIPLE}"
471 RUST_TARBALL_NAME="${RUST_PACKAGE_NAME_AND_TRIPLE}.tar.gz"
472 RUST_LOCAL_INSTALL_DIR="${CFG_TMP_DIR}/${RUST_PACKAGE_NAME_AND_TRIPLE}"
473 RUST_LOCAL_INSTALL_SCRIPT="${RUST_LOCAL_INSTALL_DIR}/install.sh"
474
475 download_hash() {
476 msg "Downloading ${remote_sha256}"
477 remote_sha256=`"${CFG_CURL}" -f "${remote_sha256}"`
478 if [ -n "${CFG_SAVE}" ]; then
479 echo "${remote_sha256}" > "${local_sha_file}"
480 fi
481 if [ "$?" -ne 0 ]; then
482 rm -Rf "${CFG_TMP_DIR}"
483 err "Failed to download ${remote_url}"
484 fi
485 }
486
487 verify_hash() {
488 remote_sha256="$1"
489 local_file="$2"
490 local_sha_file="${local_file}.sha256"
491
492 if [ -n "${CFG_SAVE}" ]; then
493 if [ -f "${local_sha_file}" ]; then
494 msg "Local ${local_sha_file} exists, treating as remote hash"
495 remote_sha256=`cat "${local_sha_file}"`
496 else
497 download_hash
498 fi
499 else
500 download_hash
501 fi
502
503 msg "Verifying hash"
504 local_sha256=$(calculate_hash "${local_file}")
505 if [ "$?" -ne 0 ]; then
506 rm -Rf "${CFG_TMP_DIR}"
507 err "Failed to compute hash for ${local_tarball}"
508 fi
509
510 # We only need the sha, not the filenames
511 remote_sha256=`echo ${remote_sha256} | cut -f 1 -d ' '`
512 local_sha256=`echo ${local_sha256} | cut -f 1 -d ' '`
513
514 if [ "${remote_sha256}" != "${local_sha256}" ]; then
515 rm -Rf "${CFG_TMP_DIR}"
516 errmsg="invalid sha256.\n"
517 errmsg="$errmsg ${remote_sha256}\t${remote_tarball}\n"
518 errmsg="$errmsg ${local_sha256}\t${local_tarball}"
519 err "$errmsg"
520 fi
521 }
522
523 # Fetch the package. Optionally caches the tarballs.
524 download_package() {
525 remote_tarball="$1"
526 local_tarball="$2"
527 remote_sha256="${remote_tarball}.sha256"
528
529 # Check if we've already downloaded this file.
530 if [ -e "${local_tarball}.tmp" ]; then
531 msg "Resuming ${remote_tarball} to ${local_tarball}"
532
533 "${CFG_CURL}" -f -C - -o "${local_tarball}.tmp" "${remote_tarball}"
534 if [ $? -ne 0 ]
535 then
536 rm -Rf "${CFG_TMP_DIR}"
537 err "failed to download installer"
538 fi
539
540 mv "${local_tarball}.tmp" "${local_tarball}"
541 elif [ ! -e "${local_tarball}" ]; then
542 msg "Downloading ${remote_tarball} to ${local_tarball}"
543
544 "${CFG_CURL}" -f -o "${local_tarball}.tmp" "${remote_tarball}"
545 if [ $? -ne 0 ]
546 then
547 rm -Rf "${CFG_TMP_DIR}"
548 err "failed to download installer"
549 fi
550
551 mv "${local_tarball}.tmp" "${local_tarball}"
552 fi
553
554 verify_hash "${remote_sha256}" "${local_tarball}"
555 }
556
557 # Wrap all the commands needed to install a package.
558 install_package() {
559 local_tarball="$1"
560 install_script="$2"
561
562 msg "Extracting ${local_tarball}"
563 (cd "${CFG_TMP_DIR}" && "${CFG_TAR}" -xzf "${local_tarball}")
564 if [ $? -ne 0 ]; then
565 rm -Rf "${CFG_TMP_DIR}"
566 err "failed to unpack installer"
567 fi
568
569 sh "${install_script}" "${CFG_INSTALL_FLAGS}"
570 if [ $? -ne 0 ]
571 then
572 rm -Rf "${CFG_TMP_DIR}"
573 err "failed to install Rust"
574 fi
575 }
576
577 # It's possible that curl could be interrupted partway though downloading
578 # `rustup.sh`, truncating the file. This could be especially bad if we were in
579 # the middle of a line that would run "rm -rf ". To protect against this, we
580 # wrap up the `rustup.sh` destructive functionality in this helper function,
581 # which we call as the last thing we do. This means we will not do anything
582 # unless we have the entire file downloaded.
583 install_packages() {
584 rm -Rf "${CFG_TMP_DIR}"
585 need_ok "failed to remove temporary installation directory"
586
587 mkdir -p "${CFG_TMP_DIR}"
588 need_ok "failed to create create temporary installation directory"
589
590 # If we're saving our nightlies, put them in $HOME/.rustup.
591 if [ -n "${CFG_SAVE}" ]
592 then
593 RUST_DOWNLOAD_DIR="${HOME}/.rustup/${CFG_DATE}"
594 else
595 RUST_DOWNLOAD_DIR="${CFG_TMP_DIR}"
596 fi
597
598 mkdir -p "${RUST_DOWNLOAD_DIR}"
599 need_ok "failed to create create download directory"
600
601 RUST_LOCAL_TARBALL="${RUST_DOWNLOAD_DIR}/${RUST_TARBALL_NAME}"
602
603 download_package \
604 "${RUST_URL}/${RUST_TARBALL_NAME}" \
605 "${RUST_LOCAL_TARBALL}"
606
607 install_package \
608 "${RUST_LOCAL_TARBALL}" \
609 "${RUST_LOCAL_INSTALL_SCRIPT}"
610
611 rm -Rf "${CFG_TMP_DIR}"
612 need_ok "couldn't rm temporary installation directory"
613 }
614
615 install_packages