bootstrap.sh 10.1 KB
Newer Older
1
#!/usr/bin/env sh
Duncan Coutts's avatar
Duncan Coutts committed
2
3
4
5
6
7
8

# A script to bootstrap cabal-install.

# It works by downloading and installing the Cabal, zlib and
# HTTP packages. It then installs cabal-install itself.
# It expects to be run inside the cabal-install directory.

9
10
11
# install settings, you can override these by setting environment vars
#VERBOSE
#EXTRA_CONFIGURE_OPTS
12
13
#EXTRA_BUILD_OPTS
#EXTRA_INSTALL_OPTS
14

15
16
die () { printf "\nError during cabal-install bootstrap:\n$1\n" >&2 && exit 2 ;}

17
# programs, you can override these by setting environment vars
18
19
20
GHC="${GHC:-ghc}"
GHC_PKG="${GHC_PKG:-ghc-pkg}"
GHC_VER="$(${GHC} --numeric-version)"
21
HADDOCK=${HADDOCK:-haddock}
22
23
24
25
WGET="${WGET:-wget}"
CURL="${CURL:-curl}"
FETCH="${FETCH:-fetch}"
TAR="${TAR:-tar}"
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
26
GZIP="${GZIP:-gzip}"
27
SCOPE_OF_INSTALLATION="--user"
28
DEFAULT_PREFIX="${HOME}/.cabal"
29

Geoff Nixon's avatar
Geoff Nixon committed
30
31
32
33
# Try to respect $TMPDIR but override if needed - see #1710.
[ -"$TMPDIR"- = -""- ] || echo "$TMPDIR" | grep -q ld &&
  export TMPDIR=/tmp/cabal-$(echo $(od -XN4 -An /dev/random)) && mkdir $TMPDIR

34
35
# Check for a C compiler.
[ ! -x "$CC" ] && for ccc in gcc clang cc icc; do
tuncer's avatar
tuncer committed
36
37
  ${ccc} --version > /dev/null 2>&1 && CC=$ccc &&
  echo "Using $CC for C compiler. If this is not what you want, set CC." >&2 &&
38
39
40
41
  break
done

# None found.
42
[ ! -x `which "$CC"` ] &&
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  die "C compiler not found (or could not be run).
       If a C compiler is installed make sure it is on your PATH,
       or set the CC variable."

# Check the C compiler/linker work.
LINK="$(for link in collect2 ld; do
  echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -q $link &&
  echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep    $link |
  sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
done)"

# They don't.
[ -z "$LINK" ] &&
  die "C compiler and linker could not compile a simple test program.
       Please check your toolchain."

## Warn that were's overriding $LD if set (if you want).

[ -x "$LD" ] && [ "$LD" != "$LINK" ] &&
  echo "Warning: value set in $LD is not the same as C compiler's $LINK." >&2
  echo "Using $LINK instead." >&2

# Set LD, overriding environment if necessary.
LD=$LINK

# Check we're in the right directory, etc.
grep "cabal-install" ./cabal-install.cabal > /dev/null 2>&1 ||
  die "The bootstrap.sh script must be run in the cabal-install directory"
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
${GHC} --numeric-version > /dev/null 2>&1  ||
  die "${GHC} not found (or could not be run).
       If ghc is installed,  make sure it is on your PATH,
       or set the GHC and GHC_PKG vars."

${GHC_PKG} --version     > /dev/null 2>&1  || die "${GHC_PKG} not found."

GHC_VER="$(${GHC} --numeric-version)"
GHC_PKG_VER="$(${GHC_PKG} --version | cut -d' ' -f 5)"

[ ${GHC_VER} = ${GHC_PKG_VER} ] ||
  die "Version mismatch between ${GHC} and ${GHC_PKG}.
       If you set the GHC variable then set GHC_PKG too."

for arg in "$@"
87
88
89
90
91
92
93
do
  case "${arg}" in
    "--user")
      SCOPE_OF_INSTALLATION=${arg}
      shift;;
    "--global")
      SCOPE_OF_INSTALLATION=${arg}
94
      DEFAULT_PREFIX="/usr/local"
95
      shift;;
96
97
98
    "--no-doc")
      NO_DOCUMENTATION=1
      shift;;
99
100
101
102
103
104
    *)
      echo "Unknown argument or option, quitting: ${arg}"
      echo "usage: bootstrap.sh [OPTION]"
      echo
      echo "options:"
      echo "   --user    Install for the local user (default)"
105
      echo "   --global  Install systemwide (must be run as root)"
106
      echo "   --no-doc  Do not generate documentation for installed packages"
107
108
109
      exit;;
  esac
done
110

111
112
113
114
115
116
# Check for haddock unless no documentation should be generated.
if [ ! ${NO_DOCUMENTATION} ]
then
  ${HADDOCK} --version     > /dev/null 2>&1  || die "${HADDOCK} not found."
fi

117
PREFIX=${PREFIX:-${DEFAULT_PREFIX}}
118
119
120

# Versions of the packages to install.
# The version regex says what existing installed versions are ok.
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
PARSEC_VER="3.1.5";    PARSEC_VER_REGEXP="[23]\."
                       # == 2.* || == 3.*
DEEPSEQ_VER="1.3.0.2"; DEEPSEQ_VER_REGEXP="1\.[1-9]\."
                       # >= 1.1 && < 2
TEXT_VER="1.1.0.0";    TEXT_VER_REGEXP="((1\.[01]\.)|(0\.([2-9]|(1[0-1]))\.))"
                       # >= 0.2 && < 1.2
NETWORK_VER="2.4.2.2"; NETWORK_VER_REGEXP="2\."
                       # == 2.*
# CABAL_VER="1.19.2";    CABAL_VER_REGEXP="1\.1[9]\."
                       # >= 1.19 && < 1.20
TRANS_VER="0.3.0.0";   TRANS_VER_REGEXP="0\.[23]\."
                       # >= 0.2.* && < 0.4.*
MTL_VER="2.1.2";       MTL_VER_REGEXP="[2]\."
                       #  == 2.*
HTTP_VER="4000.2.10";  HTTP_VER_REGEXP="4000\.[012]\."
                       # == 4000.0.* || 4000.1.* || 4000.2.*
ZLIB_VER="0.5.4.1";    ZLIB_VER_REGEXP="0\.[45]\."
                       # == 0.4.* || == 0.5.*
TIME_VER="1.4.1"       TIME_VER_REGEXP="1\.[1234]\.?"
                       # >= 1.1 && < 1.5
RANDOM_VER="1.0.1.1"   RANDOM_VER_REGEXP="1\.0\."
                       # >= 1 && < 1.1
STM_VER="2.4.2";       STM_VER_REGEXP="2\."
                       # == 2.*
Duncan Coutts's avatar
Duncan Coutts committed
145

nkaretnikov's avatar
nkaretnikov committed
146
HACKAGE_URL="https://hackage.haskell.org/package"
147

148
# Cache the list of packages:
149
echo "Checking installed packages for ghc-${GHC_VER}..."
150
151
${GHC_PKG} list --global ${SCOPE_OF_INSTALLATION} > ghc-pkg.list ||
  die "running '${GHC_PKG} list' failed"
152
153
154
155
156

# Will we need to install this package, or is a suitable version installed?
need_pkg () {
  PKG=$1
  VER_MATCH=$2
157
  if egrep " ${PKG}-${VER_MATCH}" ghc-pkg.list > /dev/null 2>&1
158
159
160
161
162
163
  then
    return 1;
  else
    return 0;
  fi
  #Note: we cannot use "! grep" here as Solaris 9 /bin/sh doesn't like it.
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
}

info_pkg () {
  PKG=$1
  VER=$2
  VER_MATCH=$3

  if need_pkg ${PKG} ${VER_MATCH}
  then
    echo "${PKG}-${VER} will be downloaded and installed."
  else
    echo "${PKG} is already installed and the version is ok."
  fi
}

fetch_pkg () {
  PKG=$1
  VER=$2

183
  URL=${HACKAGE_URL}/${PKG}-${VER}/${PKG}-${VER}.tar.gz
184
185
  if which ${CURL} > /dev/null
  then
tuncer's avatar
tuncer committed
186
187
188
    # TODO: switch back to resuming curl command once
    #       https://github.com/haskell/hackage-server/issues/111 is resolved
    #${CURL} -L --fail -C - -O ${URL} || die "Failed to download ${PKG}."
189
    ${CURL} -L --fail -O ${URL} || die "Failed to download ${PKG}."
190
191
192
  elif which ${WGET} > /dev/null
  then
    ${WGET} -c ${URL} || die "Failed to download ${PKG}."
193
  elif which ${FETCH} > /dev/null
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
194
195
    then
      ${FETCH} ${URL} || die "Failed to download ${PKG}."
196
  else
197
    die "Failed to find a downloader. 'curl', 'wget' or 'fetch' is required."
198
  fi
199
200
  [ -f "${PKG}-${VER}.tar.gz" ] ||
     die "Downloading ${URL} did not create ${PKG}-${VER}.tar.gz"
201
202
203
204
205
206
}

unpack_pkg () {
  PKG=$1
  VER=$2

207
  rm -rf "${PKG}-${VER}.tar" "${PKG}-${VER}"
208
  ${GZIP} -d < "${PKG}-${VER}.tar.gz" | ${TAR} -x
209
  [ -d "${PKG}-${VER}" ] || die "Failed to unpack ${PKG}-${VER}.tar.gz"
210
211
212
213
214
}

install_pkg () {
  PKG=$1

215
216
217
  [ -x Setup ] && ./Setup clean
  [ -f Setup ] && rm Setup

218
219
220
  ${GHC} --make Setup -o Setup ||
    die "Compiling the Setup script failed."

221
  [ -x Setup ] || die "The Setup script does not exist or cannot be run"
222

223
224
225
226
227
  args="${SCOPE_OF_INSTALLATION} --prefix=${PREFIX} --with-compiler=${GHC}"
  args="$args --with-hc-pkg=${GHC_PKG} --with-gcc=${CC} --with-ld=${LD}"
  args="$args ${EXTRA_CONFIGURE_OPTS} ${VERBOSE}"

  ./Setup configure $args || die "Configuring the ${PKG} package failed."
228

229
230
  ./Setup build ${EXTRA_BUILD_OPTS} ${VERBOSE} ||
     die "Building the ${PKG} package failed."
231

232
233
234
235
236
  if [ ! ${NO_DOCUMENTATION} ]
  then
    ./Setup haddock --with-ghc=${GHC} --with-haddock=${HADDOCK} ${VERBOSE} ||
      die "Documenting the ${PKG} package failed."
  fi
237

238
239
  ./Setup install ${SCOPE_OF_INSTALLATION} ${EXTRA_INSTALL_OPTS} ${VERBOSE} ||
     die "Installing the ${PKG} package failed."
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
}

do_pkg () {
  PKG=$1
  VER=$2
  VER_MATCH=$3

  if need_pkg ${PKG} ${VER_MATCH}
  then
    echo
    echo "Downloading ${PKG}-${VER}..."
    fetch_pkg ${PKG} ${VER}
    unpack_pkg ${PKG} ${VER}
    cd "${PKG}-${VER}"
    install_pkg ${PKG} ${VER}
    cd ..
  fi
}

# Actually do something!

261
262
info_pkg "deepseq"      ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
info_pkg "time"         ${TIME_VER}    ${TIME_VER_REGEXP}
263
info_pkg "Cabal"        ${CABAL_VER}   ${CABAL_VER_REGEXP}
264
265
info_pkg "transformers" ${TRANS_VER}   ${TRANS_VER_REGEXP}
info_pkg "mtl"          ${MTL_VER}     ${MTL_VER_REGEXP}
266
info_pkg "text"         ${TEXT_VER}    ${TEXT_VER_REGEXP}
267
268
269
270
info_pkg "parsec"       ${PARSEC_VER}  ${PARSEC_VER_REGEXP}
info_pkg "network"      ${NETWORK_VER} ${NETWORK_VER_REGEXP}
info_pkg "HTTP"         ${HTTP_VER}    ${HTTP_VER_REGEXP}
info_pkg "zlib"         ${ZLIB_VER}    ${ZLIB_VER_REGEXP}
271
info_pkg "random"       ${RANDOM_VER}  ${RANDOM_VER_REGEXP}
272
info_pkg "stm"          ${STM_VER}     ${STM_VER_REGEXP}
273

274
275
do_pkg   "deepseq"      ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
do_pkg   "time"         ${TIME_VER}    ${TIME_VER_REGEXP}
276
do_pkg   "Cabal"        ${CABAL_VER}   ${CABAL_VER_REGEXP}
277
278
do_pkg   "transformers" ${TRANS_VER}   ${TRANS_VER_REGEXP}
do_pkg   "mtl"          ${MTL_VER}     ${MTL_VER_REGEXP}
279
do_pkg   "text"         ${TEXT_VER}    ${TEXT_VER_REGEXP}
280
281
282
283
do_pkg   "parsec"       ${PARSEC_VER}  ${PARSEC_VER_REGEXP}
do_pkg   "network"      ${NETWORK_VER} ${NETWORK_VER_REGEXP}
do_pkg   "HTTP"         ${HTTP_VER}    ${HTTP_VER_REGEXP}
do_pkg   "zlib"         ${ZLIB_VER}    ${ZLIB_VER_REGEXP}
284
do_pkg   "random"       ${RANDOM_VER}  ${RANDOM_VER_REGEXP}
285
do_pkg   "stm"          ${STM_VER}     ${STM_VER_REGEXP}
286
287
288
289
290
291

install_pkg "cabal-install"

echo
echo "==========================================="
CABAL_BIN="$PREFIX/bin"
292
293
if [ -x "$CABAL_BIN/cabal" ]
then
294
295
296
297
    echo "The 'cabal' program has been installed in $CABAL_BIN/"
    echo "You should either add $CABAL_BIN to your PATH"
    echo "or copy the cabal program to a directory that is on your PATH."
    echo
298
299
300
301
302
    echo "The first thing to do is to get the latest list of packages with:"
    echo "  cabal update"
    echo "This will also create a default config file (if it does not already"
    echo "exist) at $HOME/.cabal/config"
    echo
303
    echo "By default cabal will install programs to $HOME/.cabal/bin"
304
305
    echo "If you do not want to add this directory to your PATH then you can"
    echo "change the setting in the config file, for example you could use:"
306
    echo "symlink-bindir: $HOME/bin"
307
308
else
    echo "Sorry, something went wrong."
309
310
    echo "The 'cabal' executable was not successfully installed into"
    echo "$CABAL_BIN/"
311
fi
Duncan Coutts's avatar
Duncan Coutts committed
312
echo
313
314

rm ghc-pkg.list