ghcup 31 KB
Newer Older
Julian Ospald's avatar
Julian Ospald committed
1
#!/bin/sh
Julian Ospald's avatar
Julian Ospald committed
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
#
# Copyright (c) 2018, Julian Ospald <hasufell@posteo.de>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of the <ORGANIZATION> nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

30 31
# TODO:
#   - make removal more robust
Julian Ospald's avatar
Julian Ospald committed
32

33

Julian Ospald's avatar
Julian Ospald committed
34 35 36 37 38

    ##########################
    #--[ Global Variables ]--#
    ##########################

Julian Ospald's avatar
Julian Ospald committed
39

Julian Ospald's avatar
Julian Ospald committed
40 41 42
# @VARIABLE: VERSION
# @DESCRIPTION:
# Version of this script.
Julian Ospald's avatar
Julian Ospald committed
43
VERSION=0.0.5
Julian Ospald's avatar
Julian Ospald committed
44 45 46 47

# @VARIABLE: SCRIPT
# @DESCRIPTION:
# Name of this script.
Julian Ospald's avatar
Julian Ospald committed
48
SCRIPT="$(basename "$0")"
Julian Ospald's avatar
Julian Ospald committed
49 50 51 52

# @VARIABLE: VERBOSE
# @DESCRIPTION:
# Whether to print verbose messages in this script.
Julian Ospald's avatar
Julian Ospald committed
53
VERBOSE=false
Julian Ospald's avatar
Julian Ospald committed
54 55 56 57

# @VARIABLE: FORCE
# @DESCRIPTION:
# Whether to force installation and overwrite files.
58
FORCE=false
Julian Ospald's avatar
Julian Ospald committed
59 60 61 62

# @VARIABLE: INSTALL_BASE
# @DESCRIPTION:
# The main install directory where all ghcup stuff happens.
63
INSTALL_BASE="$HOME/.ghcup"
Julian Ospald's avatar
Julian Ospald committed
64 65 66 67

# @VARIABLE: GHC_LOCATION
# @DESCRIPTION:
# The location where ghcup will install different ghc versions.
68
# This is expected to be a subdirectory of INSTALL_BASE.
Julian Ospald's avatar
Julian Ospald committed
69
GHC_LOCATION="$INSTALL_BASE/ghc"
Julian Ospald's avatar
Julian Ospald committed
70 71 72 73

# @VARIABLE: BIN_LOCATION
# @DESCRIPTION:
# The location where ghcup will create symlinks for GHC binaries.
74
# This is expected to be a subdirectory of INSTALL_BASE.
Julian Ospald's avatar
Julian Ospald committed
75
BIN_LOCATION="$INSTALL_BASE/bin"
Julian Ospald's avatar
Julian Ospald committed
76 77 78 79

# @VARIABLE: DOWNLOADER
# @DESCRIPTION:
# What program to use for downloading files.
Julian Ospald's avatar
Julian Ospald committed
80
DOWNLOADER="curl"
Julian Ospald's avatar
Julian Ospald committed
81 82 83 84

# @VARIABLE: DOWNLOADER_OPTS
# @DESCRIPTION:
# Options passed to the download program.
Julian Ospald's avatar
Julian Ospald committed
85
DOWNLOADER_OPTS="--fail -O"
Julian Ospald's avatar
Julian Ospald committed
86 87 88 89

# @VARIABLE: SCRIPT_UPDATE_URL
# @DESCRIPTION:
# Location to update this script from.
Julian Ospald's avatar
Julian Ospald committed
90
SCRIPT_UPDATE_URL="https://raw.githubusercontent.com/haskell/ghcup/master/ghcup"
Julian Ospald's avatar
Julian Ospald committed
91 92 93 94

# @VARIABLE: GHC_DOWNLOAD_BASEURL
# @DESCRIPTION:
# Base URL for all GHC tarballs.
95
GHC_DOWNLOAD_BASEURL="https://downloads.haskell.org/~ghc"
Julian Ospald's avatar
Julian Ospald committed
96

97 98 99 100
# @VARIABLE: KNOWN_GOOD_CABAL
# @DESCRIPTION:
# The latests known good cabal-install version for
# which a pre-built binary exists.
101
KNOWN_GOOD_CABAL="2.4.0.0"
Julian Ospald's avatar
Julian Ospald committed
102

103 104 105 106 107
# @VARIABLE: JOBS
# @DESCRIPTION:
# How many jobs to use for compiling GHC.
JOBS="1"

Sam Halliday's avatar
Sam Halliday committed
108 109 110 111 112
# @VARIABLE: SOURCE
# @DESCRIPTION:
# The $0 argument, which contains
# the script name.
SOURCE="$0"
Julian Ospald's avatar
Julian Ospald committed
113 114 115 116 117

    ####################
    #--[ Print Help ]--#
    ####################

Julian Ospald's avatar
Julian Ospald committed
118

Julian Ospald's avatar
Julian Ospald committed
119 120 121 122
# @FUNCTION: usage
# @DESCRIPTION:
# Print the help message for 'ghcup' to STDERR
# and exit the script with status code 1.
Julian Ospald's avatar
Julian Ospald committed
123
usage() {
Julian Ospald's avatar
Julian Ospald committed
124 125 126 127 128
    (>&2 echo "ghcup ${VERSION}
GHC up toolchain installer

USAGE:
    ${SCRIPT} [FLAGS] <SUBCOMMAND>
Julian Ospald's avatar
Julian Ospald committed
129 130 131 132 133 134 135

FLAGS:
    -v, --verbose    Enable verbose output
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
136
    install          Install GHC
137
    compile          Compile and install GHC from source
Julian Ospald's avatar
Julian Ospald committed
138
    show             Show current/installed GHC
139
    set              Set currently active GHC version
140
    self-update      Update this script in-place
Julian Ospald's avatar
Julian Ospald committed
141
    rm               Remove an already installed GHC
142
    install-cabal    Install cabal-install
Julian Ospald's avatar
Julian Ospald committed
143 144 145 146 147

DISCUSSION:
    ghcup installs the Glasgow Haskell Compiler from the official
    release channels, enabling you to easily switch between different
    versions.
Julian Ospald's avatar
Julian Ospald committed
148 149 150 151
")
    exit 1
}

Julian Ospald's avatar
Julian Ospald committed
152 153 154 155
# @FUNCTION: install_usage
# @DESCRIPTION:
# Print the help message for 'ghcup install' to STDERR
# and exit the script with status code 1.
Julian Ospald's avatar
Julian Ospald committed
156
install_usage() {
Julian Ospald's avatar
Julian Ospald committed
157 158 159 160 161
    (>&2 echo "ghcup-install
Install the specified GHC version

USAGE:
    ${SCRIPT} install [FLAGS] <VERSION>
Julian Ospald's avatar
Julian Ospald committed
162 163 164

FLAGS:
    -h, --help       Prints help information
165
    -f, --force      Overwrite already existing installation
Julian Ospald's avatar
Julian Ospald committed
166 167 168

ARGS:
    <VERSION>        E.g. \"8.4.3\" or \"8.6.1\"
Julian Ospald's avatar
Julian Ospald committed
169 170 171 172 173

DISCUSSION:
    Installs the specified GHC version into
    a self-contained \"~/.ghcup/ghc/<ghcver>\" directory
    and symlinks the ghc binaries to \"~/.ghcup/bin/<binary>-<ghcver>\".
Julian Ospald's avatar
Julian Ospald committed
174 175 176 177
")
    exit 1
}

Julian Ospald's avatar
Julian Ospald committed
178 179 180 181
# @FUNCTION: set_usage
# @DESCRIPTION:
# Print the help message for 'ghcup set' to STDERR
# and exit the script with status code 1.
182 183
set_usage() {
    (>&2 echo "ghcup-set
Julian Ospald's avatar
Julian Ospald committed
184 185 186
Set the currently active GHC to the specified version

USAGE:
187
    ${SCRIPT} set [FLAGS] <VERSION>
188 189 190 191 192 193

FLAGS:
    -h, --help       Prints help information

ARGS:
    <VERSION>        E.g. \"8.4.3\" or \"8.6.1\"
Julian Ospald's avatar
Julian Ospald committed
194 195 196 197 198

DISCUSSION:
    Sets the the current GHC version by creating non-versioned
    symlinks for all ghc binaries of the specified version in
    \"~/.ghcup/bin/<binary>\".
199 200 201 202
")
    exit 1
}

Julian Ospald's avatar
Julian Ospald committed
203 204 205 206
# @FUNCTION: self_update_usage
# @DESCRIPTION:
# Print the help message for 'ghcup self-update' to STDERR
# and exit the script with status code 1.
207
self_update_usage() {
Julian Ospald's avatar
Julian Ospald committed
208
    (>&2 echo "ghcup-self-update
209
Update the ghcup script in-place
Julian Ospald's avatar
Julian Ospald committed
210 211 212

USAGE:
    ${SCRIPT} self-update [FLAGS] [TARGET-LOCATION]
213 214 215 216 217

FLAGS:
    -h, --help         Prints help information

ARGS:
Julian Ospald's avatar
Julian Ospald committed
218
    [TARGET-LOCATION]  Where to place the updated script (defaults to directory of the script).
219 220 221 222
")
    exit 1
}

Julian Ospald's avatar
Julian Ospald committed
223 224 225 226
# @FUNCTION: show_usage
# @DESCRIPTION:
# Print the help message for 'ghcup show' to STDERR
# and exit the script with status code 1.
Julian Ospald's avatar
Julian Ospald committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240
show_usage() {
    (>&2 echo "ghcup-show
Show the installed/current GHC versions

USAGE:
    ${SCRIPT} show [FLAGS]

FLAGS:
    -h, --help         Prints help information
    -i, --installed    Show installed GHC version only
")
    exit 1
}

Julian Ospald's avatar
Julian Ospald committed
241 242 243 244
# @FUNCTION: rm_usage
# @DESCRIPTION:
# Print the help message for 'ghcup rm' to STDERR
# and exit the script with status code 1.
Julian Ospald's avatar
Julian Ospald committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
rm_usage() {
    (>&2 echo "ghcup-rm
Remove the given GHC version installed by ghcup

USAGE:
    ${SCRIPT} rm [FLAGS] <VERSION>

FLAGS:
    -h, --help       Prints help information

ARGS:
    <VERSION>        E.g. \"8.4.3\" or \"8.6.1\"
")
    exit 1
}

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
# @FUNCTION: install_cabal_usage
# @DESCRIPTION:
# Print the help message for 'ghcup install-cabal' to STDERR
# and exit the script with status code 1.
install_cabal_usage() {
    (>&2 echo "ghcup-install-cabal
Install the specified or a default cabal version

USAGE:
    ${SCRIPT} install-cabal [FLAGS] [VERSION]

FLAGS:
    -h, --help       Prints help information

ARGS:
    <VERSION>        E.g. \"2.4.0.0\"

DISCUSSION:
    Installs the specified cabal-install version (or the default ${KNOWN_GOOD_CABAL})
280 281 282 283
    into \"${BIN_LOCATION}\", so it can be overwritten
    by later \"cabal new-install cabal-install\", which installs into
    \"~/.cabal/bin\". Make sure to set up your PATH appropriately, so
    the cabal installation takes precedence.
284 285 286 287
")
    exit 1
}

288 289 290 291 292 293 294 295 296 297 298 299
# @FUNCTION: compile_usage
# @DESCRIPTION:
# Print the help message for 'ghcup compile' to STDERR
# and exit the script with status code 1.
compile_usage() {
    (>&2 echo "ghcup-compile
Compile and install the specified GHC version

USAGE:
    ${SCRIPT} compile [FLAGS] <VERSION> <BOOTSTRAP-GHC>

FLAGS:
300 301 302 303
    -h, --help                     Prints help information
    -f, --force                    Overwrite already existing installation
    -j, --jobs <n>                 How many jobs for compilation
    -c, --build-config <filepath>  Use the given config file as build config
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319

ARGS:
    <VERSION>        E.g. \"8.4.3\" or \"8.6.1\"
    <BOOTSTRAP-GHC>  E.g. \"ghc-8.2.2\" or a full path

DISCUSSION:
    Compiles and installs the specified GHC version into
    a self-contained \"~/.ghcup/ghc/<ghcver>\" directory
    and symlinks the ghc binaries to \"~/.ghcup/bin/<binary>-<ghcver>\".

EXAMPLE:
    ghcup -v compile -f -j 4 8.4.2 ghc-8.2.2
")
    exit 1
}

320

Julian Ospald's avatar
Julian Ospald committed
321

Julian Ospald's avatar
Julian Ospald committed
322 323 324 325 326

    ###########################
    #--[ Utility functions ]--#
    ###########################

Julian Ospald's avatar
Julian Ospald committed
327

Julian Ospald's avatar
Julian Ospald committed
328 329 330 331 332
# @FUNCTION: die
# @USAGE: [msg]
# @DESCRIPTION:
# Exits the shell script with status code 2
# and prints the given message in red to STDERR, if any.
Julian Ospald's avatar
Julian Ospald committed
333
die() {
Julian Ospald's avatar
Julian Ospald committed
334
    (>&2 red_message "$1")
Julian Ospald's avatar
Julian Ospald committed
335 336 337
    exit 2
}

Julian Ospald's avatar
Julian Ospald committed
338 339 340 341 342 343
# @FUNCTION: edo
# @USAGE: <command>
# @DESCRIPTION:
# Executes the given command. Also prints what
# command that is (in blue) if verbosity is enabled.
# Exits with status code 2 if the command failed.
Julian Ospald's avatar
Julian Ospald committed
344 345 346
edo()
{
    if ${VERBOSE} ; then
Julian Ospald's avatar
Julian Ospald committed
347
        printf "\\033[0;34m%s\\033[0m\\n" "$*" 1>&2
Julian Ospald's avatar
Julian Ospald committed
348 349 350 351
    fi
    "$@" || exit 2
}

Julian Ospald's avatar
Julian Ospald committed
352 353 354 355
# @FUNCTION: debug_message
# @USAGE: <msg>
# @DESCRIPTION:
# Print a blue debug message if verbosity is enabled.
Julian Ospald's avatar
Julian Ospald committed
356
debug_message() {
Julian Ospald's avatar
Julian Ospald committed
357
    if ${VERBOSE} ; then
Julian Ospald's avatar
Julian Ospald committed
358
        printf "\\033[0;34m%s\\033[0m\\n" "$1"
Julian Ospald's avatar
Julian Ospald committed
359 360 361
    fi
}

Julian Ospald's avatar
Julian Ospald committed
362 363 364 365 366 367
# @FUNCTION: optionv
# @USAGE: <arg1> [arg2]
# @DESCRIPTION:
# If verbosity is enabled, echo the first argument, otherwise
# the second (if any).
# @STDOUT: first or second argument
368 369 370 371 372 373 374 375 376 377
optionv() {
    if ${VERBOSE} ; then
        echo "$1"
    else
        if [ -n "$2" ] ; then
            echo "$2"
        fi
    fi
}

Julian Ospald's avatar
Julian Ospald committed
378 379 380 381
# @FUNCTION: status_message
# @USAGE: <msg>
# @DESCRIPTION:
# Print a green status message.
Julian Ospald's avatar
Julian Ospald committed
382
status_message() {
Julian Ospald's avatar
Julian Ospald committed
383
    printf "\\033[0;32m%s\\033[0m\\n" "$1"
Julian Ospald's avatar
Julian Ospald committed
384 385
}

Julian Ospald's avatar
Julian Ospald committed
386 387 388 389
# @FUNCTION: warning_message
# @USAGE: <msg>
# @DESCRIPTION:
# Print a yellow warning message.
Julian Ospald's avatar
Julian Ospald committed
390 391 392 393
warning_message() {
    printf "\\033[1;33m%s\\033[0m\\n" "$1"
}

Julian Ospald's avatar
Julian Ospald committed
394 395 396 397
# @FUNCTION: red_message
# @USAGE: <msg>
# @DESCRIPTION:
# Print a red message.
Julian Ospald's avatar
Julian Ospald committed
398 399 400 401
red_message() {
    printf "\\033[0;31m%s\\033[0m\\n" "$1"
}

Julian Ospald's avatar
Julian Ospald committed
402 403 404 405 406
# @FUNCTION: get_distro_name
# @DESCRIPTION:
# Gets the current distro identifier following
# https://unix.stackexchange.com/a/6348
# @STDOUT: current distro identifier
Julian Ospald's avatar
Julian Ospald committed
407 408 409
get_distro_name() {
    if [ -f /etc/os-release ]; then
        # freedesktop.org and systemd
410
        # shellcheck disable=SC1091
Julian Ospald's avatar
Julian Ospald committed
411
        . /etc/os-release
Julian Ospald's avatar
Julian Ospald committed
412
        printf "%s" "$NAME"
Julian Ospald's avatar
Julian Ospald committed
413
    elif command -V lsb_release >/dev/null 2>&1; then
Julian Ospald's avatar
Julian Ospald committed
414
        # linuxbase.org
Julian Ospald's avatar
Julian Ospald committed
415
        printf "%s" "$(lsb_release -si)"
Julian Ospald's avatar
Julian Ospald committed
416 417
    elif [ -f /etc/lsb-release ]; then
        # For some versions of Debian/Ubuntu without lsb_release command
418
        # shellcheck disable=SC1091
Julian Ospald's avatar
Julian Ospald committed
419
        . /etc/lsb-release
Julian Ospald's avatar
Julian Ospald committed
420
        printf "%s" "$DISTRIB_ID"
Julian Ospald's avatar
Julian Ospald committed
421 422 423 424 425
    elif [ -f /etc/debian_version ]; then
        # Older Debian/Ubuntu/etc.
        printf "Debian"
    else
        # Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
Julian Ospald's avatar
Julian Ospald committed
426
        printf "%s" "$(uname -s)"
Julian Ospald's avatar
Julian Ospald committed
427 428 429
    fi
}

Julian Ospald's avatar
Julian Ospald committed
430 431 432 433 434
# @FUNCTION: get_distro_ver
# @DESCRIPTION:
# Gets the current distro version (if any) following
# https://unix.stackexchange.com/a/6348
# @STDOUT: current distro version, if any
Julian Ospald's avatar
Julian Ospald committed
435 436 437
get_distro_ver() {
    if [ -f /etc/os-release ]; then
        # freedesktop.org and systemd
438
        # shellcheck disable=SC1091
Julian Ospald's avatar
Julian Ospald committed
439
        . /etc/os-release
Julian Ospald's avatar
Julian Ospald committed
440
        printf "%s" "$VERSION_ID"
Julian Ospald's avatar
Julian Ospald committed
441
    elif command -V lsb_release >/dev/null 2>&1; then
Julian Ospald's avatar
Julian Ospald committed
442
        # linuxbase.org
Julian Ospald's avatar
Julian Ospald committed
443
        printf "%s" "$(lsb_release -sr)"
Julian Ospald's avatar
Julian Ospald committed
444 445
    elif [ -f /etc/lsb-release ]; then
        # For some versions of Debian/Ubuntu without lsb_release command
446
        # shellcheck disable=SC1091
Julian Ospald's avatar
Julian Ospald committed
447
        . /etc/lsb-release
Julian Ospald's avatar
Julian Ospald committed
448
        printf "%s" "$DISTRIB_RELEASE"
Julian Ospald's avatar
Julian Ospald committed
449 450
    elif [ -f /etc/debian_version ]; then
        # Older Debian/Ubuntu/etc.
Julian Ospald's avatar
Julian Ospald committed
451
        printf "%s" "$(cat /etc/debian_version)"
Julian Ospald's avatar
Julian Ospald committed
452 453
    else
        # Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
Julian Ospald's avatar
Julian Ospald committed
454
        printf "%s" "$(uname -r)"
Julian Ospald's avatar
Julian Ospald committed
455 456 457
    fi
}

Julian Ospald's avatar
Julian Ospald committed
458 459 460 461 462 463
# @FUNCTION: get_arch
# @DESCRIPTION:
# Gets the architecture following
# https://unix.stackexchange.com/a/6348
# Fails for any architecture that we don't know a GHC version for.
# @STDOUT: current architecture
Julian Ospald's avatar
Julian Ospald committed
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
get_arch() {
    myarch=$(uname -m)

    case "${myarch}" in
    x86_64)
        printf "x86_64"  # or AMD64 or Intel64 or whatever
        ;;
    i*86)
        printf "i386"  # or IA32 or Intel32 or whatever
        ;;
    *)
        die "Cannot figure out architecture (was: ${myarch})"
        ;;
    esac

    unset myarch
}

Julian Ospald's avatar
Julian Ospald committed
482 483 484 485 486 487
# @FUNCTION: get_download_url
# @USAGE: <ghcversion>
# @DESCRIPTION:
# Gets the right (hopefully) download url for the given ghc version
# and the current distro and architecture (which it tries to discover).
# @STDOUT: ghc download url
Julian Ospald's avatar
Julian Ospald committed
488
get_download_url() {
489 490
    [ -z "$1" ] && die "Internal error: no argument given to get_download_url"

Julian Ospald's avatar
Julian Ospald committed
491 492 493 494 495
    myghcver=$1
    myarch=$(get_arch)
    mydistro=$(get_distro_name)
    mydistrover=$(get_distro_ver)

496
    # TODO: awkward, restructure
Julian Ospald's avatar
Julian Ospald committed
497
    case "${mydistro},${mydistrover},${myarch},${myghcver}" in
Julian Ospald's avatar
Julian Ospald committed
498
    Debian*,7,i386,8.2.2)
499
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb${mydistrover}-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
500
        ;;
Julian Ospald's avatar
Julian Ospald committed
501
    *,*,i386,*)
502
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
503
        ;;
Julian Ospald's avatar
Julian Ospald committed
504
    Debian*,*,*,8.2.2)
505
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
506
        ;;
Julian Ospald's avatar
Julian Ospald committed
507
    Debian*,8,*,*)
508
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
509
        ;;
Julian Ospald's avatar
Julian Ospald committed
510
    Debian*,*,*,*)
511
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb9-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
512
        ;;
Julian Ospald's avatar
Julian Ospald committed
513
    Ubuntu*,*,*,8.2.2)
514
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
515
        ;;
Julian Ospald's avatar
Julian Ospald committed
516
    Ubuntu*,*,*,*)
517
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb9-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
518
        ;;
519
    *,*,*,8.2.2)
520
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
521
        ;;
Julian Ospald's avatar
Julian Ospald committed
522
    *,*,*,*) # this is our best guess
523
        printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-fedora27-linux.tar.xz"
Julian Ospald's avatar
Julian Ospald committed
524
        ;;
Julian Ospald's avatar
Julian Ospald committed
525 526
    esac

527
    unset myghcver myarch mydistro mydistrover
Julian Ospald's avatar
Julian Ospald committed
528 529
}

Julian Ospald's avatar
Julian Ospald committed
530 531 532 533 534 535 536
# @FUNCTION: ghc_already_installed
# @USAGE: <ghcversion>
# @DESCRIPTION:
# Checks whether the specified GHC version
# has been installed by ghcup already.
# @RETURN: 0 if GHC is already installed, 1 otherwise
ghc_already_installed() {
537 538
    [ -z "$1" ] && die "Internal error: no argument given to ghc_already_installed"

Julian Ospald's avatar
Julian Ospald committed
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
    if [ -e "$(get_ghc_location "$1")" ] ; then
        return 0
    else
        return 1
    fi
}

# @FUNCTION: get_ghc_location
# @USAGE: <ghcversion>
# @DESCRIPTION:
# Gets/prints the location where the specified GHC is or would be installed.
# Doesn't check whether that directory actually exist. Use
# 'ghc_already_installed' for that.
# @STDOUT: ghc location
get_ghc_location() {
554 555
    [ -z "$1" ] && die "Internal error: no argument given to get_ghc_location"

Julian Ospald's avatar
Julian Ospald committed
556 557 558 559 560
    myghcver=$1
    inst_location=${GHC_LOCATION}/${myghcver}

    printf "%s" "${inst_location}"

Julian Ospald's avatar
Julian Ospald committed
561
    unset myghcver inst_location
Julian Ospald's avatar
Julian Ospald committed
562 563
}

Julian Ospald's avatar
Julian Ospald committed
564 565 566 567 568 569
# @FUNCTION: download
# @USAGE: <url>
# @DESCRIPTION:
# Downloads the given url as a file into the current directory.
# @RETURN: status code from the downloader
download() {
570
    [ -z "$1" ] && die "Internal error: no argument given to download"
Julian Ospald's avatar
Julian Ospald committed
571 572 573 574 575
    # shellcheck disable=SC2086
    ${DOWNLOADER} ${DOWNLOADER_OPTS} "$1"
    return $?
}

Julian Ospald's avatar
Julian Ospald committed
576

Julian Ospald's avatar
Julian Ospald committed
577 578 579 580 581

    ############################
    #--[ Subcommand install ]--#
    ############################

Julian Ospald's avatar
Julian Ospald committed
582

Julian Ospald's avatar
Julian Ospald committed
583 584 585 586
# @FUNCTION: install_ghc
# @USAGE: <ghcversion>
# @DESCRIPTION:
# Installs the given ghc version with a lot of side effects.
Julian Ospald's avatar
Julian Ospald committed
587
install_ghc() {
588 589
    [ -z "$1" ] && die "Internal error: no argument given to install_ghc"

Julian Ospald's avatar
Julian Ospald committed
590
    myghcver=$1
Julian Ospald's avatar
Julian Ospald committed
591
    inst_location=$(get_ghc_location "$1")
Julian Ospald's avatar
Julian Ospald committed
592 593
    download_url=$(get_download_url "${myghcver}")
    download_tarball_name=$(basename "${download_url}")
594

Julian Ospald's avatar
Julian Ospald committed
595
    if ghc_already_installed "${myghcver}" ; then
596 597 598 599 600 601
        if ${FORCE} ; then
            echo "GHC already installed in ${inst_location}, overwriting!"
        else
            die "GHC already installed in ${inst_location}, use --force to overwrite"
        fi
    fi
Julian Ospald's avatar
Julian Ospald committed
602

Julian Ospald's avatar
Julian Ospald committed
603
    status_message "Installing GHC for $(get_distro_name) on architecture $(get_arch)"
Julian Ospald's avatar
Julian Ospald committed
604 605
    tmp_dir=$(mktemp -d)
    [ -z "${tmp_dir}" ] && die "Failed to create temporary directory"
606
    (
Julian Ospald's avatar
Julian Ospald committed
607
        edo cd "${tmp_dir}"
Julian Ospald's avatar
Julian Ospald committed
608

Julian Ospald's avatar
Julian Ospald committed
609
        edo download "${download_url}"
Julian Ospald's avatar
Julian Ospald committed
610

Julian Ospald's avatar
Julian Ospald committed
611 612
        edo tar -xf ghc-*-linux.tar.xz
        edo cd "ghc-${myghcver}"
Julian Ospald's avatar
Julian Ospald committed
613

Julian Ospald's avatar
Julian Ospald committed
614
        debug_message "Installing GHC into ${inst_location}"
615

Julian Ospald's avatar
Julian Ospald committed
616
        edo ./configure --prefix="${inst_location}"
617
        edo make install
Julian Ospald's avatar
Julian Ospald committed
618 619

        # clean up
Julian Ospald's avatar
Julian Ospald committed
620
        edo cd ..
Julian Ospald's avatar
Julian Ospald committed
621 622
        [ -e "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}"
        [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}"
Julian Ospald's avatar
Julian Ospald committed
623
    ) || {
Julian Ospald's avatar
Julian Ospald committed
624 625
        [ -e "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}"
        [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}"
Julian Ospald's avatar
Julian Ospald committed
626
        die "Failed to install, consider updating this script via: ${SCRIPT} self-update"
Julian Ospald's avatar
Julian Ospald committed
627
    }
628

Julian Ospald's avatar
Julian Ospald committed
629
    [ -e "${BIN_LOCATION}" ] || mkdir "${BIN_LOCATION}"
Julian Ospald's avatar
Julian Ospald committed
630

Julian Ospald's avatar
Julian Ospald committed
631
    for f in "${inst_location}"/bin/*-"${myghcver}" ; do
Julian Ospald's avatar
Julian Ospald committed
632
        [ -e "${f}" ] || die "Something went wrong, ${f} does not exist!"
Julian Ospald's avatar
Julian Ospald committed
633
        fn=$(basename "${f}")
634
        # shellcheck disable=SC2046
Julian Ospald's avatar
Julian Ospald committed
635
        edo ln $(optionv "-v") -sf ../ghc/"${myghcver}/bin/${fn}" "${BIN_LOCATION}/${fn}"
636 637
        unset fn
    done
638
    # shellcheck disable=SC2046
Julian Ospald's avatar
Julian Ospald committed
639
    edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/runhaskell "${BIN_LOCATION}/runhaskell-${myghcver}"
640

Julian Ospald's avatar
Julian Ospald committed
641
    status_message "Done installing, run \"ghci-${myghcver}\" or set up your current GHC via: ${SCRIPT} set ${myghcver}"
642

Julian Ospald's avatar
Julian Ospald committed
643
    unset myghcver inst_location f download_url download_tarball_name
644 645 646
}


Julian Ospald's avatar
Julian Ospald committed
647

Julian Ospald's avatar
Julian Ospald committed
648 649 650
    ########################
    #--[ Subcommand set ]--#
    ########################
Julian Ospald's avatar
Julian Ospald committed
651

652

Julian Ospald's avatar
Julian Ospald committed
653 654 655 656
# @FUNCTION: set_ghc
# @USAGE: <ghcversion>
# @DESCRIPTION:
# Sets the current ghc version by creating symlinks.
657
set_ghc() {
658 659
    [ -z "$1" ] && die "Internal error: no argument given to set_ghc"

660
    myghcver=$1
Julian Ospald's avatar
Julian Ospald committed
661
    inst_location=$(get_ghc_location "$1")
662 663

    [ -e "${inst_location}" ] || die "GHC ${myghcver} not installed yet, use: ${SCRIPT} install ${myghcver}"
Julian Ospald's avatar
Julian Ospald committed
664
    [ -e "${BIN_LOCATION}" ] || edo mkdir "${BIN_LOCATION}"
665

Julian Ospald's avatar
Julian Ospald committed
666
    status_message "Setting GHC to ${myghcver}"
667

Julian Ospald's avatar
Julian Ospald committed
668
    for f in "${inst_location}"/bin/*-"${myghcver}" ; do
Julian Ospald's avatar
Julian Ospald committed
669
        [ -e "${f}" ] || die "Something went wrong, ${f} does not exist!"
Julian Ospald's avatar
Julian Ospald committed
670 671
        source_fn=$(basename "${f}")
        target_fn=$(echo "${source_fn}" | sed "s#-${myghcver}##")
672
        # shellcheck disable=SC2046
Julian Ospald's avatar
Julian Ospald committed
673
        edo ln $(optionv "-v") -sf ../ghc/"${myghcver}/bin/${source_fn}" "${BIN_LOCATION}/${target_fn}"
674 675
        unset source_fn target_fn
    done
676
    # shellcheck disable=SC2046
Julian Ospald's avatar
Julian Ospald committed
677
    edo ln $(optionv "-v") -sf runghc "${BIN_LOCATION}"/runhaskell
Julian Ospald's avatar
Julian Ospald committed
678

Julian Ospald's avatar
Julian Ospald committed
679
    status_message "Done, make sure \"${BIN_LOCATION}\" is in your PATH!"
Julian Ospald's avatar
Julian Ospald committed
680

Julian Ospald's avatar
Julian Ospald committed
681
    unset myghcver inst_location f
Julian Ospald's avatar
Julian Ospald committed
682 683 684
}


Julian Ospald's avatar
Julian Ospald committed
685 686 687 688 689

    ################################
    #--[ Subcommand self-update ]--#
    ################################

Sam Halliday's avatar
Sam Halliday committed
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
# @FUNCTION: script_dir
# @DESCRIPTION:
# Portably gets the full directory of where
# this script resides in and prints it to stdout.
# @STDOUT: script directory
script_dir() {
    mysource=${SOURCE}

    while [ -h "${mysource}" ]; do
        mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null && pwd )"
        mysource="$(readlink "${mysource}")"
        [ "${mysource%${mysource#?}}"x != '/x' ] && mysource="${mydir}/${mysource}"
    done
    mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null && pwd )"
    echo "${mydir}"

    unset mysource mydir
}
708

Julian Ospald's avatar
Julian Ospald committed
709 710 711 712 713
# @FUNCTION: self_update
# @USAGE: <install-location>
# @DESCRIPTION:
# Downloads the latest version of this script and places it into
# the given directory.
714 715 716 717 718
self_update() {
    target_location=$1

    [ -e "${target_location}" ] || die "Destination \"${target_location}\" does not exist, cannot update script"

Julian Ospald's avatar
Julian Ospald committed
719
    status_message "Updating ${SCRIPT}"
720 721

    (
Julian Ospald's avatar
Julian Ospald committed
722
        edo cd "$(mktemp -d)"
723
        edo download "${SCRIPT_UPDATE_URL}"
Julian Ospald's avatar
Julian Ospald committed
724 725 726
        edo chmod +x ghcup
        edo mv -f ghcup "${target_location}"/ghcup

Julian Ospald's avatar
Julian Ospald committed
727
    ) || die "failed to install"
728

Julian Ospald's avatar
Julian Ospald committed
729
    status_message "Done, make sure \"${target_location}\" is in your PATH!"
730

731
    unset target_location
732 733
}

Julian Ospald's avatar
Julian Ospald committed
734 735 736 737 738 739


    #########################
    #--[ Subcommand show ]--#
    #########################

Julian Ospald's avatar
Julian Ospald committed
740

Julian Ospald's avatar
Julian Ospald committed
741 742 743 744
# @FUNCTION: show_ghc
# @DESCRIPTION:
# Prints the currently installed and selected GHC, in human-friendly
# format.
Julian Ospald's avatar
Julian Ospald committed
745 746 747 748
show_ghc() {
    current_ghc=$(show_ghc_installed)

    echo "Installed GHCs:"
Julian Ospald's avatar
Julian Ospald committed
749
    for i in "${GHC_LOCATION}"/* ; do
750 751 752 753 754 755
        if [ -e "${i}" ] ; then
            echo "    $(basename "${i}")"
        else # directory is empty
            echo "    None"
            exit 0
        fi
Julian Ospald's avatar
Julian Ospald committed
756 757 758 759 760 761 762 763
    done

    if [ -n "${current_ghc}" ] ; then
        echo
        echo "Current GHC"
        echo "    ${current_ghc}"
    fi

Julian Ospald's avatar
Julian Ospald committed
764
    unset current_ghc i
Julian Ospald's avatar
Julian Ospald committed
765 766
}

Julian Ospald's avatar
Julian Ospald committed
767 768 769 770
# @FUNCTION: show_ghc_installed
# @DESCRIPTION:
# Prints the currently selected GHC only as version string.
# @STDOUT: current GHC version
Julian Ospald's avatar
Julian Ospald committed
771
show_ghc_installed() {
Julian Ospald's avatar
Julian Ospald committed
772 773 774 775 776 777 778 779 780 781
    current_ghc="${BIN_LOCATION}/ghc"
    real_ghc=$(realpath "${current_ghc}" 2>/dev/null)

    if [ -L "${current_ghc}" ] ; then # is symlink
        if [ -e "${real_ghc}" ] ; then # exists (realpath was called)
            real_ghc="$(basename "${real_ghc}" | sed 's#ghc-##')"
            printf "%s" "${real_ghc}"
        else # is a broken symlink
            red_message "broken symlink"
        fi
Julian Ospald's avatar
Julian Ospald committed
782 783
    fi

Julian Ospald's avatar
Julian Ospald committed
784
    unset real_ghc current_ghc
Julian Ospald's avatar
Julian Ospald committed
785 786
}

Julian Ospald's avatar
Julian Ospald committed
787 788 789 790 791 792


    #######################
    #--[ Subcommand rm ]--#
    #######################

Julian Ospald's avatar
Julian Ospald committed
793

Julian Ospald's avatar
Julian Ospald committed
794 795 796 797
# @FUNCTION: rm_ghc
# @USAGE: <ghcversion>
# @DESCRIPTION:
# Removes the given GHC version installed by ghcup.
Julian Ospald's avatar
Julian Ospald committed
798
rm_ghc() {
799 800
    [ -z "$1" ] && die "Internal error: no argument given to rm_ghc"

Julian Ospald's avatar
Julian Ospald committed
801 802 803 804 805 806 807 808 809 810 811
    myghcver=$1
    inst_location=$(get_ghc_location "${myghcver}")

    [ -z "${myghcver}" ] && die "We are paranoid, ghcver not set"

    if ghc_already_installed "${myghcver}" ; then
        for f in "${BIN_LOCATION}"/*-"${myghcver}" ; do
            # https://tanguy.ortolo.eu/blog/article113/test-symlink
            [ ! -e "${f}" ] && [ ! -h "${f}" ] && die "Something went wrong, ${f} does not exist!"
            edo rm "${f}"
        done
812
        [ -z "${inst_location}" ] && die "internal error: inst_location empty!"
Julian Ospald's avatar
Julian Ospald committed
813
        edo rm -r "${inst_location}"
Julian Ospald's avatar
Julian Ospald committed
814

Julian Ospald's avatar
Julian Ospald committed
815 816 817 818 819 820
        status_message "Successfully removed GHC ${myghcver}."

        if [ ! -e "${BIN_LOCATION}"/ghc ] ; then
            warning_message "Currently active GHC is a dangling symlink, run:"
            warning_message "    ghcup set <ghcver>"
        fi
Julian Ospald's avatar
Julian Ospald committed
821 822 823 824 825 826 827
    else
        warning_message "${myghcver} doesn't appear to be installed, skipping"
    fi

    unset myghcver inst_location f
}

828 829 830 831 832 833 834 835 836 837 838 839 840 841
    ############################
    #--[ Subcommand install ]--#
    ############################


# @FUNCTION: install_cabal
# @USAGE: <cabalversion>
# @DESCRIPTION:
# Installs the given cabal version.
install_cabal() {
    [ -z "$1" ] && die "Internal error: no argument given to install_cabal"

    mycabalver=$1
    myarch=$(get_arch)
842
    inst_location=$BIN_LOCATION
843 844

    [ -e "${inst_location}" ] || {
845 846 847
        # TODO: this is a bit shaky because we don't use -p
        edo mkdir "${INSTALL_BASE}"
        edo mkdir "${BIN_LOCATION}"
848 849 850 851
    }

    (
        edo cd "$(mktemp -d)"
852
        edo download "https://downloads.haskell.org/~cabal/cabal-install-${mycabalver}/cabal-install-${mycabalver}-${myarch}-unknown-linux.tar.gz"
853
        edo tar -xzf "cabal-install-${mycabalver}-${myarch}-unknown-linux.tar.gz"
854
        edo mv -f cabal "${inst_location}"/cabal
855 856
    ) || die "Failed to install cabal-install"

857 858 859 860
    status_message "Successfully installed cabal-install into"
    status_message "  ${BIN_LOCATION}"
    status_message ""
    status_message "You may want to run the following to get the really latest version:"
861
    status_message "    cabal new-install cabal-install"
862 863 864
    status_message ""
    status_message "And make sure that \"~/.cabal/bin\" comes *before* \"${BIN_LOCATION}\""
    status_message "in your PATH!"
865 866 867 868

    unset mycabalver myarch inst_location
}

869
# @FUNCTION: compile_ghc
870
# @USAGE: <ghcversion> <bootstrap-ghc> [build.mk]
871 872 873
# @DESCRIPTION:
# Compile and installs the given GHC version with the
# specified GHC bootstrap version.
874 875
# Can additionally take a custom file that will be used
# as build configuration.
876 877 878 879 880 881 882 883 884
compile_ghc() {
    { [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to compile_ghc"

    myghcver=$1
    bootstrap_ghc=$2
    inst_location=$(get_ghc_location "$1")
    download_url="https://downloads.haskell.org/~ghc/${myghcver}/ghc-${myghcver}-src.tar.xz"
    download_tarball_name=$(basename "${download_url}")

885 886 887 888 889 890 891 892
    if [ -n "$3" ] ; then
        case "$3" in
            /*) build_config=$3 ;;
            *) build_config="$(pwd)/$3" ;;
        esac
        [ -e "${build_config}" ] || die "specified build config \"${build_config}\" file does not exist!"
    fi

893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
    if ghc_already_installed "${myghcver}" ; then
        if ${FORCE} ; then
            echo "GHC already installed in ${inst_location}, overwriting!"
        else
            die "GHC already installed in ${inst_location}, use --force to overwrite"
        fi
    fi

    status_message "Compiling GHC for version ${myghcver} from source"
    tmp_dir=$(mktemp -d)
    [ -z "${tmp_dir}" ] && die "Failed to create temporary directory"
    (
        edo cd "${tmp_dir}"

        edo download "${download_url}"

        edo tar -xf ghc-*-src.tar.xz
        edo cd "ghc-${myghcver}"

912 913 914 915 916 917 918 919 920 921 922 923 924
        if [ -n "${build_config}" ] ; then
            edo cat "${build_config}" > mk/build.mk
        else
			cat <<-EOF > mk/build.mk || die
				V=0
				BUILD_MAN = NO
				BUILD_SPHINX_HTML = NO
				BUILD_SPHINX_PDF = NO
				HADDOCK_DOCS = YES
				GhcWithLlvmCodeGen = YES
				EOF
        fi

925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959

        edo ./boot
        edo ./configure --prefix="${inst_location}" --with-ghc="${bootstrap_ghc}"
        edo make -j${JOBS}
        edo make install

        # clean up
        edo cd ..
        [ -e "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}"
        [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}"
    ) || {
        [ -e "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}"
        [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}"
        die "Failed to install, consider updating this script via:
    ${SCRIPT} self-update
Also check https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Linux for build requirements and follow the instructions."
    }

    [ -e "${BIN_LOCATION}" ] || mkdir "${BIN_LOCATION}"

    for f in "${inst_location}"/bin/*-"${myghcver}" ; do
        [ -e "${f}" ] || die "Something went wrong, ${f} does not exist!"
        fn=$(basename "${f}")
        # shellcheck disable=SC2046
        edo ln $(optionv "-v") -sf ../ghc/"${myghcver}/bin/${fn}" "${BIN_LOCATION}/${fn}"
        unset fn
    done
    # shellcheck disable=SC2046
    edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/runhaskell "${BIN_LOCATION}/runhaskell-${myghcver}"

    status_message "Done installing, run \"ghci-${myghcver}\" or set up your current GHC via: ${SCRIPT} set ${myghcver}"

    unset myghcver bootstrap_ghc inst_location f download_url download_tarball_name
}

960

Julian Ospald's avatar
Julian Ospald committed
961

Julian Ospald's avatar
Julian Ospald committed
962

Julian Ospald's avatar
Julian Ospald committed
963 964 965 966
    #######################
    #--[ Sanity checks ]--#
    #######################

Julian Ospald's avatar
Julian Ospald committed
967

968 969 970 971
if [ -z "$HOME" ] ; then
    die "HOME env not set, cannot operate"
fi

Julian Ospald's avatar
Julian Ospald committed
972 973 974 975 976 977 978


    ##############################################
    #--[ Command line parsing and entry point ]--#
    ##############################################


979 980
[ $# -lt 1 ] && usage

Julian Ospald's avatar
Julian Ospald committed
981 982 983 984
while [ $# -gt 0 ] ; do
    case $1 in
    -v|--verbose)
        VERBOSE=true
985 986 987 988 989
        shift 1
        if [ $# -lt 1 ] ; then
            usage
        fi
        ;;
Julian Ospald's avatar
Julian Ospald committed
990
    -V|--version)
Julian Ospald's avatar
Julian Ospald committed
991
        printf "%s" "${VERSION}"
Julian Ospald's avatar
Julian Ospald committed
992 993 994 995 996 997 998 999 1000
        exit 0;;
    -h|--help)
        usage;;
    *) case $1 in
       install)
           shift 1
           while [ $# -gt 0 ] ; do
               case $1 in
                   -h|--help) install_usage;;
1001 1002
                   -f|--force) FORCE=true
                       shift 1;;
Julian Ospald's avatar
Julian Ospald committed
1003 1004 1005 1006 1007
                   *) GHC_VER=$1
                      break;;
               esac
           done
           [ "${GHC_VER}" ] || install_usage
Julian Ospald's avatar
Julian Ospald committed
1008
           install_ghc "${GHC_VER}"
Julian Ospald's avatar
Julian Ospald committed
1009
           break;;
1010
       set)
1011 1012 1013
           shift 1
           while [ $# -gt 0 ] ; do
               case $1 in
1014
                   -h|--help) set_usage;;
1015 1016 1017 1018
                   *) GHC_VER=$1
                      break;;
               esac
           done
1019
           [ "${GHC_VER}" ] || set_usage
Julian Ospald's avatar
Julian Ospald committed
1020
           set_ghc "${GHC_VER}"
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
           break;;
       self-update)
           shift 1
           while [ $# -gt 0 ] ; do
               case $1 in
                   -h|--help) self_update_usage;;
                   *) TARGET_LOCATION=$1
                       break;;
               esac
           done
           if [ "${TARGET_LOCATION}" ] ; then
               self_update "${TARGET_LOCATION}"
           else
Sam Halliday's avatar
Sam Halliday committed
1034
               self_update "$(script_dir)"
1035 1036
           fi
           break;;
Julian Ospald's avatar
Julian Ospald committed
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
       show)
           SHOW_INSTALLED=false
           shift 1
           while [ $# -gt 0 ] ; do
               case $1 in
                   -h|--help) show_usage;;
                   -i|--installed) SHOW_INSTALLED=true
                       break;;
                   *) show_usage;;
               esac
           done
           if ${SHOW_INSTALLED} ; then
               show_ghc_installed
           else
               show_ghc
           fi
           break;;
Julian Ospald's avatar
Julian Ospald committed
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
       rm)
           shift 1
           while [ $# -gt 0 ] ; do
               case $1 in
                   -h|--help) rm_usage;;
                   *) GHC_VER=$1
                      break;;
               esac
           done
           [ "${GHC_VER}" ] || rm_usage
           rm_ghc "${GHC_VER}"
           break;;
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
       install-cabal)
           shift 1
           while [ $# -gt 0 ] ; do
               case $1 in
                   -h|--help) install_cabal_usage;;
                   -f|--force) FORCE=true
                       shift 1;;
                   *) CABAL_VER=$1
                      break;;
               esac
           done
           if [ "${CABAL_VER}" ] ; then
               install_cabal "${CABAL_VER}"
           else
               install_cabal "${KNOWN_GOOD_CABAL}"
           fi
           break;;
1083 1084 1085 1086 1087 1088 1089 1090 1091
       compile)
           shift 1
           while [ $# -gt 0 ] ; do
               case $1 in
                   -h|--help) compile_usage;;
                   -f|--force) FORCE=true
                       shift 1;;
                   -j|--jobs) JOBS=$2
                       shift 2;;
1092 1093
                   -c|--build-config) BUILD_CONFIG=$2
                       shift 2;;
1094 1095 1096 1097 1098 1099 1100
                   *) GHC_VER=$1
                      BOOTSTRAP_GHC=$2
                      break;;
               esac
           done
           [ "${GHC_VER}" ] || compile_usage
           [ "${BOOTSTRAP_GHC}" ] || compile_usage
1101
           compile_ghc "${GHC_VER}" "${BOOTSTRAP_GHC}" "${BUILD_CONFIG}"
1102
           break;;
Julian Ospald's avatar
Julian Ospald committed
1103 1104 1105 1106 1107 1108
       *) usage;;
       esac
       break;;
    esac
done

Julian Ospald's avatar
Julian Ospald committed
1109
# vim: tabstop=4 shiftwidth=4 expandtab