Created
November 10, 2015 13:38
-
-
Save johnjcamilleri/1ed5db5eb4bd26a97afb to your computer and use it in GitHub Desktop.
activate-hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
quiet=no | |
verbose=no | |
dryrun=no | |
list=no | |
version="" # forgiving user input version | |
hpVersion="" # like "2014.2.0.0" | |
ghcVersion="" # like "7.8.3" | |
arch="" # "i386" or "x86_64" | |
hpDirname="" # "2014.2.0.0-x86_64" or older form "ghc-7.6.3" | |
ghcDirname="" # "7.8.3-x86_64" | |
hpInstallDir="/Library/Haskell" | |
ghcInstallDir="/Library/Frameworks/GHC.framework/Versions" | |
msg="" | |
findItems() { | |
( cd "$1" && ls -d -1 ${2:-*} ) 2>/dev/null | |
} | |
### | |
### Version and Arch Mechanics | |
### | |
extractVersions() { | |
# takes a very liberal set of formats, and figures out the version info: | |
# ver ghc version | |
# ver-arch ghc version and arch, also dirname in GHC installs | |
# and newer HP installs | |
# ghc-ver dirnames used in older HP installs | |
# in each case, ver can be x.y or x.y.z | |
hpVersion="" | |
ghcVersion="" | |
arch="" | |
msg="" | |
input="${1#ghc-}" # remove ghc- prefix if present | |
case "$input" in | |
*-*) arch="${input#*-}" | |
input="${input%-*}" | |
;; | |
esac | |
case "$input" in | |
7.6.3) ghcVersion="$input" ; hpVersion="2013.2.0.0" ;; | |
7.4.2) ghcVersion="$input" ; hpVersion="2012.4.0.0" ;; | |
7.4.1) ghcVersion="$input" ; hpVersion="2012.2.0.0" ;; | |
7.0.4) ghcVersion="$input" ; hpVersion="2011.4.0.0" ;; | |
7.0.3) ghcVersion="$input" ; hpVersion="2011.2.0.0" ;; | |
[67].*) ghcVersion="$input" ;; | |
*) msg="Can't parse $input as a GHC version" | |
return 1 | |
;; | |
esac | |
# see if there is an installed version w/bigger number | |
for d in $( findItems "$ghcInstallDir" "$ghcVersion"'*' ) ; do | |
ghcVersion="${d%-*}" # last one will be highest! | |
ghcArch="${d#*-}" | |
done | |
if [ -z "$arch" ] ; then | |
arch="${ghcArch}" | |
fi | |
if [ -z "$arch" ] ; then | |
msg="Can't determine architecture, please specify one (i386 or x86_64)" | |
return 1 | |
fi | |
ghcDirname="$ghcVersion-$arch" | |
ghcRoot="$ghcInstallDir/$ghcDirname" | |
if [ \! -d "$ghcRoot" ] ; then | |
msg="GHC $ghcVersion $arch not found in $ghcInstallDir" | |
return 1 | |
fi | |
# see if there is an installed platform to match | |
if [ -d "$hpInstallDir/ghc-$ghcVersion" ] ; then | |
# old style platform install | |
hpDirname="ghc-$ghcVersion" | |
hpRoot="$hpInstallDir/$hpDirname" | |
for r in $( findItems "$hpRoot/lib/registrations" 'haskell-platform-*.conf' ) ; do | |
q="${r#haskell-platform-}" | |
hpVersion="${q%.conf}" | |
done | |
elif [ -d "$hpInstallDir/ghc-$ghcVersion-$arch" ] ; then | |
# new style platform install | |
hpDirname="ghc-$ghcVersion-$arch" | |
hpRoot="$hpInstallDir/$hpDirname" | |
for v in $( findItems "$hpRoot" 'version-*' ) ; do | |
hpVersion="${v#version-}" | |
done | |
else | |
hpVersion="--none--" | |
hpDirname="" | |
hpRoot="" | |
fi | |
return 0 | |
} | |
### | |
### Decode arguments | |
### | |
usage() { | |
echo "$0 -l" | |
echo "$0 [-q | -v] [-n] [ version [ arch ] ]" | |
echo " -l | --list just list installed versions" | |
echo " -q | --quiet supress informational output" | |
echo " -v | --verbose print actions as they are taken" | |
echo " -n | --dryrun don't actually do anything (implies -v)" | |
echo "" | |
echo " version ex. 7.8.3, defaults to latest" | |
echo " arch i386 or x86_64, defaults to what's installed" | |
} | |
originalArgs="$*" | |
while [ $# -gt 0 ] | |
do | |
case "$1" in | |
-l|--list) list=yes ;; | |
-q|--quiet) quiet=yes ; verbose=no ;; | |
-v|--verbose) quiet=no ; verbose=yes ;; | |
-n|--dryrun) dryrun=yes ;; | |
-f|--force) force=yes ;; | |
-\?|--help) usage ; exit 0 ;; | |
-*) echo "Unknown flag $1" ; usage ; exit 1 ;; | |
*) if [ -z "$version" ] ; then | |
version="$1" | |
elif [ -z "$arch" ] ; then | |
arch="$1" | |
else | |
echo "Too many non-option arguments" ; usage ; exit 1 | |
fi | |
;; | |
esac | |
shift | |
done | |
if [ "$list" = "yes" ] ; then | |
for version in $( findItems "$ghcInstallDir" ) ; do | |
if extractVersions $version ; then | |
if [ -n "$hpRoot" ] ; then | |
echo "$ghcVersion-$arch - with platform $hpVersion" | |
if [ "$verbose" = "yes" ] ; then | |
echo " ghc at $ghcRoot" | |
echo " platform at $hpRoot" | |
fi | |
else | |
echo "$ghcVersion $arch - no platform" | |
if [ "$verbose" = "yes" ] ; then | |
echo " ghc at $ghcRoot" | |
fi | |
fi | |
fi | |
done | |
exit 0 | |
fi | |
### | |
### Validate haskell platform version | |
### | |
if [ -z "$version" ] ; then | |
version=$( ( for d in $( findItems "$ghcInstallDir" ) ; \ | |
do extractVersions "$d" && echo "$ghcVersion" ; \ | |
done ) \ | |
| sort -t '.' -n | tail -1 ) | |
fi | |
if extractVersions $version ; then | |
ok="yes" | |
else | |
if [ -z "$version" ] ; then | |
echo "No GHC or Platform versions installed in /Library" | |
else | |
echo "$msg" | |
fi | |
exit 1 | |
fi | |
if [ \! -d "$hpRoot" -a "$quiet" = "no" ] ; then | |
echo "Warning: No corresponding Haskell Platform found" | |
fi | |
### | |
### Check for Xcode command line tools | |
### | |
if [ \! \( -f /usr/bin/gcc -a -x /usr/bin/gcc \) ] ; then | |
echo "There is no compiler installed at /usr/bin/gcc" | |
echo "Install Xcode's command line tools, or another compiler tool chain." | |
exit 1 | |
fi | |
### | |
### Root check | |
### | |
if [ "$dryrun" = "no" -a `id -u` -ne 0 ] | |
then | |
echo "You must be root to activate a particular Haskell Platform." | |
echo "Please rerun this command sudo:" | |
echo " sudo $0 $originalArgs" | |
exit 1 | |
fi | |
### | |
### Get ready to actually do stuff | |
### | |
if [ "$dryrun" = "yes" -a "$verbose" = "yes" ] ; then | |
echo "Dry run mode enabled, would have run the following commands:" | |
fi | |
run() { | |
if [ "$verbose" = "yes" ] ; then | |
echo " $*" | |
fi | |
if [ "$dryrun" = "no" ] ; then | |
"$@" | |
fi | |
} | |
symLink() { | |
run rm -rf "$2" | |
run ln -sf "$1" "$2" | |
} | |
symLinkInto() { | |
run ln -sf "$@" | |
} | |
### | |
### Fix up bits in platform tree | |
### | |
if [ -d "$hpRoot" ] ; then | |
if [ -x $hpRoot/bin/cabal.wrap ] | |
then | |
run mv $hpRoot/bin/cabal $hpRoot/bin/cabal.real | |
symLink cabal.wrap $hpRoot/bin/cabal | |
fi | |
symLink $ghcRoot/usr/share/doc/ghc/html $hpRoot/doc/ghc-doc | |
symLink $ghcRoot/usr/share/doc/ghc/html/libraries/ghc-$ghcVersion $hpRoot/doc/ghc-api | |
fi | |
### | |
### Repoint current links | |
### | |
symLink $ghcDirname /Library/Frameworks/GHC.framework/Versions/Current | |
if [ -d "$hpRoot" ] ; then | |
symLink $hpDirname /Library/Haskell/current | |
symLink current/bin /Library/Haskell/bin | |
symLink current/doc /Library/Haskell/doc | |
fi | |
### | |
### Set up /usr | |
### | |
symLinkInto $ghcRoot/usr/bin/* /usr/local/bin | |
symLinkInto $ghcRoot/usr/share/man/man1/* /usr/local/share/man/man1 | |
symLinkInto $ghcRoot/usr/share/doc/ghc /usr/local/share/doc | |
if [ -d "$hpRoot" ] ; then | |
symLinkInto $hpRoot/bin/* /usr/local/bin | |
fi | |
### | |
### Patch settings file | |
extractSetting() { | |
sed -n -e "/$1/"'s/.*, *"\(.*\)").*/\1/p' $settingsFile | |
} | |
updateSetting() { | |
run sed -e "/$1/"'s/, *".*"/, "'"$2"'"/' -i '.bak' $settingsFile | |
} | |
determineCompiler() { | |
case "$( "$1" --version 2>/dev/null )" in | |
*clang*) echo clang ;; | |
*gcc*) echo gcc ;; | |
*cpphs*) echo cpphs ;; | |
*) echo unknown ;; | |
esac | |
} | |
settingsFile="$ghcRoot/usr/lib/ghc-$ghcVersion/settings" | |
if [ -f "$settingsFile" ] ; then | |
if grep -q '"Haskell CPP flags"' "$settingsFile" ; then | |
cmd=$( extractSetting "Haskell CPP command" ) | |
case "$( determineCompiler $cmd )" in | |
clang) cppArgs="-E -undef -traditional -Wno-invalid-pp-token -Wno-unicode -Wno-trigraphs" ;; | |
gcc) cppArgs="-E -undef -traditional" ;; | |
hscpp) cppArgs="--cpp -traditional" ;; | |
*) if [ "$quiet" = "no" ] ; then | |
echo "Unrecgonized Haskell CPP command $cmd" | |
echo "Leaving Haskell CPP flags unchanged in settings" | |
fi | |
;; | |
esac | |
if [ -n "$cppArgs" ] ; then | |
updateSetting "Haskell CPP flags" "$cppArgs" | |
fi | |
else | |
cmd=$( extractSetting "C compiler command" ) | |
if [ "$( determineCompiler $cmd )" = "clang" ] ; then | |
wrapperCmd=/usr/bin/ghc-clang-wrapper | |
if [ -f "$wrapperCmd" -a -e "$wrapperCmd" ] ; then | |
updateSetting "C compiler command" "$wrapperCmd" | |
else | |
echo "The compiler is clang, but $wrapperCmd isn't installed" | |
echo "Older GHCs may not work unless this is installed" | |
echo "Install $wrapperCmd and re-run this script" | |
fi | |
fi | |
fi | |
else | |
if [ "$( determineCompiler /usr/bin/gcc )" = "clang" ] ; then | |
echo "The compiler is clang, but ghc $ghcVersion is old" | |
echo "and has no settings file to change the compiler." | |
echo "There is no simple work around." | |
fi | |
fi | |
### | |
### Register platform packages | |
### | |
if [ -d "$hpRoot" ] ; then | |
for conf in $hpRoot/lib/registrations/* | |
do | |
run /usr/bin/ghc-pkg register --verbose=0 --force $conf 2>/dev/null | |
done | |
fi | |
### | |
### Report | |
### | |
if [ "$quiet" = "no" ] ; then | |
if [ "$dryrun" = "no" ] ; then | |
verb="now set to" | |
else | |
verb="would be set to" | |
fi | |
echo | |
echo "Haskell $verb:" | |
echo " GHC $ghcVersion" | |
echo " Arch. $arch" | |
echo " Platform $hpVersion" | |
if [ "$dryrun" = "no" ] ; then | |
echo "" | |
echo "View documentation with this command:" | |
echo " open /Library/Haskell/doc/start.html" | |
fi | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment