Skip to content

Commit 6259067

Browse files
committed
Refactor wrapper.in and make it more robust on Darwin
1 parent 17b66dc commit 6259067

File tree

1 file changed

+146
-68
lines changed

1 file changed

+146
-68
lines changed

bindist/wrapper.in

Lines changed: 146 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,90 +5,168 @@ executablename="@@EXE_NAME@@"
55
GHC_VERSION="@@GHC_VERSION@@"
66
ABI_HASHES="@@ABI_HASHES@@"
77

8-
fail_ghc_pkg() {
9-
echo >&2 "Could not find a ghc-pkg binary (found: $1)!"
10-
echo >&2 "Your GHC installation may be borked."
11-
echo >&2 "Consider installing GHC via ghcup or compile HLS from source."
12-
echo >&2 "exiting..."
13-
exit 42
8+
debug_msg() {
9+
if [ -n "$HLS_WRAPPER_DEBUG" ] ; then
10+
echo >&2 "$1"
11+
fi
1412
}
1513

16-
fail_libdir() {
17-
echo >&2 "Could not find a GHC installation!"
18-
echo >&2 "Consider setting GHC_LIBDIR env variable to the top-level directory of GHC shipped libraries (version ${GHC_VERSION})."
19-
echo >&2 "This is needed to find dynamic libraries."
20-
echo >&2 "exiting..."
21-
exit 42
14+
err_ghc_pkg() {
15+
debug_msg >&2 "Could not find a ghc-pkg binary (found: $1)!"
16+
debug_msg >&2 "Trying other methods..."
2217
}
2318

24-
fail_abi() {
25-
echo >&2 "GHC ABIs don't match!"
26-
echo >&2 "This means you're running an incompatible GHC and HLS won't work correctly."
27-
echo >&2 "Consider installing GHC via ghcup or compile HLS from source."
28-
echo >&2 ""
29-
echo >&2 "Expected: ${ABI_HASHES}"
30-
echo >&2 "Got: $1"
31-
echo >&2 "exiting..."
32-
exit 42
19+
err_abi() {
20+
debug_msg >&2 "GHC ABIs don't match!"
21+
debug_msg >&2 ""
22+
debug_msg >&2 "Expected: ${ABI_HASHES}"
23+
debug_msg >&2 "Got: $1"
24+
debug_msg >&2 "Trying other methods..."
3325
}
3426

35-
# try GHC_LIBDIR from the environment (e.g. user set it)
36-
if [ -n "${GHC_LIBDIR}" ] ; then
37-
:
38-
# try hls-wrapper --print-libdir
39-
elif "${exedir}"/haskell-language-server-wrapper --version >/dev/null 2>/dev/null ; then
40-
GHC_LIBDIR="$("${exedir}"/haskell-language-server-wrapper --print-libdir)" || unset GHC_LIBDIR
41-
fi
27+
err_ver() {
28+
debug_msg >&2 "GHC versions don't match!"
29+
debug_msg >&2 ""
30+
debug_msg >&2 "Expected: ${GHC_VERSION}"
31+
debug_msg >&2 "Got: $1"
32+
debug_msg >&2 "Trying other methods..."
33+
}
4234

43-
if [ -z "${GHC_LIBDIR}" ] ; then
44-
# try ghcup, if available
45-
if command -v ghcup >/dev/null ; then
46-
GHC_LIBDIR="$(ghcup whereis -d ghc ${GHC_VERSION})/../lib/ghc-${GHC_VERSION}/" || unset GHC_LIBDIR
47-
fi
48-
fi
35+
# Check the version of GHC and the ABI.
36+
check_ghc() {
37+
{ [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ] ;} && debug_msg "internal error: not enough arguments to check_ghc: 1:$1,2:$2,3:$3,4:$4" && return 4
38+
39+
debug_msg >&2 "Trying method $4"
4940

50-
# if above failed, try to examine ghc in PATH
51-
if [ -z "${GHC_LIBDIR}" ] ; then
52-
if [ -n "${GHC_BIN}" ] && command -v "${GHC_BIN}" >/dev/null ; then
53-
ghc_bin=${GHC_BIN}
54-
elif command -v ghc-${GHC_VERSION} >/dev/null ; then
55-
ghc_bin=ghc-${GHC_VERSION}
56-
elif command -v ghc >/dev/null ; then
57-
ghc_bin=ghc
41+
check_ghc_libdir=$1
42+
check_ghc_bin=$2
43+
GHC_PKG=$3
44+
check_ghc_ver="$("${check_ghc_bin}" --numeric-version 2>/dev/null)"
45+
46+
# check version
47+
if [ "${check_ghc_ver}" = "${GHC_VERSION}" ] ; then
48+
# check ABI
49+
if "${GHC_PKG}" --version >/dev/null ; then
50+
:
51+
elif "${GHC_PKG}-${GHC_VERSION}" --version >/dev/null ; then
52+
GHC_PKG=${GHC_PKG}-${GHC_VERSION}
53+
else
54+
err_ghc_pkg "${GHC_PKG}"
55+
unset GHC_LIBDIR
56+
return 1
57+
fi
58+
PKGCONF="${check_ghc_libdir}/package.conf.d"
59+
MY_ABI_HASHES="$(for dep in $("${GHC_PKG}" --global --global-package-db "$PKGCONF" list --simple-output) ; do "${GHC_PKG}" --global --global-package-db "$PKGCONF" field "${dep}" abi --simple-output ; done | tr '\n' ' ' | xargs)"
60+
if [ "${ABI_HASHES}" != "${MY_ABI_HASHES}" ] ; then
61+
err_abi "${MY_ABI_HASHES}"
62+
return 3
63+
fi
64+
unset PKGCONF
5865
else
59-
fail_libdir
66+
err_ver "${check_ghc_ver}"
67+
unset GHC_LIBDIR
68+
return 2
6069
fi
6170

62-
GHC_LIBDIR=$(${ghc_bin} --print-libdir)
63-
ghc_ver="$(${ghc_bin} --numeric-version)"
64-
if [ "${GHC_VERSION}" != "${ghc_ver}" ] ; then
65-
echo >&2 "Need GHC version ${GHC_VERSION}, got ${ghc_ver}... trying anyway"
71+
unset check_ghc_libdir check_ghc_bindir GHC_PKG check_ghc_ver
72+
}
73+
74+
# Infer ghc-pkg from the given ghc path. Doesn't check for existence of any
75+
# components.
76+
infer_ghc_pkg() {
77+
infer_ghc_path=$1
78+
infer_ghc_bin=${infer_ghc_path##**/}
79+
infer_ghc_ver_suffix=${infer_ghc_bin#ghc}
80+
path_prefix="$(dirname "${infer_ghc_path}")"
81+
82+
if [ "${path_prefix}" = "." ] ; then
83+
echo "ghc-pkg${infer_ghc_ver_suffix}"
84+
elif [ "${path_prefix}" = "/" ] ; then
85+
echo "${path_prefix}ghc-pkg${infer_ghc_ver_suffix}"
86+
else
87+
echo "${path_prefix}/ghc-pkg${infer_ghc_ver_suffix}"
6688
fi
67-
unset ghc_ver ghc_bin
68-
fi
89+
unset infer_ghc_path infer_ghc_bin infer_ghc_ver_suffix path_prefix
90+
}
6991

70-
if [ -z "${GHC_LIBDIR}" ] ; then
71-
fail_libdir
72-
fi
92+
# Get the bin dir from GHCs internal libdir. This is wobbly.
93+
ghc_bin_from_libdir() {
94+
if [ -e "$1"/bin/ghc ] ; then
95+
echo "$1"/bin/ghc
96+
elif [ -e "$1"/bin/ghc-${GHC_VERSION} ] ; then
97+
echo "$1"/bin/ghc-${GHC_VERSION}
98+
elif [ -e "$1"/../bin/ghc ] ; then
99+
echo "$1"/../bin/ghc
100+
elif [ -e "$1"/../bin/ghc-${GHC_VERSION} ] ; then
101+
echo "$1"/../bin/ghc-${GHC_VERSION}
102+
fi
103+
}
73104

74-
# check abi
75-
GHC_PKG="${GHC_LIBDIR}"/bin/ghc-pkg
76-
if "${GHC_PKG}" --version >/dev/null ; then
105+
# try GHC_LIBDIR from the environment (e.g. user set it)
106+
if [ -n "${GHC_LIBDIR}" ] &&
107+
check_ghc "${GHC_LIBDIR}" "$(ghc_bin_from_libdir "${GHC_LIBDIR}")" "$(infer_ghc_pkg "$(ghc_bin_from_libdir "${GHC_LIBDIR}")")" "GHC_LIBDIR"
108+
then
109+
:
110+
# try GHC_BIN from the environment (e.g. user set it)
111+
elif [ -n "${GHC_BIN}" ] &&
112+
GHC_LIBDIR="$("${GHC_BIN}" --print-libdir)" &&
113+
check_ghc "${GHC_LIBDIR}" "${GHC_BIN}" "$(infer_ghc_pkg "${GHC_BIN}")" "GHC_BIN"
114+
then
115+
:
116+
# try ghcup
117+
elif command -v ghcup >/dev/null &&
118+
GHC_BIN="$(ghcup whereis ghc "${GHC_VERSION}")" &&
119+
GHC_LIBDIR="$("${GHC_BIN}" --print-libdir)" &&
120+
check_ghc "${GHC_LIBDIR}" "${GHC_BIN}" "$(infer_ghc_pkg "${GHC_BIN}")" "ghcup"
121+
then
122+
:
123+
# try ghc-${GHC_VERSION}
124+
elif command -v ghc-${GHC_VERSION} >/dev/null &&
125+
GHC_LIBDIR="$("ghc-${GHC_VERSION}" --print-libdir)" &&
126+
check_ghc "${GHC_LIBDIR}" "ghc-${GHC_VERSION}" "$(infer_ghc_pkg "ghc-${GHC_VERSION}")" "ghc-<ver>"
127+
then
128+
:
129+
# try ghc
130+
elif command -v ghc >/dev/null &&
131+
GHC_LIBDIR="$(ghc --print-libdir)" &&
132+
check_ghc "${GHC_LIBDIR}" "ghc" "$(infer_ghc_pkg "ghc")" "ghc"
133+
then
134+
:
135+
# try stack
136+
elif command -v stack >/dev/null &&
137+
GHC_BIN="$(cd "$(mktemp -d)" && stack --install-ghc --resolver "ghc-${GHC_VERSION}" exec sh -- -c 'command -v ghc')" &&
138+
GHC_LIBDIR="$("${GHC_BIN}" --print-libdir)" &&
139+
check_ghc "${GHC_LIBDIR}" "${GHC_BIN}" "$(infer_ghc_pkg "${GHC_BIN}")" "stack"
140+
then
77141
:
78142
else
79-
fail_ghc_pkg "${GHC_PKG}"
80-
fi
81-
PKGCONF="${GHC_LIBDIR}/package.conf.d"
82-
MY_ABI_HASHES="$(for dep in $("${GHC_PKG}" --global --global-package-db "$PKGCONF" list --simple-output) ; do "${GHC_PKG}" --global --global-package-db "$PKGCONF" field "${dep}" abi --simple-output ; done | tr '\n' ' ' | xargs)"
83-
[ "${ABI_HASHES}" = "${MY_ABI_HASHES}" ] || fail_abi "${MY_ABI_HASHES}"
84-
unset PKGCONF
85-
86-
if [ -n "$LD_LIBRARY_PATH" ] ; then
87-
LD_LIBRARY_PATH="$(for i in "${GHC_LIBDIR}"/* ; do [ -d "$i" ] && printf "%s" "$i:" ; done)$LD_LIBRARY_PATH"
88-
export LD_LIBRARY_PATH
89-
else
90-
LD_LIBRARY_PATH="$(for i in "${GHC_LIBDIR}"/* ; do [ -d "$i" ] && printf "%s" "$i:" ; done | sed 's/:$//')"
91-
export LD_LIBRARY_PATH
143+
echo >&2 "All methods exhausted!"
144+
echo >&2 "Couldn't find a working/matching GHC installation"
145+
echo >&2 "exiting..."
146+
exit 42
92147
fi
93148

149+
debug_msg "Found GHC libdir at: ${GHC_LIBDIR}"
150+
151+
case "$(uname -s)" in
152+
"Darwin"|"darwin")
153+
if [ -n "$DYLD_LIBRARY_PATH" ] ; then
154+
DYLD_LIBRARY_PATH="$(for i in "${GHC_LIBDIR}"/* ; do [ -d "$i" ] && printf "%s" "$i:" ; done)$DYLD_LIBRARY_PATH"
155+
export DYLD_LIBRARY_PATH
156+
else
157+
DYLD_LIBRARY_PATH="$(for i in "${GHC_LIBDIR}"/* ; do [ -d "$i" ] && printf "%s" "$i:" ; done | sed 's/:$//')"
158+
export DYLD_LIBRARY_PATH
159+
fi
160+
;;
161+
*)
162+
if [ -n "$LD_LIBRARY_PATH" ] ; then
163+
LD_LIBRARY_PATH="$(for i in "${GHC_LIBDIR}"/* ; do [ -d "$i" ] && printf "%s" "$i:" ; done)$LD_LIBRARY_PATH"
164+
export LD_LIBRARY_PATH
165+
else
166+
LD_LIBRARY_PATH="$(for i in "${GHC_LIBDIR}"/* ; do [ -d "$i" ] && printf "%s" "$i:" ; done | sed 's/:$//')"
167+
export LD_LIBRARY_PATH
168+
fi
169+
;;
170+
esac
171+
94172
exec "${exedir}/${executablename}" ${1+"$@"}

0 commit comments

Comments
 (0)