bootstrap.sh 11.5 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
12
# Install settings, you can override these by setting environment vars. E.g. if
# you don't want profiling and dynamic versions of libraries to be installed in
# addition to vanilla, run 'EXTRA_CONFIGURE_OPTS="" ./bootstrap.sh'

13
#VERBOSE
14
15
DEFAULT_CONFIGURE_OPTS="--enable-library-profiling --enable-shared"
EXTRA_CONFIGURE_OPTS=${EXTRA_CONFIGURE_OPTS-$DEFAULT_CONFIGURE_OPTS}
16
17
#EXTRA_BUILD_OPTS
#EXTRA_INSTALL_OPTS
18

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

21
# programs, you can override these by setting environment vars
22
23
24
GHC="${GHC:-ghc}"
GHC_PKG="${GHC_PKG:-ghc-pkg}"
GHC_VER="$(${GHC} --numeric-version)"
25
HADDOCK=${HADDOCK:-haddock}
26
27
28
29
WGET="${WGET:-wget}"
CURL="${CURL:-curl}"
FETCH="${FETCH:-fetch}"
TAR="${TAR:-tar}"
30
GZIP_PROGRAM="${GZIP_PROGRAM:-gzip}"
31
32
33
34
35
36

# SCOPE_OF_INSTALLATION can be set on the command line to use/install
# the libaries needed to build cabal-install to a custom package
# database instead of the user or global package database
# e.g.
# ghc-pkg init /my/package/database
37
# SCOPE_OF_INSTALLATION='--package-db=/my/package/database' ./bootstrap.sh
38
39
40
#
# you can use this with PREFIX also, e.g.
# ghc-pkg init /my/prefix/packages.conf.d
41
# PREFIX=/my/prefix SCOPE_OF_INSTALLATION='--package-db=/my/prefix/packages.conf.d' ./bootstrap.sh
42
43
44
#
# if you use the --global or --user arguments, this will override the
# SCOPE_OF_INSTALLATION and not use a custom package database
45
SCOPE_OF_INSTALLATION="${SCOPE_OF_INSTALLATION:---user}"
46
DEFAULT_PREFIX="${HOME}/.cabal"
47

Geoff Nixon's avatar
Geoff Nixon committed
48
49
50
51
# 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

52
53
# Check for a C compiler.
[ ! -x "$CC" ] && for ccc in gcc clang cc icc; do
tuncer's avatar
tuncer committed
54
55
  ${ccc} --version > /dev/null 2>&1 && CC=$ccc &&
  echo "Using $CC for C compiler. If this is not what you want, set CC." >&2 &&
56
57
58
59
  break
done

# None found.
60
[ ! -x `which "$CC"` ] &&
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  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"
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
${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 "$@"
105
106
107
108
109
110
111
do
  case "${arg}" in
    "--user")
      SCOPE_OF_INSTALLATION=${arg}
      shift;;
    "--global")
      SCOPE_OF_INSTALLATION=${arg}
112
      DEFAULT_PREFIX="/usr/local"
113
      shift;;
114
115
116
    "--no-doc")
      NO_DOCUMENTATION=1
      shift;;
117
118
119
120
121
122
    *)
      echo "Unknown argument or option, quitting: ${arg}"
      echo "usage: bootstrap.sh [OPTION]"
      echo
      echo "options:"
      echo "   --user    Install for the local user (default)"
123
      echo "   --global  Install systemwide (must be run as root)"
124
      echo "   --no-doc  Do not generate documentation for installed packages"
125
126
127
      exit;;
  esac
done
128

129
130
131
132
133
134
# Check for haddock unless no documentation should be generated.
if [ ! ${NO_DOCUMENTATION} ]
then
  ${HADDOCK} --version     > /dev/null 2>&1  || die "${HADDOCK} not found."
fi

135
PREFIX=${PREFIX:-${DEFAULT_PREFIX}}
136
137
138

# Versions of the packages to install.
# The version regex says what existing installed versions are ok.
tuncer's avatar
tuncer committed
139
PARSEC_VER="3.1.6";    PARSEC_VER_REGEXP="[23]\."
140
141
142
                       # == 2.* || == 3.*
DEEPSEQ_VER="1.3.0.2"; DEEPSEQ_VER_REGEXP="1\.[1-9]\."
                       # >= 1.1 && < 2
tuncer's avatar
tuncer committed
143
144
145
146
TEXT_VER="1.2.0.0";    TEXT_VER_REGEXP="((1\.[012]\.)|(0\.([2-9]|(1[0-1]))\.))"
                       # >= 0.2 && < 1.3
NETWORK_VER="2.6.0.2"; NETWORK_VER_REGEXP="2\.[0-6]\."
                       # >= 2.0 && < 2.7
tuncer's avatar
tuncer committed
147
NETWORK_URI_VER="2.6.0.1"; NETWORK_URI_VER_REGEXP="2\.[0-6]\."
tuncer's avatar
tuncer committed
148
                       # >= 2.0 && < 2.7
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
149
150
CABAL_VER="1.21.1.0";  CABAL_VER_REGEXP="1\.21\.1"
                       # >= 1.21.1 && < 1.22
151
152
TRANS_VER="0.3.0.0";   TRANS_VER_REGEXP="0\.[23]\."
                       # >= 0.2.* && < 0.4.*
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
153
MTL_VER="2.1.3.1";     MTL_VER_REGEXP="[2]\."
154
                       #  == 2.*
tuncer's avatar
tuncer committed
155
HTTP_VER="4000.2.18";  HTTP_VER_REGEXP="4000\.2\.([5-9]|1[0-9]|2[0-9])"
tibbe's avatar
tibbe committed
156
                       # >= 4000.2.5 < 4000.3
157
158
ZLIB_VER="0.5.4.1";    ZLIB_VER_REGEXP="0\.[45]\."
                       # == 0.4.* || == 0.5.*
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
159
TIME_VER="1.4.2"       TIME_VER_REGEXP="1\.[1234]\.?"
160
                       # >= 1.1 && < 1.5
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
161
162
RANDOM_VER="1.1"       RANDOM_VER_REGEXP="1\.[01]\.?"
                       # >= 1 && < 1.2
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
163
STM_VER="2.4.3";       STM_VER_REGEXP="2\."
164
                       # == 2.*
Duncan Coutts's avatar
Duncan Coutts committed
165

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

168
# Cache the list of packages:
169
echo "Checking installed packages for ghc-${GHC_VER}..."
170
171
${GHC_PKG} list --global ${SCOPE_OF_INSTALLATION} > ghc-pkg.list ||
  die "running '${GHC_PKG} list' failed"
172
173
174
175
176

# Will we need to install this package, or is a suitable version installed?
need_pkg () {
  PKG=$1
  VER_MATCH=$2
177
  if egrep " ${PKG}-${VER_MATCH}" ghc-pkg.list > /dev/null 2>&1
178
179
180
181
182
183
  then
    return 1;
  else
    return 0;
  fi
  #Note: we cannot use "! grep" here as Solaris 9 /bin/sh doesn't like it.
184
185
186
187
188
189
190
191
192
}

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

  if need_pkg ${PKG} ${VER_MATCH}
  then
193
194
195
196
197
198
    if [ -f "${PKG}-${VER}.tar.gz" ]
    then
        echo "${PKG}-${VER} will be installed from local tarball."
    else
        echo "${PKG}-${VER} will be downloaded and installed."
    fi
199
200
201
202
203
204
205
206
207
  else
    echo "${PKG} is already installed and the version is ok."
  fi
}

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

208
  URL=${HACKAGE_URL}/${PKG}-${VER}/${PKG}-${VER}.tar.gz
209
210
  if which ${CURL} > /dev/null
  then
tuncer's avatar
tuncer committed
211
212
213
    # 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}."
214
    ${CURL} -L --fail -O ${URL} || die "Failed to download ${PKG}."
215
216
  elif which ${WGET} > /dev/null
  then
217
    ${WGET} -c ${URL} || die "Failed to download ${PKG}."
218
  elif which ${FETCH} > /dev/null
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
219
220
    then
      ${FETCH} ${URL} || die "Failed to download ${PKG}."
221
  else
222
    die "Failed to find a downloader. 'curl', 'wget' or 'fetch' is required."
223
  fi
224
225
  [ -f "${PKG}-${VER}.tar.gz" ] ||
     die "Downloading ${URL} did not create ${PKG}-${VER}.tar.gz"
226
227
228
229
230
231
}

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

232
  rm -rf "${PKG}-${VER}.tar" "${PKG}-${VER}"
233
  ${GZIP_PROGRAM} -d < "${PKG}-${VER}.tar.gz" | ${TAR} -xf -
234
  [ -d "${PKG}-${VER}" ] || die "Failed to unpack ${PKG}-${VER}.tar.gz"
235
236
237
238
239
}

install_pkg () {
  PKG=$1

240
241
242
  [ -x Setup ] && ./Setup clean
  [ -f Setup ] && rm Setup

243
244
245
  ${GHC} --make Setup -o Setup ||
    die "Compiling the Setup script failed."

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

248
249
250
251
252
  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."
253

254
255
  ./Setup build ${EXTRA_BUILD_OPTS} ${VERBOSE} ||
     die "Building the ${PKG} package failed."
256

257
258
259
260
261
  if [ ! ${NO_DOCUMENTATION} ]
  then
    ./Setup haddock --with-ghc=${GHC} --with-haddock=${HADDOCK} ${VERBOSE} ||
      die "Documenting the ${PKG} package failed."
  fi
262

263
  ./Setup install ${EXTRA_INSTALL_OPTS} ${VERBOSE} ||
264
     die "Installing the ${PKG} package failed."
265
266
267
268
269
270
271
272
273
274
}

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

  if need_pkg ${PKG} ${VER_MATCH}
  then
    echo
275
276
277
278
279
280
281
    if [ -f "${PKG}-${VER}.tar.gz" ]
    then
        echo "Using local tarball for ${PKG}-${VER}"
    else
        echo "Downloading ${PKG}-${VER}..."
        fetch_pkg ${PKG} ${VER}
    fi
282
283
284
285
286
287
288
289
290
    unpack_pkg ${PKG} ${VER}
    cd "${PKG}-${VER}"
    install_pkg ${PKG} ${VER}
    cd ..
  fi
}

# Actually do something!

291
292
info_pkg "deepseq"      ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
info_pkg "time"         ${TIME_VER}    ${TIME_VER_REGEXP}
293
info_pkg "Cabal"        ${CABAL_VER}   ${CABAL_VER_REGEXP}
294
295
info_pkg "transformers" ${TRANS_VER}   ${TRANS_VER_REGEXP}
info_pkg "mtl"          ${MTL_VER}     ${MTL_VER_REGEXP}
296
info_pkg "text"         ${TEXT_VER}    ${TEXT_VER_REGEXP}
297
298
info_pkg "parsec"       ${PARSEC_VER}  ${PARSEC_VER_REGEXP}
info_pkg "network"      ${NETWORK_VER} ${NETWORK_VER_REGEXP}
tuncer's avatar
tuncer committed
299
info_pkg "network-uri"  ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
300
301
info_pkg "HTTP"         ${HTTP_VER}    ${HTTP_VER_REGEXP}
info_pkg "zlib"         ${ZLIB_VER}    ${ZLIB_VER_REGEXP}
302
info_pkg "random"       ${RANDOM_VER}  ${RANDOM_VER_REGEXP}
303
info_pkg "stm"          ${STM_VER}     ${STM_VER_REGEXP}
304

305
306
do_pkg   "deepseq"      ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
do_pkg   "time"         ${TIME_VER}    ${TIME_VER_REGEXP}
307
do_pkg   "Cabal"        ${CABAL_VER}   ${CABAL_VER_REGEXP}
308
309
do_pkg   "transformers" ${TRANS_VER}   ${TRANS_VER_REGEXP}
do_pkg   "mtl"          ${MTL_VER}     ${MTL_VER_REGEXP}
310
do_pkg   "text"         ${TEXT_VER}    ${TEXT_VER_REGEXP}
311
312
do_pkg   "parsec"       ${PARSEC_VER}  ${PARSEC_VER_REGEXP}
do_pkg   "network"      ${NETWORK_VER} ${NETWORK_VER_REGEXP}
tuncer's avatar
tuncer committed
313
do_pkg   "network-uri"  ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
314
315
do_pkg   "HTTP"         ${HTTP_VER}    ${HTTP_VER_REGEXP}
do_pkg   "zlib"         ${ZLIB_VER}    ${ZLIB_VER_REGEXP}
316
do_pkg   "random"       ${RANDOM_VER}  ${RANDOM_VER_REGEXP}
317
do_pkg   "stm"          ${STM_VER}     ${STM_VER_REGEXP}
318
319
320
321
322
323

install_pkg "cabal-install"

echo
echo "==========================================="
CABAL_BIN="$PREFIX/bin"
324
325
if [ -x "$CABAL_BIN/cabal" ]
then
326
327
328
329
    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
330
331
332
333
334
    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
335
    echo "By default cabal will install programs to $HOME/.cabal/bin"
336
337
    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:"
338
    echo "symlink-bindir: $HOME/bin"
339
340
else
    echo "Sorry, something went wrong."
341
342
    echo "The 'cabal' executable was not successfully installed into"
    echo "$CABAL_BIN/"
343
fi
Duncan Coutts's avatar
Duncan Coutts committed
344
echo
345
346

rm ghc-pkg.list