├── .available-versions ├── .bash-completion ├── .download-urls ├── .gitlab-ci.yml ├── .gitlab ├── before_script │ ├── darwin │ │ └── install_deps.sh │ └── linux │ │ ├── install_deps.sh │ │ └── install_shellcheck.sh ├── ghcup_env └── script │ ├── ghcup_cached_tarball.sh │ ├── ghcup_version.sh │ └── shellcheck.sh ├── .requirements └── ghc │ ├── alpine │ ├── darwin │ ├── default │ └── ubuntu ├── CHANGELOG.md ├── CONTRIBUTING.md ├── COPYING ├── README.md ├── bootstrap-haskell ├── generate_changelog.sh ├── ghcup └── www ├── LICENSE ├── copy.svg ├── fonts ├── FiraSans-Light.woff ├── FiraSans-Medium.woff ├── FiraSans-Regular.woff ├── Inconsolata-Regular.ttf ├── OFL.txt └── WorkSans-Medium.ttf ├── ghcup.css ├── ghcup.js ├── haskell-logo.svg ├── index.html └── normalize.css /.available-versions: -------------------------------------------------------------------------------- 1 | # fmt-version=1 2 | # 3 | # 'recommended' follows the "most widely used" GHC version. 4 | # Indicators for that are: 5 | # 1. the current hackage ecosystem and common tools and libraries work 6 | # well with that GHC version 7 | # 2. stackage has an LTS with that GHC version 8 | # 3. people on #haskell IRC or reddit recommend it 9 | # 10 | # tool | version | tag | 11 | 12 | ghc 7.10.3 7.10 13 | ghc 8.0.2 8.0 14 | ghc 8.2.2 8.2 15 | ghc 8.4.1 16 | ghc 8.4.2 17 | ghc 8.4.3 18 | ghc 8.4.4 8.4 19 | ghc 8.6.1 bad 20 | ghc 8.6.2 21 | ghc 8.6.3 22 | ghc 8.6.4 23 | ghc 8.6.5 8.6 24 | ghc 8.8.1 25 | ghc 8.8.2 26 | ghc 8.8.3 recommended,8.8 27 | ghc 8.10.1 latest,8.10 28 | cabal-install 2.2.0.0 29 | cabal-install 2.4.0.0 30 | cabal-install 2.4.1.0 31 | cabal-install 3.0.0.0 32 | cabal-install 3.2.0.0 latest,recommended 33 | -------------------------------------------------------------------------------- /.bash-completion: -------------------------------------------------------------------------------- 1 | _ghcup() 2 | { 3 | local cur 4 | COMPREPLY=() 5 | cur="${COMP_WORDS[COMP_CWORD]}" 6 | if [[ ${#COMP_WORDS[*]} -le 2 ]]; then 7 | COMPREPLY=($(compgen -W "$(ghcup --list-commands)" -- $cur)) 8 | fi 9 | return 0 10 | } && 11 | complete -F _ghcup ghcup 12 | -------------------------------------------------------------------------------- /.download-urls: -------------------------------------------------------------------------------- 1 | # fmt-version=1 2 | # 3 | # Only url is unique. tool, version and arch are explicit, because we cannot rely 4 | # on the url to have it (we want to be agnostic of urls). 5 | # 6 | # Order of trying distros is: 7 | # 1. distro=ver if exists 8 | # 2. distro if applicable 9 | # 3. otherwise 'unknown' 10 | # 11 | # As such, every triple of (tool, version, arch) should have EXACTLY ONE 'unknown' in supported-distros 12 | # list. 13 | # 14 | # tool | version | arch | supported-distros for given url | url | 15 | 16 | ghc 7.10.3 x86_64 centos=6,centos,amazonlinux https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-centos67-linux.tar.bz2 17 | ghc 7.10.3 i386 centos=6,centos,amazonlinux https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-centos67-linux.tar.bz2 18 | ghc 7.10.3 x86_64 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2 19 | ghc 7.10.3 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-deb8-linux.tar.bz2 20 | ghc 7.10.3 x86_64 darwin https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-apple-darwin.tar.bz2 21 | ghc 7.10.3 x86_64 freebsd=9,freebsd=10,freebsd=11 https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-portbld-freebsd.tar.bz2 22 | ghc 7.10.3 i386 freebsd=9,freebsd=10,freebsd=11 https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-portbld-freebsd.tar.bz2 23 | ghc 7.10.3 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-7.10.3-musl/ghc-7.10.3-x86_64-unknown-linux-musl.tar.xz 24 | 25 | ghc 8.0.2 x86_64 debian=7 https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb7-linux.tar.xz 26 | ghc 8.0.2 i386 debian=7 https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb7-linux.tar.xz 27 | ghc 8.0.2 x86_64 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb8-linux.tar.xz 28 | ghc 8.0.2 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb8-linux.tar.xz 29 | ghc 8.0.2 x86_64 darwin https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-apple-darwin.tar.xz 30 | ghc 8.0.2 x86_64 freebsd=9,freebsd=10,freebsd=11 https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-portbld-freebsd.tar.xz 31 | ghc 8.0.2 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.0.2-musl/ghc-8.0.2-x86_64-unknown-linux-musl.tar.xz 32 | ghc 8.0.2 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.0.2-musl/ghc-8.0.2-i386-unknown-linux-musl.tar.xz 33 | 34 | ghc 8.2.2 x86_64 debian=7 https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb7-linux.tar.xz 35 | ghc 8.2.2 i386 debian=7 https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb7-linux.tar.xz 36 | ghc 8.2.2 x86_64 debian=8,debian,ubuntu,mint https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb8-linux.tar.xz 37 | ghc 8.2.2 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb8-linux.tar.xz 38 | ghc 8.2.2 x86_64 unknown https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-unknown-linux.tar.xz 39 | ghc 8.2.2 x86_64 darwin https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-apple-darwin.tar.xz 40 | ghc 8.2.2 x86_64 freebsd=10 https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld10_3-freebsd.tar.xz 41 | ghc 8.2.2 x86_64 freebsd=11 https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld11-freebsd.tar.xz 42 | 43 | ghc 8.4.1 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-i386-deb8-linux.tar.xz 44 | ghc 8.4.1 x86_64 debian=8,debian https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-deb8-linux.tar.xz 45 | ghc 8.4.1 x86_64 fedora=27,fedora,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-fedora27-linux.tar.xz 46 | ghc 8.4.1 x86_64 darwin https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-apple-darwin.tar.xz 47 | ghc 8.4.1 x86_64 freebsd=11,freebsd https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-portbld11-freebsd.tar.xz 48 | ghc 8.4.1 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.1-musl/ghc-8.4.1-i386-unknown-linux-musl.tar.xz 49 | ghc 8.4.1 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.1-musl/ghc-8.4.1-x86_64-unknown-linux-musl.tar.xz 50 | 51 | ghc 8.4.2 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-i386-deb8-linux.tar.xz 52 | ghc 8.4.2 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb8-linux.tar.xz 53 | ghc 8.4.2 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb9-linux.tar.xz 54 | ghc 8.4.2 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-fedora27-linux.tar.xz 55 | ghc 8.4.2 x86_64 darwin https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-apple-darwin.tar.xz 56 | ghc 8.4.2 x86_64 freebsd https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-portbld-freebsd.tar.xz 57 | ghc 8.4.2 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.2-musl/ghc-8.4.2-i386-unknown-linux-musl.tar.xz 58 | ghc 8.4.2 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.2-musl/ghc-8.4.2-x86_64-unknown-linux-musl.tar.xz 59 | 60 | ghc 8.4.3 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-i386-deb8-linux.tar.xz 61 | ghc 8.4.3 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb8-linux.tar.xz 62 | ghc 8.4.3 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb9-linux.tar.xz 63 | ghc 8.4.3 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-fedora27-linux.tar.xz 64 | ghc 8.4.3 x86_64 darwin https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-apple-darwin.tar.xz 65 | ghc 8.4.3 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.3-musl/ghc-8.4.3-i386-unknown-linux-musl.tar.xz 66 | ghc 8.4.3 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.3-musl/ghc-8.4.3-x86_64-unknown-linux-musl.tar.xz 67 | 68 | ghc 8.4.4 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-i386-deb8-linux.tar.xz 69 | ghc 8.4.4 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb8-linux.tar.xz 70 | ghc 8.4.4 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb9-linux.tar.xz 71 | ghc 8.4.4 x86_64 centos=7,centos,amazonlinux https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-centos70-linux.tar.xz 72 | ghc 8.4.4 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-fedora27-linux.tar.xz 73 | ghc 8.4.4 x86_64 darwin https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-apple-darwin.tar.xz 74 | ghc 8.4.4 x86_64 freebsd=11 https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-portbld-freebsd11.tar.xz 75 | ghc 8.4.4 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.4-musl/ghc-8.4.4-i386-unknown-linux-musl.tar.xz 76 | ghc 8.4.4 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.4.4-musl/ghc-8.4.4-x86_64-unknown-linux-musl.tar.xz 77 | 78 | ghc 8.6.1 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-i386-deb8-linux.tar.xz 79 | ghc 8.6.1 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb8-linux.tar.xz 80 | ghc 8.6.1 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb9-linux.tar.xz 81 | ghc 8.6.1 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-fedora27-linux.tar.xz 82 | ghc 8.6.1 x86_64 darwin https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-apple-darwin.tar.xz 83 | ghc 8.6.1 x86_64 freebsd https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-portbld-freebsd.tar.xz 84 | ghc 8.6.1 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.1-musl/ghc-8.6.1-i386-unknown-linux-musl.tar.xz 85 | ghc 8.6.1 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.1-musl/ghc-8.6.1-x86_64-unknown-linux-musl.tar.xz 86 | 87 | ghc 8.6.2 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-i386-deb8-linux.tar.xz 88 | ghc 8.6.2 x86_64 debian=8,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-deb8-linux.tar.xz 89 | ghc 8.6.2 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-fedora27-linux.tar.xz 90 | ghc 8.6.2 x86_64 darwin https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-apple-darwin.tar.xz 91 | ghc 8.6.2 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.2-musl/ghc-8.6.2-i386-unknown-linux-musl.tar.xz 92 | ghc 8.6.2 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.2-musl/ghc-8.6.2-x86_64-unknown-linux-musl.tar.xz 93 | 94 | ghc 8.6.3 i386 debian=8,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-i386-deb8-linux.tar.xz 95 | ghc 8.6.3 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb8-linux.tar.xz 96 | ghc 8.6.3 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb9-linux.tar.xz 97 | ghc 8.6.3 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-fedora27-linux.tar.xz 98 | ghc 8.6.3 x86_64 centos=7,centos,amazonlinux https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-centos7-linux.tar.xz 99 | ghc 8.6.3 x86_64 darwin https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-apple-darwin.tar.xz 100 | ghc 8.6.3 x86_64 freebsd=11 https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-portbld-freebsd.tar.xz 101 | ghc 8.6.3 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.3-musl/ghc-8.6.3-i386-unknown-linux-musl.tar.xz 102 | ghc 8.6.3 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.3-musl/ghc-8.6.3-x86_64-unknown-linux-musl.tar.xz 103 | 104 | ghc 8.6.4 i386 debian=9,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-i386-deb9-linux.tar.xz 105 | ghc 8.6.4 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb8-linux.tar.xz 106 | ghc 8.6.4 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb9-linux.tar.xz 107 | ghc 8.6.4 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-fedora27-linux.tar.xz 108 | ghc 8.6.4 x86_64 darwin https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-apple-darwin.tar.xz 109 | ghc 8.6.4 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.4-musl/ghc-8.6.4-i386-unknown-linux-musl.tar.xz 110 | ghc 8.6.4 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.4-musl/ghc-8.6.4-x86_64-unknown-linux-musl.tar.xz 111 | 112 | ghc 8.6.5 i386 debian=9,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-i386-deb9-linux.tar.xz 113 | ghc 8.6.5 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb8-linux.tar.xz 114 | ghc 8.6.5 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb9-linux.tar.xz 115 | ghc 8.6.5 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-fedora27-linux.tar.xz 116 | ghc 8.6.5 x86_64 centos=7,centos,amazonlinux https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-centos7-linux.tar.xz 117 | ghc 8.6.5 x86_64 darwin https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz 118 | ghc 8.6.5 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.5-musl/ghc-8.6.5-i386-unknown-linux-musl.tar.xz 119 | ghc 8.6.5 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.6.5-musl/ghc-8.6.5-x86_64-unknown-linux-musl.tar.xz 120 | 121 | ghc 8.8.1 i386 debian=9,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-i386-deb9-linux.tar.xz 122 | ghc 8.8.1 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb8-linux.tar.xz 123 | ghc 8.8.1 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb9-linux.tar.xz 124 | ghc 8.8.1 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-fedora27-linux.tar.xz 125 | ghc 8.8.1 x86_64 centos=7,centos,amazonlinux https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-centos7-linux.tar.xz 126 | ghc 8.8.1 x86_64 darwin https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-apple-darwin.tar.xz 127 | ghc 8.8.1 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.1-musl/ghc-8.8.1-i386-unknown-linux-musl.tar.xz 128 | ghc 8.8.1 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.1-musl/ghc-8.8.1-x86_64-unknown-linux-musl.tar.xz 129 | 130 | ghc 8.8.2 i386 debian=9,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-i386-deb9-linux.tar.xz 131 | ghc 8.8.2 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb8-linux.tar.xz 132 | ghc 8.8.2 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb9-linux.tar.xz 133 | ghc 8.8.2 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-fedora27-linux.tar.xz 134 | ghc 8.8.2 x86_64 centos=7,centos,amazonlinux https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-centos7-linux.tar.xz 135 | ghc 8.8.2 x86_64 darwin https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-apple-darwin.tar.xz 136 | ghc 8.8.2 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.2-musl/ghc-8.8.2-i386-unknown-linux-musl.tar.xz 137 | ghc 8.8.2 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.2-musl/ghc-8.8.2-x86_64-unknown-linux-musl.tar.xz 138 | 139 | ghc 8.8.3 i386 debian=9,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-i386-deb9-linux.tar.xz 140 | ghc 8.8.3 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb8-linux.tar.xz 141 | ghc 8.8.3 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04,mint https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb9-linux.tar.xz 142 | ghc 8.8.3 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-fedora27-linux.tar.xz 143 | ghc 8.8.3 x86_64 centos=7,centos,amazonlinux https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-centos7-linux.tar.xz 144 | ghc 8.8.3 x86_64 darwin https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-apple-darwin.tar.xz 145 | ghc 8.8.3 i386 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.3-musl/ghc-8.8.3-i386-unknown-linux-musl.tar.xz 146 | ghc 8.8.3 x86_64 alpine https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.3-musl/ghc-8.8.3-x86_64-unknown-linux-musl.tar.xz 147 | 148 | ghc 8.10.1 i386 debian=9,debian,ubuntu,mint,unknown https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-i386-deb9-linux.tar.xz 149 | ghc 8.10.1 x86_64 debian=9,debian,ubuntu=16.04,ubuntu=18.04 https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb9-linux.tar.xz 150 | ghc 8.10.1 x86_64 debian=10,mint https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb10-linux.tar.xz 151 | ghc 8.10.1 x86_64 fedora=27,fedora,ubuntu,unknown https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-fedora27-linux.tar.xz 152 | ghc 8.10.1 x86_64 centos=7,centos,amazonlinux https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-centos7-linux.tar.xz 153 | ghc 8.10.1 x86_64 darwin https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-apple-darwin.tar.xz 154 | ghc 8.10.1 x86_64 alpine https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-alpine3.10-linux-integer-simple.tar.xz 155 | 156 | cabal-install 2.2.0.0 i386 unknown https://downloads.haskell.org/~cabal/cabal-install-2.2.0.0/cabal-install-2.2.0.0-i386-unknown-linux.tar.gz 157 | cabal-install 2.2.0.0 x86_64 darwin https://downloads.haskell.org/~cabal/cabal-install-2.2.0.0/cabal-install-2.2.0.0-x86_64-apple-darwin-sierra.tar.gz 158 | cabal-install 2.2.0.0 x86_64 unknown https://downloads.haskell.org/~cabal/cabal-install-2.2.0.0/cabal-install-2.2.0.0-x86_64-unknown-linux.tar.gz 159 | 160 | cabal-install 2.4.0.0 x86_64 darwin https://downloads.haskell.org/~cabal/cabal-install-2.4.0.0/cabal-install-2.4.0.0-x86_64-apple-darwin-sierra.tar.gz 161 | cabal-install 2.4.0.0 x86_64 unknown https://downloads.haskell.org/~cabal/cabal-install-2.4.0.0/cabal-install-2.4.0.0-x86_64-unknown-linux.tar.gz 162 | 163 | cabal-install 2.4.1.0 powerpc aix=7 https://downloads.haskell.org/cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-powerpc-ibm-aix7.1.0.0.tar.xz 164 | cabal-install 2.4.1.0 x86_64 freebsd=11 https://downloads.haskell.org/cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-portbld-freebsd.tar.xz 165 | cabal-install 2.4.1.0 x86_64 darwin https://downloads.haskell.org/cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-apple-darwin-sierra.tar.xz 166 | cabal-install 2.4.1.0 x86_64 alpine https://downloads.haskell.org/cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-alpine-linux-musl.tar.xz 167 | cabal-install 2.4.1.0 i386 unknown https://downloads.haskell.org/cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-i386-unknown-linux.tar.xz 168 | cabal-install 2.4.1.0 x86_64 unknown https://downloads.haskell.org/cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-unknown-linux.tar.xz 169 | 170 | cabal-install 3.0.0.0 x86_64 darwin https://downloads.haskell.org/cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz 171 | cabal-install 3.0.0.0 i386 unknown https://downloads.haskell.org/cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-unknown-linux.tar.xz 172 | cabal-install 3.0.0.0 x86_64 unknown https://downloads.haskell.org/cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-unknown-linux.tar.xz 173 | 174 | cabal-install 3.2.0.0 x86_64 darwin https://downloads.haskell.org/cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-apple-darwin17.7.0.tar.xz 175 | cabal-install 3.2.0.0 i386 unknown https://downloads.haskell.org/cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-unknown-linux.tar.xz 176 | cabal-install 3.2.0.0 x86_64 unknown https://downloads.haskell.org/cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz 177 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | GIT_SSL_NO_VERIFY: "1" 3 | 4 | # Commit of ghc/ci-images repository from which to pull Docker images 5 | DOCKER_REV: cefaee3c742af193e0f7783f87edb0d35374515c 6 | 7 | ############################################################ 8 | # CI Step 9 | ############################################################ 10 | 11 | .debian: 12 | image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb9:$DOCKER_REV" 13 | tags: 14 | - x86_64-linux 15 | 16 | .darwin: 17 | tags: 18 | - x86_64-darwin 19 | 20 | .test_ghcup_version: 21 | script: 22 | - ./.gitlab/script/ghcup_version.sh 23 | 24 | .test_ghcup_version:linux: 25 | extends: 26 | - .test_ghcup_version 27 | - .debian 28 | before_script: 29 | - ./.gitlab/before_script/linux/install_deps.sh 30 | 31 | .test_ghcup_version:darwin: 32 | extends: 33 | - .test_ghcup_version 34 | - .darwin 35 | before_script: 36 | - ./.gitlab/before_script/darwin/install_deps.sh 37 | 38 | 39 | ######## shellcheck ######## 40 | 41 | test:shellcheck: 42 | extends: .debian 43 | before_script: 44 | - ./.gitlab/before_script/linux/install_shellcheck.sh 45 | script: ./.gitlab/script/shellcheck.sh 46 | 47 | 48 | ######## tarball caching ######## 49 | 50 | test:tarball_cache: 51 | extends: .debian 52 | variables: 53 | GHC_VERSION: "8.6.5" 54 | script: 55 | - ./.gitlab/script/ghcup_cached_tarball.sh 56 | 57 | 58 | ######## linux ######## 59 | 60 | test:linux:recommended: 61 | extends: .test_ghcup_version:linux 62 | variables: 63 | GHC_VERSION: "recommended" 64 | 65 | test:linux:latest: 66 | extends: .test_ghcup_version:linux 67 | variables: 68 | GHC_VERSION: "latest" 69 | 70 | test:linux:8.0.2: 71 | extends: .test_ghcup_version:linux 72 | variables: 73 | GHC_VERSION: "8.0.2" 74 | 75 | test:linux:8.2.2: 76 | extends: .test_ghcup_version:linux 77 | variables: 78 | GHC_VERSION: "8.2.2" 79 | 80 | test:linux:8.4.1: 81 | extends: .test_ghcup_version:linux 82 | variables: 83 | GHC_VERSION: "8.4.1" 84 | 85 | test:linux:8.4.2: 86 | extends: .test_ghcup_version:linux 87 | variables: 88 | GHC_VERSION: "8.4.2" 89 | 90 | test:linux:8.4.3: 91 | extends: .test_ghcup_version:linux 92 | variables: 93 | GHC_VERSION: "8.4.3" 94 | 95 | test:linux:8.4.4: 96 | extends: .test_ghcup_version:linux 97 | variables: 98 | GHC_VERSION: "8.4.4" 99 | 100 | test:linux:8.6.1: 101 | extends: .test_ghcup_version:linux 102 | variables: 103 | GHC_VERSION: "8.6.1" 104 | 105 | test:linux:8.6.2: 106 | extends: .test_ghcup_version:linux 107 | variables: 108 | GHC_VERSION: "8.6.2" 109 | 110 | test:linux:8.6.3: 111 | extends: .test_ghcup_version:linux 112 | variables: 113 | GHC_VERSION: "8.6.3" 114 | 115 | test:linux:8.6.4: 116 | extends: .test_ghcup_version:linux 117 | variables: 118 | GHC_VERSION: "8.6.4" 119 | 120 | test:linux:8.6.5: 121 | extends: .test_ghcup_version:linux 122 | variables: 123 | GHC_VERSION: "8.6.5" 124 | 125 | test:linux:8.8.1: 126 | extends: .test_ghcup_version:linux 127 | variables: 128 | GHC_VERSION: "8.8.1" 129 | 130 | test:linux:8.8.2: 131 | extends: .test_ghcup_version:linux 132 | variables: 133 | GHC_VERSION: "8.8.2" 134 | 135 | test:linux:8.8.3: 136 | extends: .test_ghcup_version:linux 137 | variables: 138 | GHC_VERSION: "8.8.3" 139 | 140 | test:linux:8.10.1: 141 | extends: .test_ghcup_version:linux 142 | variables: 143 | GHC_VERSION: "8.10.1" 144 | 145 | ######## darwin ######## 146 | 147 | test:mac:recommended: 148 | extends: .test_ghcup_version:darwin 149 | variables: 150 | GHC_VERSION: "recommended" 151 | 152 | test:mac:latest: 153 | extends: .test_ghcup_version:darwin 154 | variables: 155 | GHC_VERSION: "latest" 156 | 157 | test:mac:8.0.2: 158 | extends: .test_ghcup_version:darwin 159 | variables: 160 | GHC_VERSION: "8.0.2" 161 | 162 | test:mac:8.2.2: 163 | extends: .test_ghcup_version:darwin 164 | variables: 165 | GHC_VERSION: "8.2.2" 166 | 167 | test:mac:8.4.1: 168 | extends: .test_ghcup_version:darwin 169 | variables: 170 | GHC_VERSION: "8.4.1" 171 | 172 | test:mac:8.4.2: 173 | extends: .test_ghcup_version:darwin 174 | variables: 175 | GHC_VERSION: "8.4.2" 176 | 177 | test:mac:8.4.3: 178 | extends: .test_ghcup_version:darwin 179 | variables: 180 | GHC_VERSION: "8.4.3" 181 | 182 | test:mac:8.4.4: 183 | extends: .test_ghcup_version:darwin 184 | variables: 185 | GHC_VERSION: "8.4.4" 186 | 187 | test:mac:8.6.1: 188 | extends: .test_ghcup_version:darwin 189 | variables: 190 | GHC_VERSION: "8.6.1" 191 | # TODO: dyld: Library not loaded: /usr/local/opt/gmp/lib/libgmp.10.dylib 192 | allow_failure: true 193 | 194 | test:mac:8.6.2: 195 | extends: .test_ghcup_version:darwin 196 | variables: 197 | GHC_VERSION: "8.6.2" 198 | # TODO: dyld: Library not loaded: /usr/local/opt/gmp/lib/libgmp.10.dylib 199 | allow_failure: true 200 | 201 | test:mac:8.6.3: 202 | extends: .test_ghcup_version:darwin 203 | variables: 204 | GHC_VERSION: "8.6.3" 205 | 206 | test:mac:8.6.4: 207 | extends: .test_ghcup_version:darwin 208 | variables: 209 | GHC_VERSION: "8.6.4" 210 | 211 | test:mac:8.6.5: 212 | extends: .test_ghcup_version:darwin 213 | variables: 214 | GHC_VERSION: "8.6.5" 215 | 216 | test:mac:8.8.1: 217 | extends: .test_ghcup_version:darwin 218 | variables: 219 | GHC_VERSION: "8.8.1" 220 | 221 | test:mac:8.8.2: 222 | extends: .test_ghcup_version:darwin 223 | variables: 224 | GHC_VERSION: "8.8.2" 225 | 226 | test:mac:8.8.3: 227 | extends: .test_ghcup_version:darwin 228 | variables: 229 | GHC_VERSION: "8.8.3" 230 | 231 | test:mac:8.10.1: 232 | extends: .test_ghcup_version:darwin 233 | variables: 234 | GHC_VERSION: "8.10.1" 235 | -------------------------------------------------------------------------------- /.gitlab/before_script/darwin/install_deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | #sudo brew reinstall gmp 6 | 7 | exit 0 8 | -------------------------------------------------------------------------------- /.gitlab/before_script/linux/install_deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | sudo apt-get update -y 6 | sudo apt-get install -y libnuma-dev 7 | -------------------------------------------------------------------------------- /.gitlab/before_script/linux/install_shellcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | # install shellcheck 6 | wget https://github.com/koalaman/shellcheck/releases/download/latest/shellcheck-latest.linux.x86_64.tar.xz 7 | tar -xJf shellcheck-latest.linux.x86_64.tar.xz 8 | mkdir -p "$CI_PROJECT_DIR"/.local/bin/ 9 | mv shellcheck-latest/shellcheck "$CI_PROJECT_DIR"/.local/bin/shellcheck 10 | 11 | 12 | -------------------------------------------------------------------------------- /.gitlab/ghcup_env: -------------------------------------------------------------------------------- 1 | GHCUP_META_DOWNLOAD_URL="file://${CI_PROJECT_DIR}/.download-urls" 2 | export GHCUP_META_DOWNLOAD_URL 3 | GHCUP_META_VERSION_URL="file://${CI_PROJECT_DIR}/.available-versions" 4 | export GHCUP_META_VERSION_URL 5 | 6 | export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR" 7 | export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:$PATH" 8 | 9 | -------------------------------------------------------------------------------- /.gitlab/script/ghcup_cached_tarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | . "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env" 6 | 7 | mkdir -p "$CI_PROJECT_DIR"/.local/bin 8 | cp ./ghcup "$CI_PROJECT_DIR"/.local/bin/ghcup 9 | 10 | ghcup -v -c install 8.6.5 11 | test -f "$CI_PROJECT_DIR/.ghcup/cache/ghc-8.6.5-x86_64-deb9-linux.tar.xz" 12 | ghcup -v -c install 8.6.5 13 | 14 | -------------------------------------------------------------------------------- /.gitlab/script/ghcup_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | . "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env" 6 | 7 | mkdir -p "$CI_PROJECT_DIR"/.local/bin 8 | 9 | cp ./ghcup "$CI_PROJECT_DIR"/.local/bin/ghcup 10 | 11 | ghcup --version 12 | 13 | ghcup -v install ${GHC_VERSION} 14 | ghcup -v set ${GHC_VERSION} 15 | ghcup -v install-cabal 16 | 17 | cabal --version 18 | 19 | ghcup -v debug-info 20 | 21 | ghcup -v list 22 | ghcup -v list -t ghc 23 | ghcup -v list -t cabal-install 24 | 25 | ghc --version 26 | ghci --version 27 | ghc-$(ghc --numeric-version) --version 28 | ghci-$(ghc --numeric-version) --version 29 | 30 | ghcup -v upgrade 31 | 32 | ghcup -v rm -f ${GHC_VERSION} 33 | 34 | -------------------------------------------------------------------------------- /.gitlab/script/shellcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | . "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env" 6 | 7 | shellcheck ghcup 8 | 9 | -------------------------------------------------------------------------------- /.requirements/ghc/alpine: -------------------------------------------------------------------------------- 1 | curl gcc g++ gmp-dev ncurses-dev libffi-dev make xz tar perl 2 | -------------------------------------------------------------------------------- /.requirements/ghc/darwin: -------------------------------------------------------------------------------- 1 | (Note: on OS X, in the course of running ghcup you will be given a dialog box to install the command line tools. Accept and the requirements will be installed for you. You will then need to run the command again.) 2 | -------------------------------------------------------------------------------- /.requirements/ghc/default: -------------------------------------------------------------------------------- 1 | curl g++ gcc gmp make ncurses realpath xz-utils 2 | -------------------------------------------------------------------------------- /.requirements/ghc/ubuntu: -------------------------------------------------------------------------------- 1 | build-essential curl libgmp-dev libffi-dev libncurses-dev libtinfo5 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | ## [0.0.8](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.8) (2020-01-09) 4 | 5 | Release 0.0.8 6 | 7 | Distro support: 8 | * add some FreeBSD support 9 | * add linux mint support 10 | * add some redhat support 11 | * add some alpine support 12 | 13 | New tool versions: 14 | * GHC: 8.4.1, 8.4.2, 8.6.4, 8.6.5, 8.8.1 15 | * cabal: 3.0.0.0 16 | 17 | Commands and API: 18 | * new 'changelog' subcommand added 19 | * 'uprade' subcommand is tweaked': 20 | - add --inplace flag 21 | - by default install into BIN_LOCATION 22 | * new subcommand 'print-system-reqs' 23 | * 'compile' subcommand is now hidden from help menu (since it's only for power-users, use 'ghcup -v --help' to show all commands) 24 | * 'list' subcommand is overhauled and 'show' removed 25 | * allow to overwrite the distro detection system (see 'ghcup -v --help') 26 | * allow to overwrite meta download and meta version files via GHCUP_META_DOWNLOAD_URL and GHCUP_META_VERSION_URL 27 | 28 | Fixes: 29 | * clean up interrupted download cache properly 30 | * send debug output to stderr only 31 | * fix bug in bootstrap-haskell causing odd errors 32 | 33 | Other: 34 | * introduce major version symlinks (e.g. 8.6 -> 8.6.5) and add x.y tags 35 | * use GHCUP_INSTALL_BASE_PREFIX in bootstrap-haskell 36 | * don't reinstall cabal-install from source in bootstrap-haskell 37 | * various usability improvements in bootstrap-haskell 38 | * add bash-completion script 39 | * add manpage support when using man-db 40 | 41 | 42 | ## [0.0.7](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.7) (2019-01-07) 43 | 44 | Release 0.0.7 45 | 46 | This release introduces a new way of installing ghcup (and GHC and cabal in the process) 47 | with the infamous `curl .. | sh` pattern. See #36 for discussion. This 48 | is completely optional. 49 | 50 | Features: 51 | 52 | - Add a bootstrap-haskell script, fixes #36 53 | - Allow to specify tags for `ghcup install`, `ghcup install-cabal` and `ghcup set` 54 | - `ghcup list` also shows tags 55 | - support installing on macOS aka Darwin 56 | - Improve detection logic for CentOS/Alpine/AIX/FreeBSD 57 | - Introduce a GHCUP_INSTALL_BASE_PREFIX env variable to control where `.ghcup` directory will be created 58 | - Add rudimentary support for Amazon Linux 59 | 60 | Bugfixes: 61 | 62 | - Create missing haddock -> haddock-ghc symlink 63 | - Emit distro-alias inferred in `debug-info` output 64 | - Tweak exit code for `ghcup install` (If a GHC is already installed, we shouldn't treat it as an error) 65 | 66 | Cleanups: 67 | 68 | - Simplify mkdir calls 69 | - Documentation improvements 70 | - Error handling improvements 71 | 72 | API changes: 73 | 74 | - `self-update` was renamed to `upgrade` 75 | 76 | 77 | ## [0.0.6](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.6) (2018-10-30) 78 | 79 | Release 0.0.6 80 | 81 | 82 | ## [0.0.5](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.5) (2018-10-16) 83 | 84 | Release 0.0.5 85 | 86 | 87 | ## [0.0.4](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.4) (2018-10-09) 88 | 89 | Release 0.0.4 90 | 91 | 92 | ## [0.0.3](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.3) (2018-09-30) 93 | 94 | Release 0.0.3 95 | 96 | 97 | ## [0.0.2](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.2) (2018-09-30) 98 | 99 | Release 0.0.2 100 | 101 | 102 | ## [0.0.1](https://gitlab.haskell.org/haskell/ghcup/-/tags/0.0.1) (2018-09-29) 103 | 104 | Release 0.0.1 105 | 106 | 107 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | * PR or email 4 | * this script is POSIX shell 5 | * use [shellcheck](https://github.com/koalaman/shellcheck) and `checkbashisms.pl` from [debian devscripts](http://http.debian.net/debian/pool/main/d/devscripts/devscripts_2.18.4.tar.xz) 6 | * whitespaces, no tabs 7 | 8 | ## Adding a new distro, updating GHC versions, ... 9 | 10 | This script makes use of two files: 11 | 12 | 1. [.download-urls](https://gitlab.haskell.org/haskell/ghcup/raw/master/.download-urls), 13 | which is meta information on what binary tarball to download for the given version, architecture and distribution. 14 | If you know your distribution XY works with a tarball, add a `=` key to that line. `` 15 | will be the fallback and after that `unknown`. Lines are unique per tarball url. 16 | 2. [.available-versions](https://gitlab.haskell.org/haskell/ghcup/raw/master/.available-versions), 17 | which just lists available upstream versions and tags. 18 | 19 | ## TODO 20 | 21 | - [ ] FreeBSD support ([#4](https://gitlab.haskell.org/haskell/ghcup/issues/4)) 22 | - [x] Make fetching tarballs more robust ([#5](https://gitlab.haskell.org/haskell/ghcup/issues/5)) 23 | - [x] More code documentation 24 | - [x] Allow to compile from source ([#2](https://gitlab.haskell.org/haskell/ghcup/issues/2)) 25 | - [x] Allow to install cabal-install as well ([#3](https://gitlab.haskell.org/haskell/ghcup/issues/3)) 26 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Julian Ospald 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. Neither the name of the nor the names of its 13 | contributors may be used to endorse or promote products derived from 14 | this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **THIS PROJECT IS NOW DEPRECATED IN FAVOR OF [ghcup-hs](https://gitlab.haskell.org/haskell/ghcup-hs)** 2 | 3 | -- 4 | 5 | `ghcup` makes it easy to install specific versions of `ghc` on GNU/Linux as well as macOS (aka Darwin), and can also bootstrap a fresh Haskell developer environment from scratch. 6 | It follows the unix UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). 7 | 8 | Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be). 9 | 10 | *Ubuntu users may prefer [hvr's ppa](https://launchpad.net/~hvr/+archive/ubuntu/ghc).* 11 | 12 | *This project was started when [CM](https://github.com/capital-match) was switching from stack to [cabal nix-style builds](https://www.haskell.org/cabal/users-guide/nix-local-build-overview.html).* 13 | 14 | ## Table of Contents 15 | 16 | * [Installation](#installation) 17 | * [Usage](#usage) 18 | * [Manpages](#manpages) 19 | * [Design goals](#design-goals) 20 | * [How](#how) 21 | * [Known users](#known-users) 22 | * [Known problems](#known-problems) 23 | * [FAQ](#faq) 24 | 25 | ## Installation 26 | 27 | Choose one of the following installation methods. 28 | 29 | ### Simple bootstrap of ghcup, GHC and cabal-install 30 | 31 | ```sh 32 | # complete bootstrap 33 | curl https://gitlab.haskell.org/haskell/ghcup/raw/master/bootstrap-haskell -sSf | sh 34 | 35 | # prepare your environment 36 | . "$HOME/.ghcup/env" 37 | echo '. $HOME/.ghcup/env' >> "$HOME/.bashrc" # or similar 38 | 39 | # now create a project, such as: 40 | mkdir myproject && cd myproject 41 | cabal init -n --is-executable 42 | cabal v2-run 43 | ``` 44 | 45 | ### Manual install 46 | 47 | Just place the `ghcup` shell script into your `PATH` anywhere. 48 | 49 | E.g.: 50 | 51 | ```sh 52 | ( mkdir -p ~/.ghcup/bin && curl https://gitlab.haskell.org/haskell/ghcup/raw/master/ghcup > ~/.ghcup/bin/ghcup && chmod +x ~/.ghcup/bin/ghcup) && echo "Success" 53 | ``` 54 | 55 | Then adjust your `PATH` in `~/.bashrc` (or similar, depending on your shell) like so, for example: 56 | 57 | ```sh 58 | export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH" 59 | ``` 60 | 61 | Security aware users may want to use the files from the [release page](https://gitlab.haskell.org/haskell/ghcup/tags/) 62 | and verify the gpg signatures. 63 | 64 | ## Usage 65 | 66 | See `ghcup --help`. 67 | 68 | Common use cases are: 69 | 70 | ```sh 71 | # install the last known "best" GHC version 72 | ghcup install 73 | # install a specific GHC version 74 | ghcup install 8.2.2 75 | # set the currently "active" GHC version 76 | ghcup set 8.4.4 77 | # install cabal-install 78 | ghcup install-cabal 79 | # update cabal-install 80 | cabal new-install cabal-install 81 | ``` 82 | 83 | Generally this is meant to be used with [`cabal-install`](https://hackage.haskell.org/package/cabal-install), which 84 | handles your haskell packages and can demand that [a specific version](https://cabal.readthedocs.io/en/latest/nix-local-build.html#cfg-flag---with-compiler) of `ghc` is available, which `ghcup` can do. 85 | 86 | ### Manpages 87 | 88 | For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc. 89 | `MANPATH` may be required to be unset. 90 | 91 | ## Design goals 92 | 93 | 1. simplicity 94 | 2. non-interactive 95 | 3. portable 96 | 4. do one thing and do it well (UNIX philosophy) 97 | 98 | ### Non-goals 99 | 100 | 1. invoking `sudo`, `apt-get` or *any* package manager 101 | 2. handling system packages 102 | 3. handling cabal projects 103 | 4. being a stack alternative 104 | 105 | ## How 106 | 107 | Installs a specified GHC version into `~/.ghcup/ghc/`, and places `ghc-` symlinks in `~/.ghcup/bin/`. 108 | 109 | Optionally, an unversioned `ghc` link can point to a default version of your choice. 110 | 111 | This uses precompiled GHC binaries that have been compiled on fedora/debian by [upstream GHC](https://www.haskell.org/ghc/download_ghc_8_6_1.html#binaries). 112 | 113 | Alternatively, you can also tell it to compile from source (note that this might fail due to missing requirements). 114 | 115 | In addition this script can also install `cabal-install`. 116 | 117 | ## Known users 118 | 119 | * [vabal](https://github.com/Franciman/vabal) 120 | 121 | ## Known problems 122 | 123 | ### Limited distributions supported 124 | 125 | Currently only GNU/Linux distributions compatible with the [upstream GHC](https://www.haskell.org/ghc/download_ghc_8_6_1.html#binaries) binaries are supported. 126 | 127 | ### Precompiled binaries 128 | 129 | Since this uses precompiled binaries you may run into 130 | several problems. 131 | 132 | #### Missing libtinfo (ncurses) 133 | 134 | You may run into problems with *ncurses* and **missing libtinfo**, in case 135 | your distribution doesn't use the legacy way of building 136 | ncurses and has no compatibility symlinks in place. 137 | 138 | Ask your distributor on how to solve this or 139 | try to compile from source via `ghcup compile `. 140 | 141 | #### Libnuma required 142 | 143 | This was a [bug](https://ghc.haskell.org/trac/ghc/ticket/15688) in the build system of some GHC versions that lead to 144 | unconditionally enabled libnuma support. To mitigate this you might have to install the libnuma 145 | package of your distribution. See [here](https://gitlab.haskell.org/haskell/ghcup/issues/58) for a discussion. 146 | 147 | ### Compilation 148 | 149 | Although this script can compile GHC for you, it's just a very thin 150 | wrapper around the build system. It makes no effort in trying 151 | to figure out whether you have the correct toolchain and 152 | the correct dependencies. Refer to [the official docs](https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Linux) 153 | on how to prepare your environment for building GHC. 154 | 155 | ## FAQ 156 | 157 | 1. Why reimplement stack? 158 | 159 | ghcup is not a reimplementation of stack. The only common part is automatic installation of GHC, but even that differs in scope and design. 160 | 161 | 2. Why not contribute to stack and create a library for the common part? 162 | 163 | While this might be an interesting idea, ghcup is about simplicity. 164 | 165 | 3. Why write a >1000k LOC bash script? 166 | 167 | ghcup is POSIX sh. 168 | 169 | 4. Why write a >1000k LOC POSIX sh script? 170 | 171 | Mainly because the implementation is fairly straight-forward and the script is highly portable. No need to bootstrap anything or set up yet another CI to build ghcup binaries for all possible arches and distros just to perform a very simple task: identify distro and platform and download a GHC bindist. 172 | 173 | 5. Why not support windows? 174 | 175 | Consider using [Chocolatey](https://chocolatey.org/search?q=ghc) or [ghcups](https://github.com/kakkun61/ghcups). 176 | -------------------------------------------------------------------------------- /bootstrap-haskell: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # safety subshell to avoid executing anything in case this script is not downloaded properly 4 | ( 5 | 6 | : "${GHCUP_INSTALL_BASE_PREFIX:=$HOME}" 7 | 8 | die() { 9 | (>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1") 10 | exit 2 11 | } 12 | 13 | edo() 14 | { 15 | "$@" || die "\"$*\" failed!" 16 | } 17 | 18 | eghcup() { 19 | if [ -z "${BOOTSTRAP_HASKELL_VERBOSE}" ] ; then 20 | edo ghcup "$@" 21 | else 22 | edo ghcup --verbose "$@" 23 | fi 24 | } 25 | 26 | echo 27 | echo "Welcome to Haskell!" 28 | echo 29 | echo "This will download and install the Glasgow Haskell Compiler (GHC) for " 30 | echo "the Haskell programming language, and the Cabal build tool." 31 | echo 32 | echo "It will add the 'cabal', 'ghc', and 'ghcup' executables to bin directory " 33 | echo "located at: " 34 | echo 35 | echo " $GHCUP_INSTALL_BASE_PREFIX/.ghcup/bin" 36 | echo 37 | echo "and create the environment file $GHCUP_INSTALL_BASE_PREFIX/.ghcup/env" 38 | echo "which you should source in your ~/.bashrc or similar to get the required" 39 | echo "PATH components." 40 | echo 41 | 42 | if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then 43 | printf "\\033[0;35m%s\\033[0m\\n" "To proceed with the ghcup installation press ENTER, to cancel press ctrl-c." 44 | printf "\\033[0;35m%s\\033[0m\\n" "Note that this script can be re-run at any given time." 45 | echo 46 | # Wait for user input to continue. 47 | # shellcheck disable=SC2034 48 | read -r answer /dev/null 2>&1 ; then 54 | if [ -z "${BOOTSTRAP_HASKELL_NO_UPGRADE}" ] ; then 55 | eghcup upgrade 56 | fi 57 | else 58 | edo curl --silent https://gitlab.haskell.org/haskell/ghcup/raw/master/ghcup > "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup 59 | edo chmod +x "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup 60 | 61 | cat <<-EOF > "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/env || die "Failed to create env file" 62 | export PATH="\$HOME/.cabal/bin:\${GHCUP_INSTALL_BASE_PREFIX:=\$HOME}/.ghcup/bin:\$PATH" 63 | EOF 64 | # shellcheck disable=SC1090 65 | edo . "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/env 66 | fi 67 | 68 | echo 69 | printf "\\033[0;35m%s\\033[0m\\n" "To install and run GHC you need the following dependencies:" 70 | echo " $(ghcup print-system-reqs)" 71 | echo 72 | 73 | if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then 74 | printf "\\033[0;35m%s\\033[0m\\n" "You may want to install these now, then press ENTER to proceed" 75 | printf "\\033[0;35m%s\\033[0m\\n" "or press ctrl-c to abort. Installation may take a while." 76 | echo 77 | 78 | # Wait for user input to continue. 79 | # shellcheck disable=SC2034 80 | read -r answer > "${GHCUP_PROFILE_FILE}" 143 | printf "\\033[0;35m%s\\033[0m\\n" "OK! ${GHCUP_PROFILE_FILE} has been modified. Restart your terminal for the changes to take effect," 144 | printf "\\033[0;35m%s\\033[0m\\n" "or type \"source ${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/env\" to apply them in your current terminal session." 145 | exit 0;; 146 | [Nn]*) 147 | exit 0;; 148 | *) 149 | echo "Please type YES or NO and press enter.";; 150 | esac 151 | done 152 | fi 153 | ) 154 | 155 | # vim: tabstop=4 shiftwidth=4 expandtab 156 | 157 | -------------------------------------------------------------------------------- /generate_changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | printf "# ChangeLog\n\n" 4 | 5 | for current_tag in $(git tag --sort=-creatordate) ; do 6 | tag_date=$(git log -1 --pretty=format:'%ad' --date=short ${current_tag}) 7 | printf "## [${current_tag}](https://gitlab.haskell.org/haskell/ghcup/-/tags/${current_tag}) (${tag_date})\n\n" 8 | git --no-pager tag -l --format='%(contents)' ${current_tag} | sed -e '/BEGIN PGP/,$d' 9 | printf "\n\n" 10 | done 11 | 12 | -------------------------------------------------------------------------------- /ghcup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018, Julian Ospald 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # 2. Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # 3. Neither the name of the nor the names of its 15 | # contributors may be used to endorse or promote products derived from 16 | # this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | 32 | 33 | 34 | ########################## 35 | #--[ Global Variables ]--# 36 | ########################## 37 | 38 | 39 | # @VARIABLE: VERSION 40 | # @DESCRIPTION: 41 | # Version of this script. 42 | VERSION=0.0.8 43 | 44 | # @VARIABLE: SCRIPT 45 | # @DESCRIPTION: 46 | # Name of this script. This will be the 47 | # shell name if this script is sourced, so 48 | # only rely on this for echos and trivial things. 49 | SCRIPT="$(basename "$0")" 50 | 51 | # @VARIABLE: VERBOSE 52 | # @DESCRIPTION: 53 | # Whether to print verbose messages in this script. 54 | VERBOSE=false 55 | 56 | # @VARIABLE: FORCE 57 | # @DESCRIPTION: 58 | # Whether to force installation and overwrite files. 59 | FORCE=false 60 | 61 | # @VARIABLE: GHCUP_INSTALL_BASE_PREFIX 62 | # @DESCRIPTION: 63 | # The main install directory prefix, under which .ghcup 64 | # directory will be created. This directory is user 65 | # configurable via the environment variable of the 66 | # same name. It must be non-empty and the path 67 | # it points to must exist. 68 | : "${GHCUP_INSTALL_BASE_PREFIX:=$HOME}" 69 | 70 | # @VARIABLE: INSTALL_BASE 71 | # @DESCRIPTION: 72 | # The main install directory where all ghcup stuff happens. 73 | INSTALL_BASE="$GHCUP_INSTALL_BASE_PREFIX/.ghcup" 74 | 75 | # @VARIABLE: GHC_LOCATION 76 | # @DESCRIPTION: 77 | # The location where ghcup will install different ghc versions. 78 | # This is expected to be a subdirectory of INSTALL_BASE. 79 | GHC_LOCATION="$INSTALL_BASE/ghc" 80 | 81 | # @VARIABLE: BIN_LOCATION 82 | # @DESCRIPTION: 83 | # The location where ghcup will create symlinks for GHC binaries. 84 | # This is expected to be a subdirectory of INSTALL_BASE. 85 | BIN_LOCATION="$INSTALL_BASE/bin" 86 | 87 | # @VARIABLE: CACHE_LOCATION 88 | # @DESCRIPTION: 89 | # The location where ghcup will put tarballs for caching. 90 | # This is expected to be a subdirectory of INSTALL_BASE. 91 | CACHE_LOCATION="$INSTALL_BASE/cache" 92 | 93 | # @VARIABLE: DOWNLOADER 94 | # @DESCRIPTION: 95 | # What program to use for downloading files. 96 | DOWNLOADER="curl" 97 | 98 | # @VARIABLE: DOWNLOADER_OPTS 99 | # @DESCRIPTION: 100 | # Options passed to the download program. 101 | DOWNLOADER_OPTS="-L --fail -O" 102 | 103 | # @VARIABLE: DOWNLOADER_STDOUT_OPTS 104 | # @DESCRIPTION: 105 | # Options passed to the download program when printing the content to stdout. 106 | DOWNLOADER_STDOUT_OPTS="-L --fail" 107 | 108 | # @VARIABLE: GHC_DOWNLOAD_BASEURL 109 | # @DESCRIPTION: 110 | # Base URL for all GHC tarballs. 111 | GHC_DOWNLOAD_BASEURL="https://downloads.haskell.org/~ghc" 112 | 113 | # @VARIABLE: JOBS 114 | # @DESCRIPTION: 115 | # How many jobs to use for compiling GHC. 116 | JOBS="1" 117 | 118 | # @VARIABLE: SOURCE 119 | # @DESCRIPTION: 120 | # The $0 argument, which contains 121 | # the script name. 122 | SOURCE="$0" 123 | 124 | # @VARIABLE: BASE_DOWNLOAD_URL 125 | # DESCRIPTION: 126 | # The base url for downloading stuff like meta files, requirements files etc. 127 | BASE_DOWNLOAD_URL="https://gitlab.haskell.org/haskell/ghcup/raw/master/" 128 | 129 | # @VARIABLE: SCRIPT_UPDATE_URL 130 | # @DESCRIPTION: 131 | # Location to update this script from. 132 | SCRIPT_UPDATE_URL="${BASE_DOWNLOAD_URL}/ghcup" 133 | 134 | # @VARIABLE: META_DOWNLOAD_URL 135 | # DESCRIPTION: 136 | # The url of the meta file for getting 137 | # download information for ghc/cabal-install etc. 138 | META_DOWNLOAD_URL="${GHCUP_META_DOWNLOAD_URL:=${BASE_DOWNLOAD_URL}/.download-urls}" 139 | 140 | # @VARIABLE: META_DOWNLOAD_FORMAT 141 | # DESCRIPTION: 142 | # The version of the meta file format. 143 | # This determines whether this script can read the 144 | # file from "${META_DOWNLOAD_URL}". 145 | META_DOWNLOAD_FORMAT="1" 146 | 147 | # @VARIABLE: META_VERSION_URL 148 | # DESCRIPTION: 149 | # The url of the meta file for getting 150 | # available versions for ghc/cabal-install etc. 151 | META_VERSION_URL="${GHCUP_META_VERSION_URL:=${BASE_DOWNLOAD_URL}/.available-versions}" 152 | 153 | # @VARIABLE: META_VERSION_FORMAT 154 | # DESCRIPTION: 155 | # The version of the meta file format. 156 | # This determines whether this script can read the 157 | # file from "${META_VERSION_URL}". 158 | META_VERSION_FORMAT="1" 159 | 160 | # @VARIABLE: BUG_URL 161 | # DESCRIPTION: 162 | # The url to report bugs to. 163 | BUG_URL="https://gitlab.haskell.org/haskell/ghcup/issues" 164 | 165 | # @VARIABLE: CACHING 166 | # @DESCRIPTION: 167 | # Whether to cache tarballs in $CACHE_LOCATION. 168 | CACHING=false 169 | 170 | 171 | 172 | #################### 173 | #--[ Print Help ]--# 174 | #################### 175 | 176 | 177 | # @FUNCTION: usage 178 | # @DESCRIPTION: 179 | # Print the help message for 'ghcup' to STDERR 180 | # and exit the script with status code 1. 181 | usage() { 182 | (>&2 echo "ghcup ${VERSION} 183 | GHC up toolchain installer 184 | 185 | USAGE: 186 | ${SCRIPT} [FLAGS] 187 | 188 | FLAGS: 189 | -v, --verbose Enable verbose output 190 | -h, --help Prints help information 191 | -V, --version Prints version information 192 | -w, --wget Use wget instead of curl 193 | -c, --cache Use \"${CACHE_LOCATION}\" for caching tarballs 194 | (these will not be removed by ghcup)$(${VERBOSE} && printf "\n -o, --os Overwrite OS detection with the given string (must be a correct OS alias, e.g. 'alpine')") 195 | 196 | SUBCOMMANDS: 197 | install Install GHC$(${VERBOSE} && printf "\n compile Compile and install GHC from source (UNSTABLE!!!)") 198 | set Set currently active GHC version 199 | list Show available GHCs and other tools 200 | upgrade Upgrade this script in-place 201 | rm Remove an already installed GHC 202 | install-cabal Install cabal-install 203 | debug-info Print debug info (e.g. detected system/distro) 204 | changelog Show the changelog of a GHC release (online) 205 | print-system-reqs Print an approximation of system requirements 206 | 207 | DISCUSSION: 208 | ghcup installs the Glasgow Haskell Compiler from the official 209 | release channels, enabling you to easily switch between different 210 | versions. 211 | ") 212 | exit 1 213 | } 214 | 215 | # @FUNCTION: install_usage 216 | # @DESCRIPTION: 217 | # Print the help message for 'ghcup install' to STDERR 218 | # and exit the script with status code 1. 219 | install_usage() { 220 | (>&2 echo "ghcup-install 221 | Install GHC from binary tarball 222 | 223 | USAGE: 224 | ${SCRIPT} install [FLAGS] [VERSION|TAG] 225 | 226 | FLAGS: 227 | -h, --help Prints help information 228 | -f, --force Overwrite already existing installation 229 | 230 | ARGS: 231 | [VERSION|TAG] E.g. \"8.4.3\" or \"8.6.1\" or 232 | a tag like \"recommended\" or \"latest\" 233 | (default: discovers recommended version) 234 | 235 | DISCUSSION: 236 | Installs the specified GHC version (or a recommended default one) into 237 | a self-contained \"~/.ghcup/ghc/\" directory 238 | and symlinks the ghc binaries to \"~/.ghcup/bin/-\". 239 | ") 240 | exit 1 241 | } 242 | 243 | # @FUNCTION: set_usage 244 | # @DESCRIPTION: 245 | # Print the help message for 'ghcup set' to STDERR 246 | # and exit the script with status code 1. 247 | set_usage() { 248 | (>&2 echo "ghcup-set 249 | Set the currently active GHC to the specified version 250 | 251 | USAGE: 252 | ${SCRIPT} set [FLAGS] [VERSION|TAG] 253 | 254 | FLAGS: 255 | -h, --help Prints help information 256 | 257 | ARGS: 258 | [VERSION|TAG] E.g. \"8.4.3\" or \"8.6.3\" or 259 | a tag like \"recommended\" or \"latest\" 260 | (default: discovers recommended version) 261 | 262 | DISCUSSION: 263 | Sets the the current GHC version by creating non-versioned 264 | symlinks for all ghc binaries of the specified version in 265 | \"~/.ghcup/bin/\". 266 | ") 267 | exit 1 268 | } 269 | 270 | # @FUNCTION: upgrade_usage 271 | # @DESCRIPTION: 272 | # Print the help message for 'ghcup upgrade' to STDERR 273 | # and exit the script with status code 1. 274 | upgrade_usage() { 275 | (>&2 echo "ghcup-upgrade 276 | Update the ghcup script in-place 277 | 278 | USAGE: 279 | ${SCRIPT} upgrade [FLAGS] [TARGET-LOCATION] 280 | 281 | FLAGS: 282 | -i, --inplace Update this script in-place (wherever it's at) 283 | -h, --help Prints help information 284 | 285 | ARGS: 286 | [TARGET-LOCATION] Where to place the updated script (defaults to ${BIN_LOCATION}). 287 | This is ignored if --inplace is issued as well. 288 | ") 289 | exit 1 290 | } 291 | 292 | # @FUNCTION: rm_usage 293 | # @DESCRIPTION: 294 | # Print the help message for 'ghcup rm' to STDERR 295 | # and exit the script with status code 1. 296 | rm_usage() { 297 | (>&2 echo "ghcup-rm 298 | Remove the given GHC version installed by ghcup 299 | 300 | USAGE: 301 | ${SCRIPT} rm [FLAGS] 302 | 303 | FLAGS: 304 | -h, --help Prints help information 305 | -f, --force Don't prompt user 306 | 307 | ARGS: 308 | E.g. \"8.4.3\" or \"8.6.1\" 309 | ") 310 | exit 1 311 | } 312 | 313 | # @FUNCTION: install_cabal_usage 314 | # @DESCRIPTION: 315 | # Print the help message for 'ghcup install-cabal' to STDERR 316 | # and exit the script with status code 1. 317 | install_cabal_usage() { 318 | (>&2 echo "ghcup-install-cabal 319 | Install the specified or a default cabal version 320 | 321 | USAGE: 322 | ${SCRIPT} install-cabal [FLAGS] [VERSION|TAG] 323 | 324 | FLAGS: 325 | -h, --help Prints help information 326 | 327 | ARGS: 328 | [VERSION|TAG] E.g. \"2.4.0.0\" or a tag 329 | like \"recommended\" or \"latest\" 330 | 331 | DISCUSSION: 332 | Installs the specified cabal-install version (or the default recommended) 333 | into \"${BIN_LOCATION}\", so it can be overwritten 334 | by later \"cabal new-install cabal-install\", which installs into 335 | \"~/.cabal/bin\". Make sure to set up your PATH appropriately, so 336 | the cabal installation takes precedence. 337 | ") 338 | exit 1 339 | } 340 | 341 | # @FUNCTION: compile_usage 342 | # @DESCRIPTION: 343 | # Print the help message for 'ghcup compile' to STDERR 344 | # and exit the script with status code 1. 345 | compile_usage() { 346 | (>&2 echo "ghcup-compile 347 | Compile and install the specified GHC version 348 | 349 | USAGE: 350 | ${SCRIPT} compile [FLAGS] 351 | 352 | FLAGS: 353 | -h, --help Prints help information 354 | -f, --force Overwrite already existing installation 355 | -j, --jobs How many jobs for compilation 356 | -c, --build-config Use the given config file as build config 357 | 358 | ARGS: 359 | E.g. \"8.4.3\" or \"8.6.1\" 360 | E.g. \"ghc-8.2.2\" or a full path 361 | 362 | DISCUSSION: 363 | Compiles and installs the specified GHC version into 364 | a self-contained \"~/.ghcup/ghc/\" directory 365 | and symlinks the ghc binaries to \"~/.ghcup/bin/-\". 366 | 367 | EXAMPLE: 368 | ghcup -v compile -f -j 4 8.4.2 ghc-8.2.2 369 | ") 370 | exit 1 371 | } 372 | 373 | # @FUNCTION: debug_info_usage 374 | # @DESCRIPTION: 375 | # Print the help message for 'ghcup debug-info' to STDERR 376 | # and exit the script with status code 1. 377 | debug_info_usage() { 378 | (>&2 echo "ghcup-debug-info 379 | Print debug info (e.g. detected system/distro) 380 | 381 | USAGE: 382 | ${SCRIPT} debug-info 383 | 384 | FLAGS: 385 | -h, --help Prints help information 386 | 387 | DISCUSSION: 388 | Prints debug information, e.g. detected system architecture, 389 | distribution, version, as well as script variables. This 390 | is mainly useful for debugging purposes. 391 | ") 392 | exit 1 393 | } 394 | 395 | # @FUNCTION: list_usage 396 | # @DESCRIPTION: 397 | # Print the help message for 'ghcup list' to STDERR 398 | # and exit the script with status code 1. 399 | list_usage() { 400 | (>&2 echo "ghcup-list 401 | Show available GHCs and other tools 402 | 403 | USAGE: 404 | ${SCRIPT} list 405 | 406 | FLAGS: 407 | -h, --help Prints help information 408 | -t, --tool Tool to list versions for. Default is ghc only. 409 | -c, --show-criteria Show only installed or set tool versions 410 | -r, --raw-format Raw format, for machine parsing 411 | 412 | DISCUSSION: 413 | Prints tools (e.g. GHC and cabal-install) and their 414 | available/installed/set versions. 415 | ") 416 | exit 1 417 | } 418 | 419 | # @FUNCTION: changelog_usage 420 | # @DESCRIPTION: 421 | # Print the help message for 'ghcup changelog' to STDERR 422 | # and exit the script with status code 1. 423 | changelog_usage() { 424 | (>&2 echo "ghcup-changelog 425 | View the online changelog for the given GHC version 426 | 427 | USAGE: 428 | ${SCRIPT} changelog [FLAGS] [VERSION|TAG] 429 | 430 | FLAGS: 431 | -h, --help Prints help information 432 | 433 | ARGS: 434 | [VERSION|TAG] E.g. \"8.4.3\" or \"8.6.3\" or 435 | a tag like \"recommended\" or \"latest\" 436 | (default: discovers latest version) 437 | 438 | DISCUSSION: 439 | Opens the online changelog for the given GHC version via 440 | xdg-open. 441 | ") 442 | exit 1 443 | } 444 | 445 | # @FUNCTION: print_system_reqs_usage 446 | # @DESCRIPTION: 447 | # Print the help message for 'ghcup print-system-reqs' to STDERR 448 | # and exit the script with status code 1. 449 | print_system_reqs_usage() { 450 | (>&2 echo "ghcup-print-system-reqs 451 | Print an approximation of system requirements 452 | 453 | USAGE: 454 | ${SCRIPT} print-system-reqs 455 | 456 | FLAGS: 457 | -h, --help Prints help information 458 | 459 | DISCUSSION: 460 | Just prints an approximation of the system requirements 461 | for the 'recommended' GHC version and the 'latest' distro version 462 | you are on. 463 | 464 | Review this output carefully! 465 | ") 466 | exit 1 467 | } 468 | 469 | 470 | 471 | 472 | ########################### 473 | #--[ Utility functions ]--# 474 | ########################### 475 | 476 | 477 | # @FUNCTION: die 478 | # @USAGE: [msg] 479 | # @DESCRIPTION: 480 | # Exits the shell script with status code 2 481 | # and prints the given message in red to STDERR, if any. 482 | die() { 483 | (>&2 red_message "$1") 484 | exit 2 485 | } 486 | 487 | # @FUNCTION: edo 488 | # @USAGE: 489 | # @DESCRIPTION: 490 | # Executes the given command. Also prints what 491 | # command that is (in blue) if verbosity is enabled. 492 | # Exits with status code 2 if the command failed. 493 | edo() 494 | { 495 | if ${VERBOSE} ; then 496 | printf "\\033[0;34m%s\\033[0m\\n" "$*" 1>&2 497 | fi 498 | "$@" || exit 2 499 | } 500 | 501 | # @FUNCTION: emake 502 | # @USAGE: [arguments] 503 | # @DESCRIPTION: 504 | # Wrapper around 'make', may call 'gmake' if it exists. 505 | emake() { # avoid re-checking for gmake 506 | if [ -n "${MAKE}" ] ; then 507 | # shellcheck disable=SC2086 508 | edo ${MAKE} "$@" 509 | else 510 | if command_exists gmake ; then 511 | MAKE="gmake" 512 | # shellcheck disable=SC2086 513 | edo ${MAKE} "$@" 514 | else 515 | MAKE="make" 516 | # shellcheck disable=SC2086 517 | edo ${MAKE} "$@" 518 | fi 519 | fi 520 | } 521 | 522 | # @FUNCTION: debug_message 523 | # @USAGE: 524 | # @DESCRIPTION: 525 | # Print a blue debug message if verbosity is enabled. 526 | debug_message() { 527 | if ${VERBOSE} ; then 528 | (>&2 printf "\\033[0;34m%s\\033[0m\\n" "$1") 529 | fi 530 | } 531 | 532 | # @FUNCTION: optionv 533 | # @USAGE: [arg2] 534 | # @DESCRIPTION: 535 | # If verbosity is enabled, echo the first argument, otherwise 536 | # the second (if any). 537 | # @STDOUT: first or second argument 538 | optionv() { 539 | if ${VERBOSE} ; then 540 | echo "$1" 541 | else 542 | if [ -n "$2" ] ; then 543 | echo "$2" 544 | fi 545 | fi 546 | } 547 | 548 | # @FUNCTION: status_message 549 | # @USAGE: 550 | # @DESCRIPTION: 551 | # Print a green status message. 552 | status_message() { 553 | printf "\\033[0;32m%s\\033[0m\\n" "$1" 554 | } 555 | 556 | # @FUNCTION: warning_message 557 | # @USAGE: 558 | # @DESCRIPTION: 559 | # Print a yellow warning message. 560 | warning_message() { 561 | printf "\\033[1;33m%s\\033[0m\\n" "$1" 562 | } 563 | 564 | # @FUNCTION: red_message 565 | # @USAGE: 566 | # @DESCRIPTION: 567 | # Print a red message. 568 | red_message() { 569 | printf "\\033[0;31m%s\\033[0m\\n" "$1" 570 | } 571 | 572 | # @FUNCTION: command_exists 573 | # @USAGE: 574 | # @DESCRIPTION: 575 | # Check if a command exists (no arguments). 576 | # @RETURNS: 0 if the command exists, non-zero otherwise 577 | command_exists() { 578 | [ -z "$1" ] && die "Internal error: no argument given to command_exists" 579 | 580 | command -V "$1" >/dev/null 2>&1 581 | return $? 582 | } 583 | 584 | # @FUNCTION: check_required_commands 585 | # @USAGE: [additional-commands] 586 | # @DESCRIPTION: 587 | # Check that all required commands for this script exist. 588 | # @STDOUT: The commands that do not exist 589 | # @RETURNS: 0 if all command exists, non-zero otherwise 590 | check_required_commands() { 591 | _missing_commands= 592 | mydistro=$(get_distro_alias "$(get_distro_name)") 593 | 594 | for com in "$@" awk uname basename tar gzip mktemp dirname ; do 595 | command_exists "${com}" || { 596 | _missing_commands="${_missing_commands} ${com}" 597 | } 598 | done 599 | unset com 600 | 601 | # darwin uses tar's built-in xz decompression 602 | if test "${mydistro}" != "darwin"; then 603 | command_exists xz || { 604 | _missing_commands="${_missing_commands} xz" 605 | } 606 | fi 607 | 608 | if [ -n "${_missing_commands}" ] ; then 609 | printf "%s" "${_missing_commands}" 610 | unset _missing_commands mydistro 611 | return 1 612 | else 613 | unset _missing_commands mydistro 614 | return 0 615 | fi 616 | } 617 | 618 | # @FUNCTION: get_distro_name 619 | # @DESCRIPTION: 620 | # Gets the current distro identifier following 621 | # https://unix.stackexchange.com/a/6348 622 | # (see also http://linuxmafia.com/faq/Admin/release-files.html) 623 | # @STDOUT: current distro identifier 624 | get_distro_name() { 625 | if [ -f /etc/os-release ]; then 626 | # freedesktop.org and systemd 627 | # shellcheck disable=SC1091 628 | . /etc/os-release 629 | printf "%s" "$NAME" 630 | elif command_exists lsb_release ; then 631 | # linuxbase.org 632 | printf "%s" "$(lsb_release -si)" 633 | elif [ -f /etc/lsb-release ]; then 634 | # For some versions of Debian/Ubuntu without lsb_release command 635 | # shellcheck disable=SC1091 636 | . /etc/lsb-release 637 | printf "%s" "$DISTRIB_ID" 638 | elif [ -f /etc/redhat-release ]; then 639 | case "$(cat /etc/redhat-release)" in 640 | # Older CentOS releases didn't have a /etc/centos-release file 641 | "CentOS release "*) 642 | printf "CentOS" 643 | ;; 644 | "CentOS Linux release "*) 645 | printf "CentOS Linux" 646 | ;; 647 | "Fedora release "*) 648 | printf "Fedora" 649 | ;; 650 | # Fallback to uname 651 | *) 652 | printf "%s" "$(uname -s)" 653 | ;; 654 | esac 655 | elif [ -f /etc/debian_version ]; then 656 | # Older Debian/Ubuntu/etc. 657 | printf "Debian" 658 | else 659 | # Fall back to uname, e.g. "Linux ", also works for BSD, etc. 660 | printf "%s" "$(uname -s)" 661 | fi 662 | } 663 | 664 | # @FUNCTION: get_distro_ver 665 | # @DESCRIPTION: 666 | # Gets the current distro version (if any) following 667 | # https://unix.stackexchange.com/a/6348 668 | # @STDOUT: current distro version, if any 669 | get_distro_ver() { 670 | if [ -f /etc/os-release ]; then 671 | # freedesktop.org and systemd 672 | # shellcheck disable=SC1091 673 | . /etc/os-release 674 | printf "%s" "$VERSION_ID" 675 | elif command_exists lsb_release ; then 676 | # linuxbase.org 677 | printf "%s" "$(lsb_release -sr)" 678 | elif [ -f /etc/lsb-release ]; then 679 | # For some versions of Debian/Ubuntu without lsb_release command 680 | # shellcheck disable=SC1091 681 | . /etc/lsb-release 682 | printf "%s" "$DISTRIB_RELEASE" 683 | elif [ -f /etc/redhat-release ]; then 684 | case "$(cat /etc/redhat-release)" in 685 | # NB: Older CentOS releases didn't have a /etc/centos-release file 686 | "CentOS release "*|"Fedora release "*) 687 | printf "%s" "$(awk 'NR==1 { split($3, a, "."); print a[1] }' /etc/redhat-release)" 688 | ;; 689 | "CentOS Linux release "*) 690 | printf "%s" "$(awk 'NR==1 { split($4, a, "."); print a[1] }' /etc/redhat-release)" 691 | ;; 692 | # Fallback to uname 693 | *) 694 | printf "%s" "$(uname -r)" 695 | ;; 696 | esac 697 | elif [ -f /etc/debian_version ]; then 698 | # Older Debian/Ubuntu/etc. 699 | printf "%s" "$(cat /etc/debian_version)" 700 | else 701 | case "$(uname -s)" in 702 | AIX) 703 | printf "%s" "$(uname -v)" 704 | ;; 705 | FreeBSD) 706 | # we only care about the major numeric version part left of 707 | # the '.' in "11.2-RELEASE". 708 | printf "%s" "$(uname -r | cut -d . -f 1)" 709 | ;; 710 | *) 711 | # Fall back to uname, e.g. "Linux ", also works for BSD, etc. 712 | printf "%s" "$(uname -r)" 713 | esac 714 | fi 715 | } 716 | 717 | # @FUNCTION: get_arch 718 | # @DESCRIPTION: 719 | # Gets the architecture following 720 | # https://unix.stackexchange.com/a/6348 721 | # Fails for any architecture that we don't know a GHC version for. 722 | # @STDOUT: current architecture 723 | get_arch() { 724 | myarch=$(uname -m) 725 | 726 | case "${myarch}" in 727 | x86_64|amd64) 728 | printf "x86_64" # or AMD64 or Intel64 or whatever 729 | ;; 730 | i*86) 731 | printf "i386" # or IA32 or Intel32 or whatever 732 | ;; 733 | *) 734 | case "$(uname -s)" in 735 | AIX) 736 | case "$(uname -p)" in 737 | powerpc) 738 | printf "powerpc" 739 | ;; 740 | *) 741 | die "Cannot figure out architecture on AIX (was: ${myarch})" 742 | ;; 743 | esac 744 | ;; 745 | *) 746 | die "Cannot figure out architecture (was: ${myarch})" 747 | ;; 748 | esac 749 | esac 750 | 751 | unset myarch 752 | } 753 | 754 | # @FUNCTION: try_download_url 755 | # @USAGE: 756 | # @DESCRIPTION: 757 | # Tries to get the download url of a tool with our 758 | # specified format for download urls (see ${META_DOWNLOAD_URL}"). 759 | # STDOUT: the download url, if an appropriate was found 760 | try_download_url() { 761 | [ "$#" -lt 5 ] && die "Internal error: not enough arguments to try_download_url" 762 | 763 | tool=$1 764 | ver=$2 765 | arch=$3 766 | distro_ident=$4 767 | filename=$5 768 | 769 | awk " 770 | NF { 771 | split(\$4,a,\",\") 772 | if (\$1 == \"${tool}\" && \$2 == \"${ver}\" && \$3 == \"${arch}\") { 773 | for (i in a) if (a[i] == \"${distro_ident}\") { 774 | print \$5 775 | exit 776 | } 777 | } 778 | }" "${filename}" || die "awk failed!" 779 | 780 | unset tool ver arch distro_ident filename 781 | } 782 | 783 | # @FUNCTION: check_meta_file_version 784 | # @USAGE: 785 | # @DESCRIPTION: 786 | # Check that the given meta file has the same format version 787 | # as specified, otherwise die. 788 | check_meta_file_version() { 789 | { [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to check_meta_file_version" 790 | 791 | mymetavar=$(awk " 792 | NR==1 { 793 | if (\$2 ~ \"fmt-version\") { 794 | { 795 | split(\$2,a,\"=\") 796 | print a[2] 797 | exit 798 | } 799 | } 800 | }" "$1") 801 | 802 | if [ "${mymetavar}" != "$2" ] ; then 803 | die "Unsupported meta file format, run: ${SCRIPT} upgrade" 804 | fi 805 | 806 | unset mymetavar 807 | } 808 | 809 | # @FUNCTION: get_download_url 810 | # @USAGE: [os-overwrite] 811 | # @DESCRIPTION: 812 | # Gets the download url for the given tool and version 813 | # and the current distro and architecture (which it tries to discover). 814 | # This uses "${META_DOWNLOAD_URL}" for url discovery. 815 | # @STDOUT: download url or nothing if no appropriate was found 816 | get_download_url() { 817 | { [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to get_download_url" 818 | 819 | mytool=$1 820 | myver=$2 821 | myarch=$(get_arch) 822 | [ -z "${myarch}" ] && die "failed to get architecture" 823 | if [ -n "$3" ] ; then 824 | mydistro=$(get_distro_alias "$3") 825 | else 826 | mydistro=$(get_distro_alias "$(get_distro_name)") 827 | fi 828 | mydistrover=$(get_distro_ver) 829 | meta_file="$(get_meta_download_file)" 830 | [ -z "${meta_file}" ] && die "failed to get meta file" 831 | 832 | 833 | # 1st try with full distro=ver 834 | url=$(try_download_url "${mytool}" "${myver}" "${myarch}" "${mydistro}=${mydistrover}" "${meta_file}") 835 | if [ -n "${url}" ] ; then 836 | printf "%s" "${url}" 837 | exit 0 838 | fi 839 | 840 | # 2nd try with just distro 841 | url=$(try_download_url "${mytool}" "${myver}" "${myarch}" "${mydistro}" "${meta_file}") 842 | if [ -n "${url}" ] ; then 843 | printf "%s" "${url}" 844 | exit 0 845 | fi 846 | 847 | # 3rd try with unknown 848 | url=$(try_download_url "${mytool}" "${myver}" "${myarch}" "unknown" "${meta_file}") 849 | if [ -n "${url}" ] ; then 850 | printf "%s" "${url}" 851 | exit 0 852 | fi 853 | 854 | unset mytool myver myarch mydistro mydistrover meta_file 855 | } 856 | 857 | # @FUNCTION: get_tool_ver_from_tag 858 | # @USAGE: 859 | # @DESCRIPTION: 860 | # Gets the tool version with the given tag (first match) from 861 | # "${META_VERSION_URL}". 862 | # STDOUT: the version, if any, or nothing 863 | get_tool_ver_from_tag() { 864 | { [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to get_tool_ver_from_tag" 865 | 866 | mytool=$1 867 | mytag=$2 868 | 869 | meta_file="$(get_meta_version_file)" 870 | [ -z "${meta_file}" ] && die "failed to get meta file" 871 | 872 | awk " 873 | NF { 874 | if (\$1 == \"${mytool}\") { 875 | split(\$3,a,\",\"); 876 | for (i in a) if (a[i] == \"${mytag}\") { 877 | print \$2 878 | exit 879 | } 880 | } 881 | }" "${meta_file}" || die "awk failed!" 882 | 883 | unset mytool mytag meta_file 884 | } 885 | 886 | # @FUNCTION: ghc_already_installed 887 | # @USAGE: 888 | # @DESCRIPTION: 889 | # Checks whether the specified GHC version 890 | # has been installed by ghcup already. 891 | # @RETURN: 0 if GHC is already installed, 1 otherwise 892 | ghc_already_installed() { 893 | [ -z "$1" ] && die "Internal error: no argument given to ghc_already_installed" 894 | 895 | if [ -e "$(get_ghc_location "$1")" ] ; then 896 | return 0 897 | else 898 | return 1 899 | fi 900 | } 901 | 902 | # @FUNCTION: cabal_already_installed 903 | # @USAGE: 904 | # @DESCRIPTION: 905 | # Checks whether the specified cabal version 906 | # has been installed by ghcup already. 907 | # @RETURN: 0 if cabal is already installed, 1 otherwise 908 | cabal_already_installed() { 909 | [ -z "$1" ] && die "Internal error: no argument given to cabal_already_installed" 910 | 911 | if [ -x "${BIN_LOCATION}/cabal" ] ; then 912 | if [ "$("${BIN_LOCATION}/cabal" --numeric-version)" = "$1" ] ; then 913 | return 0 914 | else 915 | return 1 916 | fi 917 | else 918 | return 1 919 | fi 920 | } 921 | 922 | # @FUNCTION: tool_already_installed 923 | # @USAGE: 924 | # @DESCRIPTION: 925 | # Checks whether the specified tool and version 926 | # has been installed by ghcup already. 927 | # @RETURN: 0 if tool is already installed, 1 otherwise 928 | tool_already_installed() { 929 | if [ "$1" = "ghc" ] ; then 930 | ghc_already_installed "$2" 931 | return $? 932 | elif [ "$1" = "cabal-install" ] ; then 933 | cabal_already_installed "$2" 934 | return $? 935 | else 936 | return 1 937 | fi 938 | } 939 | 940 | 941 | # @FUNCTION: get_ghc_location 942 | # @USAGE: 943 | # @DESCRIPTION: 944 | # Gets/prints the location where the specified GHC is or would be installed. 945 | # Doesn't check whether that directory actually exist. Use 946 | # 'ghc_already_installed' for that. 947 | # @STDOUT: ghc location 948 | get_ghc_location() { 949 | [ -z "$1" ] && die "Internal error: no argument given to get_ghc_location" 950 | 951 | myghcver=$1 952 | inst_location=${GHC_LOCATION}/${myghcver} 953 | 954 | printf "%s" "${inst_location}" 955 | 956 | unset myghcver inst_location 957 | } 958 | 959 | # @FUNCTION: download 960 | # @USAGE: 961 | # @DESCRIPTION: 962 | # Downloads the given url as a file into the current directory. 963 | download() { 964 | [ -z "$1" ] && die "Internal error: no argument given to download" 965 | # shellcheck disable=SC2086 966 | edo ${DOWNLOADER} ${DOWNLOADER_OPTS} "$1" 967 | } 968 | 969 | # @FUNCTION: download_to_cache 970 | # @USAGE: 971 | # @DESCRIPTION: 972 | # Downloads the given url as a file into the cache directory 973 | # and makes sure the file is deleted on failed/interrupted download. 974 | download_to_cache() { 975 | [ -z "$1" ] && die "Internal error: no argument given to download_to_cache" 976 | 977 | _dtc_download_url="$1" 978 | _dtc_download_tarball_name=$(basename "${_dtc_download_url}") 979 | 980 | rm_tarball() { 981 | if [ -f "${CACHE_LOCATION}/${_dtc_download_tarball_name}" ] ; then 982 | rm "${CACHE_LOCATION}/${_dtc_download_tarball_name}" 983 | fi 984 | } 985 | 986 | ( 987 | trap 'rm_tarball' 2 988 | edo cd "${CACHE_LOCATION}" 989 | # shellcheck disable=SC2086 990 | edo ${DOWNLOADER} ${DOWNLOADER_OPTS} "${_dtc_download_url}" 991 | trap - 2 992 | ) || { 993 | rm_tarball 994 | die "Failed to download" 995 | } 996 | 997 | unset _dtc_download_tarball_name _dtc_download_url 998 | } 999 | 1000 | # @FUNCTION: download_silent 1001 | # @USAGE: 1002 | # @DESCRIPTION: 1003 | # Downloads the given url as a file into the current directory, silent, unless 1004 | # verbosity is on. 1005 | download_silent() { 1006 | [ -z "$1" ] && die "Internal error: no argument given to download" 1007 | 1008 | if ${VERBOSE} ; then 1009 | # shellcheck disable=SC2086 1010 | edo ${DOWNLOADER} ${DOWNLOADER_OPTS} "$1" 1011 | else 1012 | # shellcheck disable=SC2086 1013 | edo ${DOWNLOADER} ${DOWNLOADER_OPTS} "$1" 1> /dev/null 2> /dev/null 1014 | fi 1015 | } 1016 | 1017 | # @FUNCTION: download_to_stdout 1018 | # @USAGE: 1019 | # @DESCRIPTION: 1020 | # Downloads the given url to stdout. 1021 | download_to_stdout() { 1022 | [ -z "$1" ] && die "Internal error: no argument given to download" 1023 | # shellcheck disable=SC2086 1024 | edo ${DOWNLOADER} ${DOWNLOADER_STDOUT_OPTS} "$1" 2> /dev/null 1025 | } 1026 | 1027 | # @FUNCTION: mktempdir 1028 | # @DESCRIPTION: 1029 | # Makes a temporary directory. 1030 | mktempdir() { 1031 | mktemp_mydistro=$(get_distro_alias "$(get_distro_name)") 1032 | 1033 | if test "${mktemp_mydistro}" = "darwin"; then 1034 | debug_message "mktemp -d -t ghcup.XXXXXXX" 1035 | mktemp -d -t ghcup.XXXXXXX 1036 | else 1037 | debug_message "mktemp -d" 1038 | mktemp -d 1039 | fi 1040 | 1041 | unset mktemp_mydistro 1042 | } 1043 | 1044 | # @FUNCTION: darwin_notarization 1045 | # @USAGE: 1046 | # @DESCRIPTION: 1047 | # https://gitlab.haskell.org/ghc/ghc/issues/17418 1048 | # Can safely be invoked without distro check. 1049 | darwin_notarization() { 1050 | [ -z "$1" ] && die "Internal error: no argument given to darwin_notarization" 1051 | 1052 | if [ "$(get_distro_alias "$(get_distro_name)")" = "darwin" ] ; then 1053 | edo xattr -r -d com.apple.quarantine "$1" 1054 | fi 1055 | } 1056 | 1057 | # @FUNCTION: unpack 1058 | # @USAGE: 1059 | # @DESCRIPTION: 1060 | # Uncompresses and unpacks the given tarball if needed by discovering the 1061 | # file extension. 1062 | unpack() { 1063 | [ -z "$1" ] && die "Internal error: no argument given to unpack" 1064 | 1065 | mydistro=$(get_distro_alias "$(get_distro_name)") 1066 | filename=$1 1067 | file_ext=${filename##*.} 1068 | 1069 | # this is for portability, since not all 1070 | # distros have tar with compression detection 1071 | # capability 1072 | case "${file_ext}" in 1073 | xz) 1074 | if test "${mydistro}" = "darwin"; then 1075 | debug_message "tar xf \"${filename}\"" 1076 | ( tar xf "${filename}" ) || die "unpacking failed!" 1077 | else 1078 | debug_message "xz -cd \"${filename}\" | tar -xf -" 1079 | ( xz -cd "${filename}" | tar xf - ; ) || die "unpacking failed!" 1080 | fi 1081 | ;; 1082 | gz) 1083 | debug_message "gzip -cd \"${filename}\" | tar -xf -" 1084 | ( gzip -cd "${filename}" | tar xf - ; ) || die "unpacking failed!" 1085 | ;; 1086 | bz2) 1087 | debug_message "bzip2 -cd \"${filename}\" | tar -xf -" 1088 | ( bzip2 -cd "${filename}" | tar xf - ; ) || die "unpacking failed!" 1089 | ;; 1090 | tar) 1091 | edo tar xf "${filename}" 1092 | ;; 1093 | *) 1094 | die "Unknown file extension: \"${file_ext}\"" 1095 | esac 1096 | 1097 | unset mydistro filename file_ext 1098 | } 1099 | 1100 | # @FUNCTION: ask_for_confirmation 1101 | # @USAGE: [confirmation-msg] 1102 | # @DESCRIPTION: 1103 | # Asks the user for confirmation and returns 0 for yes, 1 for no. 1104 | # @RETURN: 0 if user confirmed, 1 otherwise 1105 | ask_for_confirmation() { 1106 | confirmation_msg=$1 1107 | 1108 | if [ -n "${confirmation_msg}" ] ; then 1109 | printf "%s\\n(y/n and press Enter)\\n" "${confirmation_msg}" 1110 | else 1111 | printf "Confirm action: (y/n and press Enter)\\n" 1112 | fi 1113 | read -r answer 1114 | 1115 | if [ "${answer}" != "${answer#[Yy]}" ] ;then 1116 | return 0 1117 | else 1118 | return 1 1119 | fi 1120 | 1121 | unset confirmation_msg answer 1122 | } 1123 | 1124 | # @FUNCTION: get_distro_alias 1125 | # @USAGE: 1126 | # @DESCRIPTION: 1127 | # For a given known distro name, return our internal 1128 | # unique distro alias. E.g.: 1129 | # Debian GNU/Linux -> debian 1130 | # STDOUT: our internal distro alias 1131 | get_distro_alias() { 1132 | distro_name=$1 1133 | distro_alias=unknown 1134 | 1135 | case "${distro_name}" in 1136 | "Debian"|"Debian GNU/Linux"|"debian") 1137 | distro_alias=debian 1138 | ;; 1139 | "Ubuntu"|"ubuntu") 1140 | distro_alias=ubuntu 1141 | ;; 1142 | "Exherbo"|"exherbo") 1143 | distro_alias=exherbo 1144 | ;; 1145 | "Fedora"|"fedora") 1146 | distro_alias=fedora 1147 | ;; 1148 | "CentOS Linux"|"CentOS"|"centos"|"Red Hat Enterprise Linux"*) 1149 | distro_alias=centos 1150 | ;; 1151 | "Alpine Linux"|"Alpine"|"alpine") 1152 | distro_alias=alpine 1153 | ;; 1154 | "Linux Mint"|"LinuxMint"|"linuxmint") 1155 | distro_alias=mint 1156 | ;; 1157 | "Amazon Linux AMI"|"amazonlinux") 1158 | distro_alias=amazonlinux 1159 | ;; 1160 | "AIX"|"aix") 1161 | distro_alias=aix 1162 | ;; 1163 | "FreeBSD"|"freebsd") 1164 | distro_alias=freebsd 1165 | ;; 1166 | "Darwin"|"darwin") 1167 | distro_alias=darwin 1168 | ;; 1169 | esac 1170 | 1171 | printf "%s" "${distro_alias}" 1172 | 1173 | unset distro_name distro_alias 1174 | } 1175 | 1176 | # @FUNCTION: posix_realpath 1177 | # @USAGE: 1178 | # @DESCRIPTION: 1179 | # Portably gets the realpath and prints it to stdout. 1180 | # This was initially inspired by 1181 | # https://gist.github.com/tvlooy/cbfbdb111a4ebad8b93e 1182 | # and 1183 | # https://stackoverflow.com/a/246128 1184 | # 1185 | # If the file does not exist, just prints it appended to the current directory. 1186 | # @STDOUT: realpath of the given file 1187 | posix_realpath() { 1188 | [ -z "$1" ] && die "Internal error: no argument given to posix_realpath" 1189 | current_loop=0 1190 | max_loops=50 1191 | mysource=$1 1192 | 1193 | while [ -h "${mysource}" ]; do 1194 | current_loop=$((current_loop+1)) 1195 | mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )" 1196 | mysource="$(readlink "${mysource}")" 1197 | [ "${mysource%${mysource#?}}"x != '/x' ] && mysource="${mydir}/${mysource}" 1198 | 1199 | if [ ${current_loop} -gt ${max_loops} ] ; then 1200 | (>&2 echo "${1}: Too many levels of symbolic links") 1201 | break 1202 | fi 1203 | done 1204 | mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )" 1205 | 1206 | # TODO: better distinguish between "does not exist" and "permission denied" 1207 | if [ -z "${mydir}" ] ; then 1208 | (>&2 echo "${1}: Permission denied") 1209 | else 1210 | echo "${mydir%/}/$(basename "${mysource}")" 1211 | fi 1212 | 1213 | unset current_loop max_loops mysource mydir 1214 | } 1215 | 1216 | 1217 | # @FUNCTION: get_meta_version_file 1218 | # @DESCRIPTION: 1219 | # Downloads the META_VERSION_URL 1220 | # in case it hasn't been downloaded 1221 | # during the execution of this script yet 1222 | # and checks the format version matches 1223 | # the expected one. 1224 | # @STDOUT: file location 1225 | get_meta_version_file() { 1226 | meta_file_name="$(basename "${META_VERSION_URL}")" 1227 | meta_filepath="${CACHE_LOCATION}/${meta_file_name}" 1228 | 1229 | if [ ! -f "${meta_filepath}" ] ; then 1230 | ( 1231 | edo cd "${CACHE_LOCATION}" 1232 | download_silent "${META_VERSION_URL}" 1233 | ) || die "downloading failed" 1234 | fi 1235 | 1236 | check_meta_file_version "${meta_filepath}" "${META_VERSION_FORMAT}" 1237 | 1238 | printf "%s" "${meta_filepath}" 1239 | 1240 | unset meta_file_name meta_filepath 1241 | } 1242 | 1243 | 1244 | # @FUNCTION: get_meta_download_file 1245 | # @DESCRIPTION: 1246 | # Downloads the META_DOWNLOAD_URL 1247 | # in case it hasn't been downloaded 1248 | # during the execution of this script yet 1249 | # and checks the format version matches 1250 | # the expected one. 1251 | # @STDOUT: file location 1252 | get_meta_download_file() { 1253 | meta_file_name="$(basename "${META_DOWNLOAD_URL}")" 1254 | meta_filepath="${CACHE_LOCATION}/${meta_file_name}" 1255 | 1256 | if [ ! -f "${meta_filepath}" ] ; then 1257 | ( 1258 | edo cd "${CACHE_LOCATION}" 1259 | download_silent "${META_DOWNLOAD_URL}" 1260 | ) || die "downloading failed!" 1261 | fi 1262 | 1263 | check_meta_file_version "${meta_filepath}" "${META_DOWNLOAD_FORMAT}" 1264 | 1265 | printf "%s" "${CACHE_LOCATION}/${meta_file_name}" 1266 | 1267 | unset meta_file_name meta_filepath 1268 | } 1269 | 1270 | # @FUNCTION: known_tool_versions 1271 | # @USAGE: 1272 | # @DESCRIPTION: 1273 | # Prints the known tool versions from 1274 | # META_VERSION_URL. 1275 | # @STDOUT: known ghc versions 1276 | known_tool_versions() { 1277 | [ -z "$1" ] && die "Internal error: no argument given to posix_realpath" 1278 | 1279 | mytool=$1 1280 | meta_file="$(get_meta_version_file)" 1281 | [ -z "${meta_file}" ] && die "failed to get meta file" 1282 | 1283 | awk " 1284 | NF { 1285 | if (\$1 == \"${mytool}\") { 1286 | print \$2 1287 | } 1288 | }" "${meta_file}" || die "awk failed!" 1289 | 1290 | unset mytool meta_file 1291 | } 1292 | 1293 | 1294 | # @FUNCTION: known_tool_tags 1295 | # @USAGE: 1296 | # @DESCRIPTION: 1297 | # Prints the known tool tags from 1298 | # META_VERSION_URL. 1299 | # @STDOUT: known tool tags 1300 | known_tool_tags() { 1301 | [ -z "$1" ] && die "Internal error: no argument given to known_tool_tags" 1302 | 1303 | mytool=$1 1304 | meta_file="$(get_meta_version_file)" 1305 | [ -z "${meta_file}" ] && die "failed to get meta file" 1306 | 1307 | awk " 1308 | NF { 1309 | if (\$1 == \"${mytool}\") { 1310 | split(\$3,a,\",\"); 1311 | for (i in a) { 1312 | print a[i] 1313 | } 1314 | } 1315 | }" "${meta_file}" | sort -u || die "awk failed!" 1316 | 1317 | unset mytool meta_file 1318 | } 1319 | 1320 | # @FUNCTION: array_contains 1321 | # @USAGE: 1322 | # @DESCRIPTION: 1323 | # Checks whether the given elements 1324 | # is in the array. 1325 | # @RETURNS: returns 0 if the element is in the array, 1 otherwise 1326 | array_contains() { 1327 | { [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to array_contains" 1328 | 1329 | element=$1 1330 | array=$2 1331 | 1332 | for e in ${array} ; do 1333 | if [ "${e}" = "${element}" ] ; then 1334 | unset e element array 1335 | return 0 1336 | fi 1337 | done 1338 | 1339 | unset e element array 1340 | return 1 1341 | } 1342 | 1343 | # @FUNCTION: show_ghc_installed 1344 | # @DESCRIPTION: 1345 | # Prints the currently selected GHC only as version string. 1346 | # @STDOUT: current GHC version 1347 | show_ghc_installed() { 1348 | current_ghc="${BIN_LOCATION}/ghc" 1349 | real_ghc=$(posix_realpath "${current_ghc}") 1350 | 1351 | if [ -L "${current_ghc}" ] ; then # is symlink 1352 | if [ -f "${real_ghc}" ] ; then # exists (posix_realpath was called) 1353 | real_ghc="$(basename "${real_ghc}" | sed 's#ghc-##')" 1354 | printf "%s" "${real_ghc}" 1355 | else # is a broken symlink 1356 | red_message "broken symlink" 1357 | fi 1358 | fi 1359 | 1360 | unset real_ghc current_ghc 1361 | } 1362 | 1363 | # @FUNCTION: show_cabal_installed 1364 | # @DESCRIPTION: 1365 | # Prints the currently selected cabal only as version string. 1366 | # @STDOUT: current cabal version 1367 | show_cabal_installed() { 1368 | if [ -x "${BIN_LOCATION}/cabal" ] ; then 1369 | "${BIN_LOCATION}/cabal" --numeric-version 1370 | fi 1371 | } 1372 | 1373 | 1374 | # @FUNCTION: get_full_ghc_ver 1375 | # @USAGE: 1376 | # @DESCRIPTION: 1377 | # Get the latest full GHC version . 1378 | get_full_ghc_ver() { 1379 | [ -z "$1" ] && die "Internal error: no argument given to get_full_ghc_ver" 1380 | 1381 | mymajorghcver=$1 1382 | latest_ghc=0 1383 | 1384 | for current_ghc in "${BIN_LOCATION}/ghc-${mymajorghcver}."* ; do 1385 | [ -f "${current_ghc}" ] || break 1386 | real_ghc=$(posix_realpath "${current_ghc}") 1387 | real_ghc="$(basename "${real_ghc}" | sed 's#ghc-##')" 1388 | if [ "$(expr "${real_ghc}" \> "${latest_ghc}")" = 1 ] ; then 1389 | latest_ghc=${real_ghc} 1390 | fi 1391 | done 1392 | 1393 | if [ "${latest_ghc}" != 0 ] ; then 1394 | printf "%s" "${latest_ghc}" 1395 | fi 1396 | 1397 | unset mymajorghcver latest_ghc real_ghc current_ghc 1398 | } 1399 | 1400 | # @FUNCTION: set_ghc_major 1401 | # @USAGE: 1402 | # @DESCRIPTION: 1403 | # Sets a ghc-x.y major version to the latest ghc-x.y.z if any is installed. 1404 | set_ghc_major() { 1405 | [ -z "$1" ] && die "Internal error: no argument given to set_ghc_major" 1406 | 1407 | full_ghc_ver="$(get_full_ghc_ver "${1%.*}")" 1408 | 1409 | if [ -z "${full_ghc_ver}" ] ; then 1410 | die "Could not set GHC major symlink" 1411 | fi 1412 | set_ghc "${full_ghc_ver}" "-${1%.*}" 1413 | 1414 | unset full_ghc_ver 1415 | } 1416 | 1417 | 1418 | 1419 | 1420 | ############################ 1421 | #--[ Subcommand install ]--# 1422 | ############################ 1423 | 1424 | 1425 | # @FUNCTION: install_ghc 1426 | # @USAGE: [os-overwrite] 1427 | # @DESCRIPTION: 1428 | # Installs the given ghc version with a lot of side effects. 1429 | install_ghc() { 1430 | [ -z "$1" ] && die "Internal error: no argument given to install_ghc" 1431 | 1432 | myghcver=$1 1433 | inst_location=$(get_ghc_location "$1") 1434 | [ -z "${inst_location}" ] && die "failed to get install location" 1435 | download_url=$(get_download_url "ghc" "${myghcver}" "$2") 1436 | if [ -z "${download_url}" ] ; then 1437 | die "Could not find an appropriate download for the requested GHC-${myghcver} on your system! Please report a bug at ${BUG_URL}" 1438 | fi 1439 | download_tarball_name=$(basename "${download_url}") 1440 | first_install=true 1441 | 1442 | 1443 | status_message "Installing GHC-${myghcver} for $(if [ -n "$2" ] ; then echo "$2" ; else get_distro_name ; fi) on architecture $(get_arch)" 1444 | 1445 | if ghc_already_installed "${myghcver}" ; then 1446 | if ${FORCE} ; then 1447 | echo "GHC already installed in ${inst_location}, overwriting!" 1448 | else 1449 | warning_message "GHC already installed in ${inst_location}, use --force to overwrite" 1450 | exit 0 1451 | fi 1452 | first_install=false 1453 | fi 1454 | 1455 | tmp_dir=$(mktempdir) 1456 | { [ -z "${tmp_dir}" ] || ! [ -d "${tmp_dir}" ] ; } && die "Failed to create temporary directory" 1457 | ( 1458 | if ${CACHING} ; then 1459 | if [ ! -f "${CACHE_LOCATION}/${download_tarball_name}" ] ; then 1460 | download_to_cache "${download_url}" 1461 | fi 1462 | edo cd "${tmp_dir}" 1463 | unpack "${CACHE_LOCATION}/${download_tarball_name}" 1464 | else 1465 | edo cd "${tmp_dir}" 1466 | download "${download_url}" 1467 | unpack "${download_tarball_name}" 1468 | fi 1469 | 1470 | edo cd "./ghc-${myghcver}" 1471 | 1472 | darwin_notarization . 1473 | 1474 | debug_message "Installing GHC into ${inst_location}" 1475 | 1476 | edo ./configure --prefix="${inst_location}" 1477 | emake install 1478 | 1479 | # clean up 1480 | edo cd .. 1481 | [ -f "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}" 1482 | [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}" 1483 | ) || { 1484 | [ -f "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}" 1485 | [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}" 1486 | 1487 | if ${first_install} ; then 1488 | [ -e "${inst_location}" ] && rm -r "${inst_location}" 1489 | else 1490 | warning_message "GHC force installation failed. The install might be broken." 1491 | warning_message "Consider running: ghcup rm ${myghcver}" 1492 | fi 1493 | 1494 | die "Failed to install, consider updating this script via: ${SCRIPT} upgrade" 1495 | } 1496 | 1497 | for f in "${inst_location}"/bin/*-"${myghcver}" ; do 1498 | [ -f "${f}" ] || die "Something went wrong, ${f} does not exist!" 1499 | fn=$(basename "${f}") 1500 | # shellcheck disable=SC2046 1501 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}/bin/${fn}" "${BIN_LOCATION}/${fn}" 1502 | unset fn 1503 | done 1504 | # shellcheck disable=SC2046 1505 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/runhaskell "${BIN_LOCATION}/runhaskell-${myghcver}" 1506 | # shellcheck disable=SC2046 1507 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/hsc2hs "${BIN_LOCATION}/hsc2hs-${myghcver}" 1508 | # shellcheck disable=SC2046 1509 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/hp2ps "${BIN_LOCATION}/hp2ps-${myghcver}" 1510 | # shellcheck disable=SC2046 1511 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/hpc "${BIN_LOCATION}/hpc-${myghcver}" 1512 | if [ -f "${inst_location}/bin/haddock" ] ; then 1513 | # shellcheck disable=SC2046 1514 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/haddock "${BIN_LOCATION}/haddock-${myghcver}" 1515 | fi 1516 | 1517 | status_message "Done installing, run \"ghci-${myghcver}\" or set up your current GHC via: ${SCRIPT} set ${myghcver}" 1518 | 1519 | unset inst_location f download_url download_tarball_name first_install tmp_dir 1520 | 1521 | set_ghc_major "${myghcver}" 1522 | 1523 | unset myghcver 1524 | } 1525 | 1526 | 1527 | 1528 | ######################## 1529 | #--[ Subcommand set ]--# 1530 | ######################## 1531 | 1532 | 1533 | # @FUNCTION: set_ghc 1534 | # @USAGE: [target-suffix] 1535 | # @DESCRIPTION: 1536 | # Sets the current ghc version by creating symlinks. 1537 | set_ghc() { 1538 | [ -z "$1" ] && die "Internal error: no argument given to set_ghc" 1539 | 1540 | myghcver=$1 1541 | target_suffix=$2 1542 | inst_location=$(get_ghc_location "$1") 1543 | [ -z "${inst_location}" ] && die "failed to get install location" 1544 | 1545 | [ -e "${inst_location}" ] || die "GHC ${myghcver} not installed yet, use: ${SCRIPT} install ${myghcver}" 1546 | 1547 | status_message "Setting GHC${target_suffix} to ${myghcver}" 1548 | 1549 | for f in "${inst_location}"/bin/*-"${myghcver}" ; do 1550 | [ -f "${f}" ] || die "Something went wrong, ${f} does not exist!" 1551 | source_fn=$(basename "${f}") 1552 | target_fn="$(echo "${source_fn}" | sed "s#-${myghcver}##")${target_suffix}" 1553 | # shellcheck disable=SC2046 1554 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}/bin/${source_fn}" "${BIN_LOCATION}/${target_fn}" 1555 | unset source_fn target_fn 1556 | done 1557 | # shellcheck disable=SC2046 1558 | edo ln $(optionv "-v") -sf "runghc${target_suffix}" "${BIN_LOCATION}/runhaskell${target_suffix}" 1559 | # shellcheck disable=SC2046 1560 | edo ln $(optionv "-v") -sf "hsc2hs-${myghcver}" "${BIN_LOCATION}/hsc2hs${target_suffix}" 1561 | # shellcheck disable=SC2046 1562 | edo ln $(optionv "-v") -sf "hp2ps-${myghcver}" "${BIN_LOCATION}/hp2ps${target_suffix}" 1563 | # shellcheck disable=SC2046 1564 | edo ln $(optionv "-v") -sf "hpc-${myghcver}" "${BIN_LOCATION}/hpc${target_suffix}" 1565 | # not all bindists install haddock... 1566 | if [ -f "${inst_location}/bin/haddock" ] ; then 1567 | # shellcheck disable=SC2046 1568 | edo ln $(optionv "-v") -sf "haddock-ghc${target_suffix}" "${BIN_LOCATION}/haddock${target_suffix}" 1569 | fi 1570 | if [ -z "${target_suffix}" ] && [ -d "${inst_location}/share" ] ; then 1571 | # Make sure we don't link "${BIN_LOCATION}/../share/share". 1572 | # POSIX doesn't allow '-T' for 'ln'. 1573 | if [ -e "${BIN_LOCATION}/../share" ] ; then 1574 | edo rm "${BIN_LOCATION}/../share" 1575 | fi 1576 | # shellcheck disable=SC2046 1577 | edo ln $(optionv "-v") -sf ghc/"${myghcver}"/share "${BIN_LOCATION}/../share" 1578 | fi 1579 | 1580 | status_message "Done" 1581 | 1582 | unset myghcver inst_location f target_suffix 1583 | } 1584 | 1585 | 1586 | 1587 | 1588 | ############################ 1589 | #--[ Subcommand upgrade ]--# 1590 | ############################ 1591 | 1592 | 1593 | # @FUNCTION: upgrade 1594 | # @USAGE: 1595 | # @DESCRIPTION: 1596 | # Downloads the latest version of this script and places it into 1597 | # the given directory. 1598 | upgrade() { 1599 | target_location=$1 1600 | 1601 | [ -e "${target_location}" ] || die "Destination \"${target_location}\" does not exist, cannot update script" 1602 | 1603 | status_message "Updating ${SCRIPT}" 1604 | 1605 | ( 1606 | _plat="$(uname -s)" 1607 | _arch=$(uname -m) 1608 | 1609 | case "${_plat}" in 1610 | "linux"|"Linux") 1611 | case "${_arch}" in 1612 | x86_64|amd64) 1613 | _url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-linux-ghcup-0.1.4 1614 | ;; 1615 | i*86) 1616 | _url=https://downloads.haskell.org/~ghcup/0.1.4/i386-linux-ghcup-0.1.4 1617 | ;; 1618 | *) die "Unknown architecture: ${_arch}" 1619 | ;; 1620 | esac 1621 | ;; 1622 | "FreeBSD"|"freebsd") 1623 | case "${_arch}" in 1624 | x86_64|amd64) 1625 | ;; 1626 | i*86) 1627 | die "i386 currently not supported!" 1628 | ;; 1629 | *) die "Unknown architecture: ${_arch}" 1630 | ;; 1631 | esac 1632 | _url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-portbld-freebsd-ghcup-0.1.4 1633 | ;; 1634 | "Darwin"|"darwin") 1635 | case "${_arch}" in 1636 | x86_64|amd64) 1637 | ;; 1638 | i*86) 1639 | die "i386 currently not supported!" 1640 | ;; 1641 | *) die "Unknown architecture: ${_arch}" 1642 | ;; 1643 | esac 1644 | _url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-apple-darwin-ghcup-0.1.4 ;; 1645 | *) die "Unknown platform: ${_plat}" 1646 | ;; 1647 | esac 1648 | 1649 | 1650 | edo cd "$(mktempdir)" 1651 | download_to_stdout "${_url}" > ghcup 1652 | edo chmod +x ghcup 1653 | edo mv -f ghcup "${target_location}"/ghcup 1654 | 1655 | unset _plat _arch _url 1656 | 1657 | ) || die "failed to install" 1658 | 1659 | status_message "Done" 1660 | 1661 | unset target_location 1662 | } 1663 | 1664 | 1665 | 1666 | 1667 | ####################### 1668 | #--[ Subcommand rm ]--# 1669 | ####################### 1670 | 1671 | 1672 | # @FUNCTION: rm_ghc 1673 | # @USAGE: 1674 | # @DESCRIPTION: 1675 | # Removes the given GHC version installed by ghcup. 1676 | rm_ghc() { 1677 | [ -z "$1" ] && die "Internal error: no argument given to rm_ghc" 1678 | 1679 | myghcver=$1 1680 | inst_location=$(get_ghc_location "${myghcver}") 1681 | 1682 | [ -z "${myghcver}" ] && die "We are paranoid, ghcver not set" 1683 | 1684 | if ghc_already_installed "${myghcver}" ; then 1685 | [ -z "${inst_location}" ] && die "internal error: inst_location empty!" 1686 | 1687 | if ! ${FORCE} ; then 1688 | if ! ask_for_confirmation "Really removing ${myghcver}? This will also recursively remove the following directory (please double-check): \"${inst_location}\"" ; then 1689 | warning_message "Not removing GHC..." 1690 | return 0 1691 | fi 1692 | fi 1693 | 1694 | for f in "${BIN_LOCATION}"/*-"${myghcver}" ; do 1695 | # https://tanguy.ortolo.eu/blog/article113/test-symlink 1696 | [ ! -e "${f}" ] && [ ! -h "${f}" ] && { 1697 | warning_message "No existing symlinks for ${myghcver} in ${BIN_LOCATION}, skipping" 1698 | break 1699 | } 1700 | edo rm "${f}" 1701 | done 1702 | 1703 | edo rm -r "${inst_location}" 1704 | 1705 | status_message "Successfully removed GHC ${myghcver}." 1706 | 1707 | # Only run set_ghc_major if there is at least one 8.6.x version left for 8.6. 1708 | if [ -n "$(get_full_ghc_ver "${myghcver%.*}")" ] ; then 1709 | set_ghc_major "${myghcver}" 1710 | fi 1711 | 1712 | if [ -h "${BIN_LOCATION}/ghc-${myghcver%.*}" ] && [ ! -e "${BIN_LOCATION}/ghc-${myghcver%.*}" ] ; then 1713 | # TODO: known_tools is not very robust, but we want to avoid accidentially deleting 1714 | # unrelated things (even if those are dangling symlinks) 1715 | known_tools="ghc ghci ghc-pkg haddock haddock-ghc runghc runhaskell hp2ps hpc hsc2hs" 1716 | # remove dangling symlinks for ghc, ghci, ... 1717 | for t in ${known_tools} ; do 1718 | if [ -h "${BIN_LOCATION}/${t}-${myghcver%.*}" ] && [ ! -e "${BIN_LOCATION}/${t}-${myghcver%.*}" ] ; then 1719 | edo rm "${BIN_LOCATION}/${t}-${myghcver%.*}" 1720 | fi 1721 | done 1722 | unset t known_tools 1723 | fi 1724 | 1725 | if [ -h "${BIN_LOCATION}/ghc" ] && [ ! -e "${BIN_LOCATION}/ghc" ] ; then 1726 | warning_message "Currently active GHC is a dangling symlink, removing..." 1727 | 1728 | # TODO: known_tools is not very robust, but we want to avoid accidentially deleting 1729 | # unrelated things (even if those are dangling symlinks) 1730 | known_tools="ghc ghci ghc-pkg haddock haddock-ghc runghc runhaskell hp2ps hpc hsc2hs" 1731 | # remove dangling symlinks for ghc, ghci, ... 1732 | for t in ${known_tools} ; do 1733 | if [ -h "${BIN_LOCATION}/${t}" ] && [ ! -e "${BIN_LOCATION}/${t}" ] ; then 1734 | edo rm "${BIN_LOCATION}/${t}" 1735 | fi 1736 | done 1737 | unset t known_tools 1738 | # remove dangling symlink to share directory 1739 | if [ -h "${BIN_LOCATION}/../share" ] && [ ! -e "${BIN_LOCATION}/../share" ] ; then 1740 | edo rm "${BIN_LOCATION}/../share" 1741 | fi 1742 | 1743 | warning_message "Done." 1744 | warning_message "You may now want to set currently active GHC to a different version via:" 1745 | warning_message " ghcup set " 1746 | fi 1747 | else 1748 | warning_message "${myghcver} doesn't appear to be installed, skipping" 1749 | fi 1750 | 1751 | unset myghcver inst_location f 1752 | } 1753 | 1754 | ############################ 1755 | #--[ Subcommand install ]--# 1756 | ############################ 1757 | 1758 | 1759 | # @FUNCTION: install_cabal 1760 | # @USAGE: [os-overwrite] 1761 | # @DESCRIPTION: 1762 | # Installs the given cabal version. 1763 | install_cabal() { 1764 | [ -z "$1" ] && die "Internal error: no argument given to install_cabal" 1765 | 1766 | mycabalver=$1 1767 | myarch=$(get_arch) 1768 | [ -z "${myarch}" ] && die "failed to get architecture" 1769 | inst_location=$BIN_LOCATION 1770 | download_url=$(get_download_url "cabal-install" "${mycabalver}" "$2") 1771 | download_tarball_name=$(basename "${download_url}") 1772 | 1773 | if [ -z "${download_url}" ] ; then 1774 | die "Could not find an appropriate download for the requested cabal-install-${mycabalver} on your system! Please report a bug at ${BUG_URL}" 1775 | fi 1776 | 1777 | status_message "Installing cabal-install-${mycabalver} for $(if [ -n "$2" ] ; then echo "$2" ; else get_distro_name ; fi) on architecture $(get_arch)" 1778 | 1779 | edo mkdir -p "${inst_location}" 1780 | 1781 | tmp_dir=$(mktempdir) 1782 | { [ -z "${tmp_dir}" ] || ! [ -d "${tmp_dir}" ] ; } && die "Failed to create temporary directory" 1783 | ( 1784 | if ${CACHING} ; then 1785 | if [ ! -f "${CACHE_LOCATION}/${download_tarball_name}" ] ; then 1786 | download_to_cache "${download_url}" 1787 | fi 1788 | edo cd "${tmp_dir}" 1789 | unpack "${CACHE_LOCATION}/${download_tarball_name}" 1790 | else 1791 | edo cd "${tmp_dir}" 1792 | download "${download_url}" 1793 | unpack "${download_tarball_name}" 1794 | fi 1795 | 1796 | darwin_notarization . 1797 | 1798 | edo mv -f cabal "${inst_location}"/cabal 1799 | if [ -f "${tmp_dir}/${download_tarball_name}" ] ; then 1800 | rm "${tmp_dir}/${download_tarball_name}" 1801 | fi 1802 | ) || die "Failed to install cabal-install" 1803 | 1804 | status_message "Successfully installed cabal-install into" 1805 | status_message " ${BIN_LOCATION}" 1806 | status_message "" 1807 | 1808 | unset mycabalver myarch inst_location download_url download_tarball_name tmp_dir 1809 | } 1810 | 1811 | # @FUNCTION: compile_ghc 1812 | # @USAGE: [build.mk] 1813 | # @DESCRIPTION: 1814 | # Compile and installs the given GHC version with the 1815 | # specified GHC bootstrap version. 1816 | # Can additionally take a custom file that will be used 1817 | # as build configuration. 1818 | compile_ghc() { 1819 | { [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to compile_ghc" 1820 | 1821 | myghcver=$1 1822 | bootstrap_ghc=$2 1823 | inst_location=$(get_ghc_location "$1") 1824 | [ -z "${inst_location}" ] && die "failed to get install location" 1825 | download_url="https://downloads.haskell.org/~ghc/${myghcver}/ghc-${myghcver}-src.tar.xz" 1826 | download_tarball_name=$(basename "${download_url}") 1827 | 1828 | if [ -n "$3" ] ; then 1829 | case "$3" in 1830 | /*) build_config=$3 ;; 1831 | *) build_config="$(pwd)/$3" ;; 1832 | esac 1833 | [ -f "${build_config}" ] || die "specified build config \"${build_config}\" file does not exist!" 1834 | fi 1835 | 1836 | if ghc_already_installed "${myghcver}" ; then 1837 | if ${FORCE} ; then 1838 | echo "GHC already installed in ${inst_location}, overwriting!" 1839 | else 1840 | die "GHC already installed in ${inst_location}, use --force to overwrite" 1841 | fi 1842 | fi 1843 | 1844 | status_message "Compiling GHC for version ${myghcver} from source" 1845 | tmp_dir=$(mktempdir) 1846 | { [ -z "${tmp_dir}" ] || ! [ -d "${tmp_dir}" ] ; } && die "Failed to create temporary directory" 1847 | ( 1848 | if ${CACHING} ; then 1849 | if [ ! -f "${CACHE_LOCATION}/${download_tarball_name}" ] ; then 1850 | download_to_cache "${download_url}" 1851 | fi 1852 | edo cd "${tmp_dir}" 1853 | unpack "${CACHE_LOCATION}/${download_tarball_name}" 1854 | else 1855 | edo cd "${tmp_dir}" 1856 | download "${download_url}" 1857 | unpack "${download_tarball_name}" 1858 | fi 1859 | 1860 | edo cd "./ghc-${myghcver}" 1861 | 1862 | darwin_notarization . 1863 | 1864 | if [ -n "${build_config}" ] ; then 1865 | edo cat "${build_config}" > mk/build.mk 1866 | else 1867 | cat <<-EOF > mk/build.mk || die 1868 | V=0 1869 | BUILD_MAN = NO 1870 | BUILD_SPHINX_HTML = NO 1871 | BUILD_SPHINX_PDF = NO 1872 | HADDOCK_DOCS = YES 1873 | GhcWithLlvmCodeGen = YES 1874 | EOF 1875 | fi 1876 | 1877 | 1878 | edo ./boot 1879 | if [ "$(echo "${myghcver}" | awk -F. '{printf"%d%03d",$1,$2;}')" -ge 8008 ]; then 1880 | GHC=$(command -v "${bootstrap_ghc}") edo ./configure --prefix="${inst_location}" 1881 | else 1882 | edo ./configure --prefix="${inst_location}" --with-ghc="${bootstrap_ghc}" 1883 | fi 1884 | emake -j${JOBS} 1885 | emake install 1886 | 1887 | # clean up 1888 | edo cd .. 1889 | [ -f "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}" 1890 | [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}" 1891 | ) || { 1892 | [ -f "${tmp_dir}/${download_tarball_name}" ] && rm "${tmp_dir}/${download_tarball_name}" 1893 | [ -e "${tmp_dir}/ghc-${myghcver}" ] && rm -r "${tmp_dir}/ghc-${myghcver}" 1894 | die "Failed to install, consider updating this script via: 1895 | ${SCRIPT} upgrade 1896 | Also check https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Linux for build requirements and follow the instructions." 1897 | } 1898 | 1899 | for f in "${inst_location}"/bin/*-"${myghcver}" ; do 1900 | [ -f "${f}" ] || die "Something went wrong, ${f} does not exist!" 1901 | fn=$(basename "${f}") 1902 | # shellcheck disable=SC2046 1903 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}/bin/${fn}" "${BIN_LOCATION}/${fn}" 1904 | unset fn 1905 | done 1906 | # shellcheck disable=SC2046 1907 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/runhaskell "${BIN_LOCATION}/runhaskell-${myghcver}" 1908 | # shellcheck disable=SC2046 1909 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/hsc2hs "${BIN_LOCATION}/hsc2hs-${myghcver}" 1910 | # shellcheck disable=SC2046 1911 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/hp2ps "${BIN_LOCATION}/hp2ps-${myghcver}" 1912 | # shellcheck disable=SC2046 1913 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/hpc "${BIN_LOCATION}/hpc-${myghcver}" 1914 | if [ -f "${inst_location}/bin/haddock" ] ; then 1915 | # shellcheck disable=SC2046 1916 | edo ln $(optionv "-v") -sf ../ghc/"${myghcver}"/bin/haddock "${BIN_LOCATION}/haddock-${myghcver}" 1917 | fi 1918 | 1919 | status_message "Done installing, run \"ghci-${myghcver}\" or set up your current GHC via: ${SCRIPT} set ${myghcver}" 1920 | 1921 | unset bootstrap_ghc inst_location f download_url download_tarball_name tmp_dir 1922 | 1923 | set_ghc_major "${myghcver}" 1924 | 1925 | unset myghcver 1926 | } 1927 | 1928 | 1929 | ############################### 1930 | #--[ Subcommand debug-info ]--# 1931 | ############################### 1932 | 1933 | 1934 | # @FUNCTION: print_debug_info 1935 | # @DESCRIPTION: 1936 | # Print debug info (e.g. detected system/distro). 1937 | print_debug_info() { 1938 | echo "Script version: ${VERSION}" 1939 | echo 1940 | echo "Script variables:" 1941 | echo " GHC install location: ${GHC_LOCATION}" 1942 | echo " Binary install location: ${BIN_LOCATION}" 1943 | echo " Tarball cache location: ${CACHE_LOCATION}" 1944 | echo " Downloader: ${DOWNLOADER} ${DOWNLOADER_OPTS} " 1945 | echo " Script update url: ${SCRIPT_UPDATE_URL}" 1946 | echo " GHC download baseurl: ${GHC_DOWNLOAD_BASEURL}" 1947 | echo " Meta download url ${META_DOWNLOAD_URL}" 1948 | echo " Meta download format ${META_DOWNLOAD_FORMAT}" 1949 | echo " Meta version url ${META_VERSION_URL}" 1950 | echo " Meta version format ${META_VERSION_FORMAT}" 1951 | echo 1952 | echo "Detected system information:" 1953 | echo " Architecture: $(get_arch)" 1954 | echo " Distribution: $(get_distro_name)" 1955 | echo " Distro alias: $(get_distro_alias "$(get_distro_name)")" 1956 | echo " Distro version: $(get_distro_ver)" 1957 | } 1958 | 1959 | 1960 | ######################### 1961 | #--[ Subcommand list ]--# 1962 | ######################### 1963 | 1964 | 1965 | # @FUNCTION: list 1966 | # @USAGE: 1967 | # @DESCRIPTION: 1968 | # List available tools and their versions from upstream. 1969 | list() { 1970 | mytool=$1 1971 | raw_format=$2 1972 | criteria=$3 1973 | 1974 | meta_file="$(get_meta_version_file)" 1975 | [ -z "${meta_file}" ] && die "failed to get meta file" 1976 | 1977 | if ! ${raw_format} ; then 1978 | printf "\\033[1;32m%s\\033[0m\\n" "Available versions:" 1979 | fi 1980 | 1981 | lines=$( 1982 | if [ "${mytool}" = "all" ] ; then 1983 | awk " 1984 | NF { 1985 | if (\$1 != \"#\") { 1986 | print \$1 \"\\t\" \$2 \"\\t\" \$3 1987 | } 1988 | }" "${meta_file}" || die "awk failed!" 1989 | else 1990 | awk " 1991 | NF { 1992 | if (\$1 == \"${mytool}\") { 1993 | print \$1 \"\\t\" \$2 \"\\t\" \$3 1994 | } 1995 | }" "${meta_file}" || die "awk failed!" 1996 | fi 1997 | ) 1998 | 1999 | _print_me() { 2000 | if ${raw_format} ; then 2001 | printf "%s\\n" "$1" 2002 | else 2003 | if [ "$2" = "available" ] ; then 2004 | printf "\\033[0;32m\342\234\224\\033[0m %s\\n" "$1" 2005 | elif [ "$2" = "set" ] ; then 2006 | printf "\\033[0;32m\342\234\224 \\033[0;34m%s\\033[0m\\n" "$1" 2007 | elif [ "$2" = "unavailable" ] ; then 2008 | printf "\\033[0;31m\342\234\227\\033[0m %s\\n" "$1" 2009 | fi 2010 | fi 2011 | } 2012 | 2013 | if [ -z "${lines}" ] ; then 2014 | (>&2 echo "Nothing found for tool ${mytool}") 2015 | return 2016 | fi 2017 | 2018 | 2019 | echo "$lines" | while read -r l; do 2020 | tool=$(echo "${l}" | cut -f1) 2021 | version=$(echo "${l}" | cut -f2) 2022 | 2023 | if [ "${criteria}" = "set" ] ; then 2024 | if [ "${tool}" = "ghc" ] && [ "${version}" = "$(show_ghc_installed)" ] ; then 2025 | _print_me "${l}" "set" 2026 | fi 2027 | 2028 | if [ "${tool}" = "cabal-install" ] && [ "${version}" = "$(show_cabal_installed)" ] ; then 2029 | _print_me "${l}" "set" 2030 | fi 2031 | else 2032 | if tool_already_installed "${tool}" "${version}" ; then 2033 | if [ "${tool}" = "ghc" ] && [ "${version}" = "$(show_ghc_installed)" ] ; then 2034 | _print_me "${l}" "set" 2035 | elif [ "${tool}" = "cabal-install" ] && [ "${version}" = "$(show_cabal_installed)" ] ; then 2036 | _print_me "${l}" "set" 2037 | else 2038 | _print_me "${l}" "available" 2039 | fi 2040 | else 2041 | if [ "${criteria}" != "installed" ] ; then 2042 | _print_me "${l}" "unavailable" 2043 | fi 2044 | fi 2045 | fi 2046 | done 2047 | 2048 | unset mytool meta_file l lines tool version raw_format installed_only criteria 2049 | } 2050 | 2051 | 2052 | ############################## 2053 | #--[ Subcommand changelog ]--# 2054 | ############################## 2055 | 2056 | 2057 | # @FUNCTION: changelog_url 2058 | # @USAGE: 2059 | # @DESCRIPTION: 2060 | # Print the changelog url for the given GHC version to stdout. 2061 | # @STDOUT: the changelog url 2062 | changelog_url() { 2063 | [ -z "$1" ] && die "Internal error: no argument given to changelog" 2064 | 2065 | printf "https://downloads.haskell.org/~ghc/%s/docs/html/users_guide/%s-notes.html" "$1" "$1" 2066 | } 2067 | 2068 | 2069 | # @FUNCTION: changelog 2070 | # @USAGE: 2071 | # @DESCRIPTION: 2072 | # Opens the changelog for the given ghc version via xdg-open. 2073 | changelog() { 2074 | [ -z "$1" ] && die "Internal error: no argument given to changelog" 2075 | 2076 | url=$(changelog_url "$1") 2077 | 2078 | xdg-open "${url}" || die "failed to xdg-open the following url: ${url}" 2079 | 2080 | unset url 2081 | } 2082 | 2083 | 2084 | ###################################### 2085 | #--[ Subcommand print-system-reqs ]--# 2086 | ###################################### 2087 | 2088 | 2089 | # @FUNCTION: system_reqs_url 2090 | # @USAGE: 2091 | # @DESCRIPTION: 2092 | # Mapping of distro-alias to system requirements URL. 2093 | system_reqs_url() { 2094 | [ -z "$1" ] && die "Internal error: no argument given to system_reqs_url" 2095 | 2096 | case "$1" in 2097 | "alpine") 2098 | printf "%s/.requirements/ghc/alpine" "${BASE_DOWNLOAD_URL}" 2099 | ;; 2100 | "debian"|"ubuntu") 2101 | printf "%s/.requirements/ghc/ubuntu" "${BASE_DOWNLOAD_URL}" 2102 | ;; 2103 | "darwin") 2104 | printf "%s/.requirements/ghc/darwin" "${BASE_DOWNLOAD_URL}" 2105 | ;; 2106 | *) 2107 | printf "%s/.requirements/ghc/default" "${BASE_DOWNLOAD_URL}" 2108 | ;; 2109 | esac 2110 | } 2111 | 2112 | 2113 | # @FUNCTION: print_system_reqs 2114 | # @DESCRIPTION: 2115 | # Print the system requirements (approximation). 2116 | print_system_reqs() { 2117 | mydistro=$(get_distro_alias "$(get_distro_name)") 2118 | reqs_url=$(system_reqs_url "${mydistro}") 2119 | 2120 | download_to_stdout "${reqs_url}" 2121 | 2122 | unset mydistro reqs_url 2123 | } 2124 | 2125 | ####################### 2126 | #--[ Sanity checks ]--# 2127 | ####################### 2128 | 2129 | 2130 | if [ -z "${GHCUP_INSTALL_BASE_PREFIX}" ] ; then 2131 | die "GHCUP_INSTALL_BASE_PREFIX empty, cannot operate" 2132 | fi 2133 | 2134 | if [ ! -d "${GHCUP_INSTALL_BASE_PREFIX}" ] ; then 2135 | die "${GHCUP_INSTALL_BASE_PREFIX} does not exist" 2136 | fi 2137 | 2138 | 2139 | 2140 | >&2 warning_message "ghcup has been rewritten in haskell. Please upgrade again via 'ghcup upgrade'" 2141 | 2142 | 2143 | 2144 | 2145 | ############################################## 2146 | #--[ Command line parsing and entry point ]--# 2147 | ############################################## 2148 | 2149 | [ $# -lt 1 ] && usage 2150 | 2151 | while [ $# -gt 0 ] ; do 2152 | case $1 in 2153 | -v|--verbose) 2154 | VERBOSE=true 2155 | shift 1 2156 | if [ $# -lt 1 ] ; then 2157 | usage 2158 | fi 2159 | ;; 2160 | -V|--version) 2161 | printf "%s\\n" "${VERSION}" 2162 | exit 0;; 2163 | --list-commands) 2164 | echo "changelog 2165 | compile 2166 | debug-info 2167 | install 2168 | install-cabal 2169 | list 2170 | print-system-reqs 2171 | rm 2172 | set 2173 | upgrade" 2174 | exit 0;; 2175 | -h|--help) 2176 | usage;; 2177 | -w|--wget) 2178 | DOWNLOADER="wget" 2179 | DOWNLOADER_OPTS="" 2180 | DOWNLOADER_STDOUT_OPTS="-qO-" 2181 | shift 1 2182 | if [ $# -lt 1 ] ; then 2183 | usage 2184 | fi 2185 | ;; 2186 | -c|--cache) 2187 | CACHING=true 2188 | shift 1 2189 | if [ $# -lt 1 ] ; then 2190 | usage 2191 | fi 2192 | ;; 2193 | -o|--os) MY_OS=$2 2194 | shift 2;; 2195 | 2196 | *) ## startup tasks ## 2197 | 2198 | edo mkdir -p "${INSTALL_BASE}" 2199 | edo mkdir -p "${BIN_LOCATION}" 2200 | edo mkdir -p "${CACHE_LOCATION}" 2201 | 2202 | # clean up old meta files 2203 | if [ -f "${CACHE_LOCATION}/$(basename "${META_VERSION_URL}")" ] ; then 2204 | edo rm "${CACHE_LOCATION}/$(basename "${META_VERSION_URL}")" 2205 | fi 2206 | if [ -f "${CACHE_LOCATION}/$(basename "${META_DOWNLOAD_URL}")" ] ; then 2207 | edo rm "${CACHE_LOCATION}/$(basename "${META_DOWNLOAD_URL}")" 2208 | fi 2209 | 2210 | # check for available commands 2211 | missing_commands="$(check_required_commands ${DOWNLOADER})" 2212 | if [ -n "${missing_commands}" ] ; then 2213 | die "Following commands are required, but missing, please install: ${missing_commands}" 2214 | fi 2215 | unset missing_commands 2216 | case $1 in 2217 | install) 2218 | shift 1 2219 | while [ $# -gt 0 ] ; do 2220 | case $1 in 2221 | -h|--help) install_usage;; 2222 | -f|--force) FORCE=true 2223 | shift 1;; 2224 | *) GHC_VER=$1 2225 | break;; 2226 | esac 2227 | done 2228 | if [ -z "${GHC_VER}" ] ; then 2229 | _tool_ver="$(get_tool_ver_from_tag "ghc" "recommended")" 2230 | if [ -z "${_tool_ver}" ] ; then 2231 | die "Could not find a recommended GHC version, please report a bug at ${BUG_URL}!" 2232 | fi 2233 | install_ghc "${_tool_ver}" "${MY_OS}" 2234 | else 2235 | # could be a version or a tag, let's check 2236 | if array_contains "${GHC_VER}" "$(known_tool_versions "ghc")" ; then 2237 | install_ghc "${GHC_VER}" "${MY_OS}" 2238 | elif array_contains "${GHC_VER}" "$(known_tool_tags "ghc")" ; then 2239 | install_ghc "$(get_tool_ver_from_tag "ghc" "${GHC_VER}")" "${MY_OS}" 2240 | else 2241 | die "\"${GHC_VER}\" is not a known version or tag!" 2242 | fi 2243 | fi 2244 | break;; 2245 | set) 2246 | shift 1 2247 | while [ $# -gt 0 ] ; do 2248 | case $1 in 2249 | -h|--help) set_usage;; 2250 | *) GHC_VER=$1 2251 | break;; 2252 | esac 2253 | done 2254 | 2255 | if [ -z "${GHC_VER}" ] ; then 2256 | _tool_ver="$(get_tool_ver_from_tag "ghc" "recommended")" 2257 | if [ -z "${_tool_ver}" ] ; then 2258 | die "Could not find a recommended GHC version, please report a bug at ${BUG_URL}!" 2259 | fi 2260 | set_ghc "${_tool_ver}" 2261 | else 2262 | # could be a version or a tag, let's check 2263 | if array_contains "${GHC_VER}" "$(known_tool_versions "ghc")" ; then 2264 | set_ghc "${GHC_VER}" 2265 | elif array_contains "${GHC_VER}" "$(known_tool_tags "ghc")" ; then 2266 | set_ghc "$(get_tool_ver_from_tag "ghc" "${GHC_VER}")" 2267 | else 2268 | die "\"${GHC_VER}\" is not a known version or tag!" 2269 | fi 2270 | fi 2271 | 2272 | break;; 2273 | upgrade) 2274 | IN_PLACE=false 2275 | shift 1 2276 | while [ $# -gt 0 ] ; do 2277 | case $1 in 2278 | -h|--help) upgrade_usage;; 2279 | -i|--inplace) IN_PLACE=true 2280 | shift 1 ;; 2281 | *) TARGET_LOCATION=$1 2282 | break;; 2283 | esac 2284 | done 2285 | if ${IN_PLACE} ; then 2286 | upgrade "$(dirname "$(posix_realpath "${SOURCE}")")" 2287 | elif [ -n "${TARGET_LOCATION}" ] ; then 2288 | upgrade "${TARGET_LOCATION}" 2289 | else 2290 | upgrade "${BIN_LOCATION}" 2291 | fi 2292 | break;; 2293 | rm) 2294 | shift 1 2295 | while [ $# -gt 0 ] ; do 2296 | case $1 in 2297 | -h|--help) rm_usage;; 2298 | -f|--force) FORCE=true 2299 | shift 1;; 2300 | *) GHC_VER=$1 2301 | break;; 2302 | esac 2303 | done 2304 | [ -n "${GHC_VER}" ] || rm_usage 2305 | rm_ghc "${GHC_VER}" 2306 | break;; 2307 | install-cabal) 2308 | shift 1 2309 | while [ $# -gt 0 ] ; do 2310 | case $1 in 2311 | -h|--help) install_cabal_usage;; 2312 | -f|--force) FORCE=true 2313 | shift 1;; 2314 | *) CABAL_VER=$1 2315 | break;; 2316 | esac 2317 | done 2318 | if [ -n "${CABAL_VER}" ] ; then 2319 | # could be a version or a tag, let's check 2320 | if array_contains "${CABAL_VER}" "$(known_tool_versions "cabal-install")" ; then 2321 | install_cabal "${CABAL_VER}" "${MY_OS}" 2322 | elif array_contains "${CABAL_VER}" "$(known_tool_tags "cabal-install")" ; then 2323 | install_cabal "$(get_tool_ver_from_tag "cabal-install" "${CABAL_VER}")" "${MY_OS}" 2324 | else 2325 | die "\"${CABAL_VER}\" is not a known version or tag!" 2326 | fi 2327 | else 2328 | _cabal_ver="$(get_tool_ver_from_tag "cabal-install" "recommended")" 2329 | if [ -z "${_cabal_ver}" ] ; then 2330 | die "Could not find a recommended cabal-install version, please report a bug at ${BUG_URL}!" 2331 | fi 2332 | install_cabal "${_cabal_ver}" "${MY_OS}" 2333 | fi 2334 | break;; 2335 | compile) 2336 | shift 1 2337 | while [ $# -gt 0 ] ; do 2338 | case $1 in 2339 | -h|--help) compile_usage;; 2340 | -f|--force) FORCE=true 2341 | shift 1;; 2342 | -j|--jobs) JOBS=$2 2343 | shift 2;; 2344 | -c|--build-config) BUILD_CONFIG=$2 2345 | shift 2;; 2346 | *) GHC_VER=$1 2347 | BOOTSTRAP_GHC=$2 2348 | break;; 2349 | esac 2350 | done 2351 | [ -n "${GHC_VER}" ] || compile_usage 2352 | [ -n "${BOOTSTRAP_GHC}" ] || compile_usage 2353 | compile_ghc "${GHC_VER}" "${BOOTSTRAP_GHC}" "${BUILD_CONFIG}" 2354 | break;; 2355 | debug-info) 2356 | shift 1 2357 | while [ $# -gt 0 ] ; do 2358 | case $1 in 2359 | -h|--help) debug_info_usage;; 2360 | *) debug_info_usage;; 2361 | esac 2362 | done 2363 | print_debug_info 2364 | break;; 2365 | list) 2366 | RAW_FORMAT=false 2367 | TOOL="ghc" 2368 | shift 1 2369 | while [ $# -gt 0 ] ; do 2370 | case $1 in 2371 | -h|--help) list_usage;; 2372 | -t|--tool) TOOL=$2 2373 | shift 2;; 2374 | -r|--raw-format) RAW_FORMAT=true 2375 | shift 1;; 2376 | -c|--show-criteria) SHOW_CRITERIA=$2 2377 | shift 2;; 2378 | *) list_usage;; 2379 | esac 2380 | done 2381 | list "${TOOL}" ${RAW_FORMAT} "${SHOW_CRITERIA}" 2382 | break;; 2383 | changelog) 2384 | shift 1 2385 | while [ $# -gt 0 ] ; do 2386 | case $1 in 2387 | -h|--help) changelog_usage;; 2388 | -f|--force) FORCE=true 2389 | shift 1;; 2390 | *) GHC_VER=$1 2391 | break;; 2392 | esac 2393 | done 2394 | if [ -z "${GHC_VER}" ] ; then 2395 | _tool_ver="$(get_tool_ver_from_tag "ghc" "latest")" 2396 | if [ -z "${_tool_ver}" ] ; then 2397 | die "Could not find a latest GHC version, please report a bug at ${BUG_URL}!" 2398 | fi 2399 | changelog "${_tool_ver}" 2400 | else 2401 | # could be a version or a tag, let's check 2402 | if array_contains "${GHC_VER}" "$(known_tool_versions "ghc")" ; then 2403 | changelog "${GHC_VER}" 2404 | elif array_contains "${GHC_VER}" "$(known_tool_tags "ghc")" ; then 2405 | changelog "$(get_tool_ver_from_tag "ghc" "${GHC_VER}")" 2406 | else 2407 | die "\"${GHC_VER}\" is not a known version or tag!" 2408 | fi 2409 | fi 2410 | break;; 2411 | print-system-reqs) 2412 | shift 1 2413 | while [ $# -gt 0 ] ; do 2414 | case $1 in 2415 | -h|--help) print_system_reqs_usage;; 2416 | *) print_system_reqs_usage;; 2417 | esac 2418 | done 2419 | print_system_reqs 2420 | break;; 2421 | *) usage;; 2422 | esac 2423 | break;; 2424 | esac 2425 | done 2426 | 2427 | 2428 | # vim: tabstop=4 shiftwidth=4 expandtab 2429 | -------------------------------------------------------------------------------- /www/LICENSE: -------------------------------------------------------------------------------- 1 | The ghcup website, excluding ghcup, fonts, bootstrap-haskell script are subject 2 | to the license below. Design, javascript and css are used from the rustup 3 | project: https://github.com/rust-lang/rustup.rs/tree/master/www 4 | 5 | 6 | 7 | =============================================================================== 8 | Apache License 9 | Version 2.0, January 2004 10 | http://www.apache.org/licenses/ 11 | 12 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 13 | 14 | 1. Definitions. 15 | 16 | "License" shall mean the terms and conditions for use, reproduction, 17 | and distribution as defined by Sections 1 through 9 of this document. 18 | 19 | "Licensor" shall mean the copyright owner or entity authorized by 20 | the copyright owner that is granting the License. 21 | 22 | "Legal Entity" shall mean the union of the acting entity and all 23 | other entities that control, are controlled by, or are under common 24 | control with that entity. For the purposes of this definition, 25 | "control" means (i) the power, direct or indirect, to cause the 26 | direction or management of such entity, whether by contract or 27 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 28 | outstanding shares, or (iii) beneficial ownership of such entity. 29 | 30 | "You" (or "Your") shall mean an individual or Legal Entity 31 | exercising permissions granted by this License. 32 | 33 | "Source" form shall mean the preferred form for making modifications, 34 | including but not limited to software source code, documentation 35 | source, and configuration files. 36 | 37 | "Object" form shall mean any form resulting from mechanical 38 | transformation or translation of a Source form, including but 39 | not limited to compiled object code, generated documentation, 40 | and conversions to other media types. 41 | 42 | "Work" shall mean the work of authorship, whether in Source or 43 | Object form, made available under the License, as indicated by a 44 | copyright notice that is included in or attached to the work 45 | (an example is provided in the Appendix below). 46 | 47 | "Derivative Works" shall mean any work, whether in Source or Object 48 | form, that is based on (or derived from) the Work and for which the 49 | editorial revisions, annotations, elaborations, or other modifications 50 | represent, as a whole, an original work of authorship. For the purposes 51 | of this License, Derivative Works shall not include works that remain 52 | separable from, or merely link (or bind by name) to the interfaces of, 53 | the Work and Derivative Works thereof. 54 | 55 | "Contribution" shall mean any work of authorship, including 56 | the original version of the Work and any modifications or additions 57 | to that Work or Derivative Works thereof, that is intentionally 58 | submitted to Licensor for inclusion in the Work by the copyright owner 59 | or by an individual or Legal Entity authorized to submit on behalf of 60 | the copyright owner. For the purposes of this definition, "submitted" 61 | means any form of electronic, verbal, or written communication sent 62 | to the Licensor or its representatives, including but not limited to 63 | communication on electronic mailing lists, source code control systems, 64 | and issue tracking systems that are managed by, or on behalf of, the 65 | Licensor for the purpose of discussing and improving the Work, but 66 | excluding communication that is conspicuously marked or otherwise 67 | designated in writing by the copyright owner as "Not a Contribution." 68 | 69 | "Contributor" shall mean Licensor and any individual or Legal Entity 70 | on behalf of whom a Contribution has been received by Licensor and 71 | subsequently incorporated within the Work. 72 | 73 | 2. Grant of Copyright License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | copyright license to reproduce, prepare Derivative Works of, 77 | publicly display, publicly perform, sublicense, and distribute the 78 | Work and such Derivative Works in Source or Object form. 79 | 80 | 3. Grant of Patent License. Subject to the terms and conditions of 81 | this License, each Contributor hereby grants to You a perpetual, 82 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 83 | (except as stated in this section) patent license to make, have made, 84 | use, offer to sell, sell, import, and otherwise transfer the Work, 85 | where such license applies only to those patent claims licensable 86 | by such Contributor that are necessarily infringed by their 87 | Contribution(s) alone or by combination of their Contribution(s) 88 | with the Work to which such Contribution(s) was submitted. If You 89 | institute patent litigation against any entity (including a 90 | cross-claim or counterclaim in a lawsuit) alleging that the Work 91 | or a Contribution incorporated within the Work constitutes direct 92 | or contributory patent infringement, then any patent licenses 93 | granted to You under this License for that Work shall terminate 94 | as of the date such litigation is filed. 95 | 96 | 4. Redistribution. You may reproduce and distribute copies of the 97 | Work or Derivative Works thereof in any medium, with or without 98 | modifications, and in Source or Object form, provided that You 99 | meet the following conditions: 100 | 101 | (a) You must give any other recipients of the Work or 102 | Derivative Works a copy of this License; and 103 | 104 | (b) You must cause any modified files to carry prominent notices 105 | stating that You changed the files; and 106 | 107 | (c) You must retain, in the Source form of any Derivative Works 108 | that You distribute, all copyright, patent, trademark, and 109 | attribution notices from the Source form of the Work, 110 | excluding those notices that do not pertain to any part of 111 | the Derivative Works; and 112 | 113 | (d) If the Work includes a "NOTICE" text file as part of its 114 | distribution, then any Derivative Works that You distribute must 115 | include a readable copy of the attribution notices contained 116 | within such NOTICE file, excluding those notices that do not 117 | pertain to any part of the Derivative Works, in at least one 118 | of the following places: within a NOTICE text file distributed 119 | as part of the Derivative Works; within the Source form or 120 | documentation, if provided along with the Derivative Works; or, 121 | within a display generated by the Derivative Works, if and 122 | wherever such third-party notices normally appear. The contents 123 | of the NOTICE file are for informational purposes only and 124 | do not modify the License. You may add Your own attribution 125 | notices within Derivative Works that You distribute, alongside 126 | or as an addendum to the NOTICE text from the Work, provided 127 | that such additional attribution notices cannot be construed 128 | as modifying the License. 129 | 130 | You may add Your own copyright statement to Your modifications and 131 | may provide additional or different license terms and conditions 132 | for use, reproduction, or distribution of Your modifications, or 133 | for any such Derivative Works as a whole, provided Your use, 134 | reproduction, and distribution of the Work otherwise complies with 135 | the conditions stated in this License. 136 | 137 | 5. Submission of Contributions. Unless You explicitly state otherwise, 138 | any Contribution intentionally submitted for inclusion in the Work 139 | by You to the Licensor shall be under the terms and conditions of 140 | this License, without any additional terms or conditions. 141 | Notwithstanding the above, nothing herein shall supersede or modify 142 | the terms of any separate license agreement you may have executed 143 | with Licensor regarding such Contributions. 144 | 145 | 6. Trademarks. This License does not grant permission to use the trade 146 | names, trademarks, service marks, or product names of the Licensor, 147 | except as required for reasonable and customary use in describing the 148 | origin of the Work and reproducing the content of the NOTICE file. 149 | 150 | 7. Disclaimer of Warranty. Unless required by applicable law or 151 | agreed to in writing, Licensor provides the Work (and each 152 | Contributor provides its Contributions) on an "AS IS" BASIS, 153 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 154 | implied, including, without limitation, any warranties or conditions 155 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 156 | PARTICULAR PURPOSE. You are solely responsible for determining the 157 | appropriateness of using or redistributing the Work and assume any 158 | risks associated with Your exercise of permissions under this License. 159 | 160 | 8. Limitation of Liability. In no event and under no legal theory, 161 | whether in tort (including negligence), contract, or otherwise, 162 | unless required by applicable law (such as deliberate and grossly 163 | negligent acts) or agreed to in writing, shall any Contributor be 164 | liable to You for damages, including any direct, indirect, special, 165 | incidental, or consequential damages of any character arising as a 166 | result of this License or out of the use or inability to use the 167 | Work (including but not limited to damages for loss of goodwill, 168 | work stoppage, computer failure or malfunction, or any and all 169 | other commercial damages or losses), even if such Contributor 170 | has been advised of the possibility of such damages. 171 | 172 | 9. Accepting Warranty or Additional Liability. While redistributing 173 | the Work or Derivative Works thereof, You may choose to offer, 174 | and charge a fee for, acceptance of support, warranty, indemnity, 175 | or other liability obligations and/or rights consistent with this 176 | License. However, in accepting such obligations, You may act only 177 | on Your own behalf and on Your sole responsibility, not on behalf 178 | of any other Contributor, and only if You agree to indemnify, 179 | defend, and hold each Contributor harmless for any liability 180 | incurred by, or claims asserted against, such Contributor by reason 181 | of your accepting any such warranty or additional liability. 182 | 183 | END OF TERMS AND CONDITIONS 184 | 185 | APPENDIX: How to apply the Apache License to your work. 186 | 187 | To apply the Apache License to your work, attach the following 188 | boilerplate notice, with the fields enclosed by brackets "[]" 189 | replaced with your own identifying information. (Don't include 190 | the brackets!) The text should be enclosed in the appropriate 191 | comment syntax for the file format. We also recommend that a 192 | file or class name and description of purpose be included on the 193 | same "printed page" as the copyright notice for easier 194 | identification within third-party archives. 195 | 196 | Copyright [yyyy] [name of copyright owner] 197 | 198 | Licensed under the Apache License, Version 2.0 (the "License"); 199 | you may not use this file except in compliance with the License. 200 | You may obtain a copy of the License at 201 | 202 | http://www.apache.org/licenses/LICENSE-2.0 203 | 204 | Unless required by applicable law or agreed to in writing, software 205 | distributed under the License is distributed on an "AS IS" BASIS, 206 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 207 | See the License for the specific language governing permissions and 208 | limitations under the License. 209 | -------------------------------------------------------------------------------- /www/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /www/fonts/FiraSans-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghcup/8f4705a50eefafd92ceef32094eec7140885b3d5/www/fonts/FiraSans-Light.woff -------------------------------------------------------------------------------- /www/fonts/FiraSans-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghcup/8f4705a50eefafd92ceef32094eec7140885b3d5/www/fonts/FiraSans-Medium.woff -------------------------------------------------------------------------------- /www/fonts/FiraSans-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghcup/8f4705a50eefafd92ceef32094eec7140885b3d5/www/fonts/FiraSans-Regular.woff -------------------------------------------------------------------------------- /www/fonts/Inconsolata-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghcup/8f4705a50eefafd92ceef32094eec7140885b3d5/www/fonts/Inconsolata-Regular.ttf -------------------------------------------------------------------------------- /www/fonts/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Raph Levien (firstname.lastname@gmail.com), Copyright (c) 2012, Cyreal (cyreal.org) 2 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 3 | This license is copied below, and is also available with a FAQ at: 4 | http://scripts.sil.org/OFL 5 | 6 | 7 | ----------------------------------------------------------- 8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 9 | ----------------------------------------------------------- 10 | 11 | PREAMBLE 12 | The goals of the Open Font License (OFL) are to stimulate worldwide 13 | development of collaborative font projects, to support the font creation 14 | efforts of academic and linguistic communities, and to provide a free and 15 | open framework in which fonts may be shared and improved in partnership 16 | with others. 17 | 18 | The OFL allows the licensed fonts to be used, studied, modified and 19 | redistributed freely as long as they are not sold by themselves. The 20 | fonts, including any derivative works, can be bundled, embedded, 21 | redistributed and/or sold with any software provided that any reserved 22 | names are not used by derivative works. The fonts and derivatives, 23 | however, cannot be released under any other type of license. The 24 | requirement for fonts to remain under this license does not apply 25 | to any document created using the fonts or their derivatives. 26 | 27 | DEFINITIONS 28 | "Font Software" refers to the set of files released by the Copyright 29 | Holder(s) under this license and clearly marked as such. This may 30 | include source files, build scripts and documentation. 31 | 32 | "Reserved Font Name" refers to any names specified as such after the 33 | copyright statement(s). 34 | 35 | "Original Version" refers to the collection of Font Software components as 36 | distributed by the Copyright Holder(s). 37 | 38 | "Modified Version" refers to any derivative made by adding to, deleting, 39 | or substituting -- in part or in whole -- any of the components of the 40 | Original Version, by changing formats or by porting the Font Software to a 41 | new environment. 42 | 43 | "Author" refers to any designer, engineer, programmer, technical 44 | writer or other person who contributed to the Font Software. 45 | 46 | PERMISSION & CONDITIONS 47 | Permission is hereby granted, free of charge, to any person obtaining 48 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 49 | redistribute, and sell modified and unmodified copies of the Font 50 | Software, subject to the following conditions: 51 | 52 | 1) Neither the Font Software nor any of its individual components, 53 | in Original or Modified Versions, may be sold by itself. 54 | 55 | 2) Original or Modified Versions of the Font Software may be bundled, 56 | redistributed and/or sold with any software, provided that each copy 57 | contains the above copyright notice and this license. These can be 58 | included either as stand-alone text files, human-readable headers or 59 | in the appropriate machine-readable metadata fields within text or 60 | binary files as long as those fields can be easily viewed by the user. 61 | 62 | 3) No Modified Version of the Font Software may use the Reserved Font 63 | Name(s) unless explicit written permission is granted by the corresponding 64 | Copyright Holder. This restriction only applies to the primary font name as 65 | presented to the users. 66 | 67 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 68 | Software shall not be used to promote, endorse or advertise any 69 | Modified Version, except to acknowledge the contribution(s) of the 70 | Copyright Holder(s) and the Author(s) or with their explicit written 71 | permission. 72 | 73 | 5) The Font Software, modified or unmodified, in part or in whole, 74 | must be distributed entirely under this license, and must not be 75 | distributed under any other license. The requirement for fonts to 76 | remain under this license does not apply to any document created 77 | using the Font Software. 78 | 79 | TERMINATION 80 | This license becomes null and void if any of the above conditions are 81 | not met. 82 | 83 | DISCLAIMER 84 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 85 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 86 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 87 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 88 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 89 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 90 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 91 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 92 | OTHER DEALINGS IN THE FONT SOFTWARE. 93 | -------------------------------------------------------------------------------- /www/fonts/WorkSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghcup/8f4705a50eefafd92ceef32094eec7140885b3d5/www/fonts/WorkSans-Medium.ttf -------------------------------------------------------------------------------- /www/ghcup.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Fira Sans'; 3 | font-style: normal; 4 | font-weight: 300; 5 | src: local('Fira Sans Light'), url("fonts/FiraSans-Light.woff") format('woff'); 6 | } 7 | @font-face { 8 | font-family: 'Fira Sans'; 9 | font-style: normal; 10 | font-weight: 400; 11 | src: local('Fira Sans'), url("fonts/FiraSans-Regular.woff") format('woff'); 12 | } 13 | @font-face { 14 | font-family: 'Fira Sans'; 15 | font-style: normal; 16 | font-weight: 500; 17 | src: local('Fira Sans Medium'), url("fonts/FiraSans-Medium.woff") format('woff'); 18 | } 19 | 20 | @font-face { 21 | font-family: 'Work Sans'; 22 | font-style: normal; 23 | font-weight: 500; 24 | src: local('Work Sans Medium'), url("fonts/WorkSans-Medium.ttf") format('ttf'); 25 | } 26 | 27 | @font-face { 28 | font-family: 'Inconsolata'; 29 | font-style: normal; 30 | font-weight: 400; 31 | src: local('Inconsolata Regular'), url("fonts/Inconsolata-Regular.ttf") format('ttf'); 32 | } 33 | 34 | body { 35 | margin-top: 2em; 36 | background-color: white; 37 | color: #515151; 38 | font-family: "Fira Sans","Helvetica Neue",Helvetica,Arial,sans-serif; 39 | font-weight: 300; 40 | font-size: 25px; 41 | } 42 | 43 | pre { 44 | font-family: Inconsolata,Menlo,Monaco,Consolas,"Courier New",monospace; 45 | font-weight: 400; 46 | } 47 | 48 | body#idx #pitch > a { 49 | font-weight: 500; 50 | line-height: 2em; 51 | } 52 | 53 | a { 54 | color: #428bca; 55 | text-decoration: none; 56 | } 57 | 58 | a:hover { 59 | color: rgb(42, 100, 150); 60 | } 61 | 62 | body#idx > * { 63 | margin-left: auto; 64 | margin-right: auto; 65 | text-align: center; 66 | width: 37em; 67 | } 68 | 69 | body#idx > #pitch { 70 | width: 30rem; 71 | } 72 | 73 | #pitch em { 74 | font-style: normal; 75 | font-weight: 400; 76 | } 77 | 78 | body#idx p { 79 | margin-top: 2em; 80 | margin-bottom: 2em; 81 | } 82 | 83 | body#idx p.other-help { 84 | font-size: 0.6em; 85 | } 86 | 87 | .instructions { 88 | background-color: rgb(250, 250, 250); 89 | margin-left: auto; 90 | margin-right: auto; 91 | border-radius: 3px; 92 | border: 1px solid rgb(204, 204, 204); 93 | box-shadow: 0px 1px 4px 0px rgb(204, 204, 204); 94 | } 95 | 96 | .instructions > * { 97 | width: 55rem; 98 | margin-left: auto; 99 | margin-right: auto; 100 | } 101 | 102 | .instructions div.command-button { 103 | display: flex; 104 | } 105 | 106 | .instructions div.command-button button { 107 | color: white; 108 | /* border: none; */ 109 | background-color: rgb(242, 242, 242); 110 | border-width: 2px; 111 | border-style: solid; 112 | border-radius: 3px; 113 | 114 | margin-left: 1rem; 115 | margin-right: auto; 116 | margin-top: 25px; 117 | margin-bottom: 25px; 118 | text-align: center; 119 | } 120 | 121 | .instructions div.command-button button:hover { 122 | background: rgb(232, 232, 232); 123 | } 124 | 125 | .instructions div.command-button button:focus { 126 | background: rgb(222, 222, 222); 127 | } 128 | 129 | hr { 130 | margin-top: 2em; 131 | margin-bottom: 2em; 132 | } 133 | 134 | #platform-instructions-linux > div > pre, 135 | #platform-instructions-mac > div > pre, 136 | #platform-instructions-freebsd > div > pre, 137 | #platform-instructions-win32 > pre, 138 | #platform-instructions-win64 > pre, 139 | #platform-instructions-default > div > div > pre, 140 | #platform-instructions-unknown > div > div > pre { 141 | background-color: #515151; 142 | color: white; 143 | margin-left: auto; 144 | margin-right: auto; 145 | padding-top: 1rem; 146 | padding-bottom: 1rem; 147 | padding-right: 1rem; 148 | text-align: center; 149 | border-radius: 3px; 150 | box-shadow: inset 0px 0px 20px 0px #333333; 151 | } 152 | 153 | #platform-instructions-win32 a.windows-download, 154 | #platform-instructions-win64 a.windows-download, 155 | #platform-instructions-default a.windows-download, 156 | #platform-instructions-unknown a.windows-download { 157 | display: block; 158 | padding-top: 0.4rem; 159 | padding-bottom: 0.6rem; 160 | font-family: "Work Sans", "Fira Sans","Helvetica Neue",Helvetica,Arial,sans-serif; 161 | font-weight: 500; 162 | letter-spacing: 0.1rem; 163 | } 164 | 165 | /* This is the box that prints navigator.platform, navigator.appVersion values */ 166 | #platform-instructions-unknown > div:first-of-type { 167 | font-size: 16px; 168 | line-height: 2rem; 169 | } 170 | 171 | #about { 172 | font-size: 16px; 173 | line-height: 2em; 174 | } 175 | 176 | #about > img { 177 | width: 30px; 178 | height: 30px; 179 | transform: translateY(11px); 180 | } 181 | 182 | #platform-button { 183 | background-color: #515151; 184 | color: white; 185 | margin-left: auto; 186 | margin-right: auto; 187 | padding: 1em; 188 | } 189 | 190 | .ghcup-command:before { 191 | color: #999; 192 | content: " $ "; 193 | } 194 | 195 | /* Tooltip container */ 196 | .tooltip { 197 | position: relative; 198 | display: inline-block; 199 | /* border-bottom: 1px dotted black; [> If you want dots under the hoverable text <] */ 200 | } 201 | 202 | /* Tooltip text */ 203 | .tooltip .tooltiptext { 204 | visibility: hidden; 205 | width: 120px; 206 | background-color: #555; 207 | color: #fff; 208 | text-align: center; 209 | padding: 5px 0; 210 | border-radius: 6px; 211 | 212 | /* Position the tooltip text */ 213 | position: absolute; 214 | z-index: 1; 215 | bottom: 125%; 216 | left: 50%; 217 | margin-left: -60px; 218 | 219 | /* Fade in tooltip */ 220 | opacity: 0; 221 | transition: opacity 0.3s; 222 | } 223 | 224 | /* Tooltip arrow */ 225 | .tooltip .tooltiptext::after { 226 | content: ""; 227 | position: absolute; 228 | top: 100%; 229 | left: 50%; 230 | margin-left: -5px; 231 | border-width: 5px; 232 | border-style: solid; 233 | border-color: #555 transparent transparent transparent; 234 | } 235 | 236 | /* Show the tooltip text when you mouse over the tooltip container */ 237 | .tooltip:hover .tooltiptext { 238 | visibility: visible; 239 | opacity: 1; 240 | } 241 | -------------------------------------------------------------------------------- /www/ghcup.js: -------------------------------------------------------------------------------- 1 | var platforms = ["default", "unknown", "win32", "win64", "linux", "freebsd", "mac"]; 2 | var platform_override = null; 3 | 4 | function detect_platform() { 5 | "use strict"; 6 | 7 | if (platform_override !== null) { 8 | return platforms[platform_override]; 9 | } 10 | 11 | var os = "unknown"; 12 | 13 | if (navigator.platform == "Linux x86_64") {os = "linux";} 14 | if (navigator.platform == "Linux i686") {os = "linux";} 15 | if (navigator.platform == "Linux i686 on x86_64") {os = "linux";} 16 | if (navigator.platform == "Linux aarch64") {os = "linux";} 17 | if (navigator.platform == "Linux armv6l") {os = "linux";} 18 | if (navigator.platform == "Linux armv7l") {os = "linux";} 19 | if (navigator.platform == "Linux armv8l") {os = "linux";} 20 | if (navigator.platform == "Linux ppc64") {os = "linux";} 21 | if (navigator.platform == "Linux mips") {os = "linux";} 22 | if (navigator.platform == "Linux mips64") {os = "linux";} 23 | if (navigator.platform == "Mac") {os = "mac";} 24 | if (navigator.platform == "Win32") {os = "win32";} 25 | if (navigator.platform == "Win64" || 26 | navigator.userAgent.indexOf("WOW64") != -1 || 27 | navigator.userAgent.indexOf("Win64") != -1) { os = "win64"; } 28 | if (navigator.platform == "FreeBSD x86_64") {os = "freebsd";} 29 | if (navigator.platform == "FreeBSD amd64") {os = "freebsd";} 30 | // if (navigator.platform == "NetBSD x86_64") {os = "unix";} 31 | // if (navigator.platform == "NetBSD amd64") {os = "unix";} 32 | 33 | // I wish I knew by now, but I don't. Try harder. 34 | if (os == "unknown") { 35 | if (navigator.appVersion.indexOf("Win")!=-1) {os = "win32";} 36 | if (navigator.appVersion.indexOf("Mac")!=-1) {os = "mac";} 37 | if (navigator.appVersion.indexOf("FreeBSD")!=-1) {os = "freebsd";} 38 | } 39 | 40 | // Firefox Quantum likes to hide platform and appVersion but oscpu works 41 | if (navigator.oscpu) { 42 | if (navigator.oscpu.indexOf("Win32")!=-1) {os = "win32";} 43 | if (navigator.oscpu.indexOf("Win64")!=-1) {os = "win64";} 44 | if (navigator.oscpu.indexOf("Mac")!=-1) {os = "mac";} 45 | if (navigator.oscpu.indexOf("Linux")!=-1) {os = "linux";} 46 | if (navigator.oscpu.indexOf("FreeBSD")!=-1) {os = "freebsd";} 47 | // if (navigator.oscpu.indexOf("NetBSD")!=-1) {os = "unix";} 48 | } 49 | 50 | return os; 51 | } 52 | 53 | function adjust_for_platform() { 54 | "use strict"; 55 | 56 | var platform = detect_platform(); 57 | 58 | platforms.forEach(function (platform_elem) { 59 | var platform_div = document.getElementById("platform-instructions-" + platform_elem); 60 | platform_div.style.display = "none"; 61 | if (platform == platform_elem) { 62 | platform_div.style.display = "block"; 63 | } 64 | }); 65 | 66 | adjust_platform_specific_instrs(platform); 67 | } 68 | 69 | function adjust_platform_specific_instrs(platform) { 70 | var platform_specific = document.getElementsByClassName("platform-specific"); 71 | for (var el of platform_specific) { 72 | var el_is_not_win = el.className.indexOf("not-win") !== -1; 73 | var el_is_inline = el.tagName.toLowerCase() == "span"; 74 | var el_visible_style = "block"; 75 | if (el_is_inline) { 76 | el_visible_style = "inline"; 77 | } 78 | if (platform == "win64" || platform == "win32") { 79 | if (el_is_not_win) { 80 | el.style.display = "none"; 81 | } else { 82 | el.style.display = el_visible_style; 83 | } 84 | } else { 85 | if (el_is_not_win) { 86 | el.style.display = el_visible_style; 87 | } else { 88 | el.style.display = "none"; 89 | } 90 | } 91 | } 92 | } 93 | 94 | function cycle_platform() { 95 | if (platform_override == null) { 96 | platform_override = 0; 97 | } else { 98 | platform_override = (platform_override + 1) % platforms.length; 99 | } 100 | adjust_for_platform(); 101 | } 102 | 103 | function set_up_cycle_button() { 104 | var cycle_button = document.getElementById("platform-button"); 105 | cycle_button.onclick = cycle_platform; 106 | 107 | var key="test"; 108 | var idx=0; 109 | var unlocked=false; 110 | 111 | document.onkeypress = function(event) { 112 | if (event.key == "n" && unlocked) { 113 | cycle_platform(); 114 | } 115 | 116 | if (event.key == key[idx]) { 117 | idx += 1; 118 | 119 | if (idx == key.length) { 120 | cycle_button.style.display = "block"; 121 | unlocked = true; 122 | cycle_platform(); 123 | } 124 | } else if (event.key == key[0]) { 125 | idx = 1; 126 | } else { 127 | idx = 0; 128 | } 129 | }; 130 | } 131 | 132 | function go_to_default_platform() { 133 | platform_override = 0; 134 | adjust_for_platform(); 135 | } 136 | 137 | function set_up_default_platform_buttons() { 138 | var defaults_buttons = document.getElementsByClassName('default-platform-button'); 139 | for (var i = 0; i < defaults_buttons.length; i++) { 140 | defaults_buttons[i].onclick = go_to_default_platform; 141 | } 142 | } 143 | 144 | function fill_in_bug_report_values() { 145 | var nav_plat = document.getElementById("nav-plat"); 146 | var nav_app = document.getElementById("nav-app"); 147 | nav_plat.textContent = navigator.platform; 148 | nav_app.textContent = navigator.appVersion; 149 | } 150 | 151 | function copyToClipboard() { 152 | const text = document.getElementsByClassName("ghcup-command").item(0).innerText; 153 | const el = document.createElement('textarea'); 154 | el.value = text; 155 | document.body.appendChild(el); 156 | el.select(); 157 | document.execCommand('copy'); 158 | document.body.removeChild(el); 159 | } 160 | 161 | (function () { 162 | adjust_for_platform(); 163 | set_up_cycle_button(); 164 | set_up_default_platform_buttons(); 165 | fill_in_bug_report_values(); 166 | }()); 167 | -------------------------------------------------------------------------------- /www/haskell-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 61 | 66 | 67 | -------------------------------------------------------------------------------- /www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ghcup - The Haskell (GHC) toolchain installer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 130 | 133 | 134 | 135 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /www/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | --------------------------------------------------------------------------------