Skip to content

Commit 09a85ca

Browse files
committed
Add script for preparing the wasm libraries for building without Nix
1 parent e8e80af commit 09a85ca

1 file changed

Lines changed: 219 additions & 0 deletions

File tree

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#!/usr/bin/env bash
2+
# Build libsodium, libsecp256k1, and libblst for wasm32-wasi and install them
3+
# into a single prefix that cabal.project can point at via extra-lib-dirs /
4+
# extra-include-dirs. Mirrors ./nix/{libsodium,secp256k1,blst}.nix but uses
5+
# wasm32-wasi-clang directly (no Nix).
6+
#
7+
# Requirements on PATH: wasm32-wasi-clang (from wasi-sdk), autoreconf,
8+
# automake, libtool, make, git, pkg-config.
9+
10+
set -euo pipefail
11+
12+
# Script must be run from the root of the project
13+
PROJECT_DIR="$(pwd)"
14+
[ -f "$PROJECT_DIR/cabal.project" ] || {
15+
echo "Error: cabal.project not found in $PROJECT_DIR. Run this script from the root of the project" >&2
16+
exit 1
17+
}
18+
19+
missing=()
20+
[ -n "${PREFIX:-}" ] || missing+=(PREFIX)
21+
[ -n "${SRC_ROOT:-}" ] || missing+=(SRC_ROOT)
22+
if [ "${#missing[@]}" -gt 0 ]; then
23+
cat >&2 <<EOF
24+
Error: required environment variable(s) not set: ${missing[*]}
25+
26+
Both values are interpreted relative to the cabal.project directory
27+
($PROJECT_DIR) unless given as an absolute path.
28+
29+
PREFIX where the wasm libs/headers will be installed, e.g. wasm-libs.
30+
Will be created if missing. Point cabal.project's
31+
extra-lib-dirs / extra-include-dirs at \$PREFIX/lib and
32+
\$PREFIX/include.
33+
34+
SRC_ROOT where the libsodium / secp256k1 / blst source trees live (or
35+
will be cloned into as \$SRC_ROOT/{libsodium,secp256k1,blst}),
36+
e.g. wasm-deps.
37+
38+
Example:
39+
PREFIX=wasm-libs SRC_ROOT=wasm-libs-src $0
40+
EOF
41+
exit 1
42+
fi
43+
44+
resolve_rel() {
45+
case "$1" in
46+
/*) printf '%s\n' "$1" ;;
47+
*) printf '%s\n' "$PROJECT_DIR/$1" ;;
48+
esac
49+
}
50+
51+
ABS_PREFIX="$(resolve_rel "$PREFIX")"
52+
ABS_SRC_ROOT="$(resolve_rel "$SRC_ROOT")"
53+
54+
# Toolchain check: wasm32-wasi-clang must be on PATH (drives both compile and
55+
# link). The other wasm32-wasi-* tools come along with it via the wasi-sdk /
56+
# ghc-wasm env.
57+
toolchain_missing=()
58+
for t in wasm32-wasi-clang wasm-ld; do
59+
command -v "$t" >/dev/null 2>&1 || toolchain_missing+=("$t")
60+
done
61+
if [ "${#toolchain_missing[@]}" -gt 0 ]; then
62+
cat >&2 <<EOF
63+
Error: wasm toolchain not on PATH (missing: ${toolchain_missing[*]}).
64+
65+
The ghc-wasm / wasi-sdk environment doesn't appear to be active. Activate it
66+
with:
67+
68+
source ~/.ghc-wasm/env
69+
70+
then re-run this script.
71+
EOF
72+
exit 1
73+
fi
74+
75+
LIBSODIUM_REV="9511c982fb1d046470a8b42aa36556cdb7da15de"
76+
LIBSODIUM_REPO="https://github.com/jedisct1/libsodium.git"
77+
SECP256K1_REPO="https://github.com/bitcoin-core/secp256k1.git"
78+
BLST_REPO="https://github.com/supranational/blst.git"
79+
80+
mkdir -p "$ABS_PREFIX/lib" "$ABS_PREFIX/include" "$ABS_PREFIX/lib/pkgconfig"
81+
82+
clone_if_missing() {
83+
local repo="$1" dir="$2" rev="${3:-}"
84+
if [ ! -d "$dir/.git" ]; then
85+
git clone "$repo" "$dir"
86+
fi
87+
if [ -n "$rev" ]; then
88+
git -C "$dir" fetch --tags origin "$rev" 2>/dev/null || true
89+
git -C "$dir" checkout "$rev"
90+
fi
91+
}
92+
93+
build_libsodium() {
94+
local dir="$ABS_SRC_ROOT/libsodium"
95+
clone_if_missing "$LIBSODIUM_REPO" "$dir" "$LIBSODIUM_REV"
96+
cd "$dir"
97+
[ -x ./configure ] || ./autogen.sh -s
98+
./configure --host=wasm32-wasi --prefix="$ABS_PREFIX"
99+
make -j"$(nproc)"
100+
make install
101+
wasm32-wasi-clang -shared -Wl,--whole-archive \
102+
"$ABS_PREFIX/lib/libsodium.a" \
103+
-o "$ABS_PREFIX/lib/libsodium.so"
104+
}
105+
106+
build_secp256k1() {
107+
local dir="$ABS_SRC_ROOT/secp256k1"
108+
clone_if_missing "$SECP256K1_REPO" "$dir"
109+
cd "$dir"
110+
[ -x ./configure ] || ./autogen.sh
111+
./configure \
112+
--host=wasm32-wasi \
113+
--enable-module-schnorrsig \
114+
--prefix="$ABS_PREFIX" \
115+
SECP_CFLAGS=-fPIC
116+
make -j"$(nproc)"
117+
make install
118+
wasm32-wasi-clang -shared -Wl,--whole-archive \
119+
"$ABS_PREFIX/lib/libsecp256k1.a" \
120+
-o "$ABS_PREFIX/lib/libsecp256k1.so"
121+
}
122+
123+
build_blst() {
124+
local dir="$ABS_SRC_ROOT/blst"
125+
clone_if_missing "$BLST_REPO" "$dir"
126+
cd "$dir"
127+
CC=wasm32-wasi-clang ./build.sh
128+
129+
cp libblst.a "$ABS_PREFIX/lib/"
130+
cp bindings/blst.h bindings/blst_aux.h "$ABS_PREFIX/include/"
131+
132+
wasm32-wasi-clang -shared -Wl,--whole-archive \
133+
"$ABS_PREFIX/lib/libblst.a" \
134+
-o "$ABS_PREFIX/lib/libblst.so"
135+
136+
local version
137+
version="$(git -C "$dir" describe --tags --always 2>/dev/null || echo 0.0.0)"
138+
cat > "$ABS_PREFIX/lib/pkgconfig/libblst.pc" <<EOF
139+
prefix=$ABS_PREFIX
140+
exec_prefix=\${prefix}
141+
libdir=\${exec_prefix}/lib
142+
includedir=\${prefix}/include
143+
144+
Name: libblst
145+
Description: blst BLS12-381 signature library
146+
URL: https://github.com/supranational/blst
147+
Version: $version
148+
149+
Cflags: -I\${includedir}
150+
Libs: -L\${libdir} -lblst
151+
Libs.private:
152+
EOF
153+
}
154+
155+
verify_wasm() {
156+
local archive="$1"
157+
local tmp
158+
tmp="$(mktemp -d)"
159+
( cd "$tmp" && ar x "$archive" && \
160+
first_obj="$(ls *.o 2>/dev/null | head -1)" && \
161+
[ -n "$first_obj" ] && file "$first_obj" | grep -q WebAssembly )
162+
local rc=$?
163+
rm -rf "$tmp"
164+
if [ "$rc" -ne 0 ]; then
165+
echo "ERROR: $archive does not appear to contain wasm objects" >&2
166+
exit 1
167+
fi
168+
}
169+
170+
build_libsodium 2>&1 | sed -u $'s/^/\033[1;32mlibsodium\033[0m > /'
171+
build_secp256k1 2>&1 | sed -u $'s/^/\033[1;36msecp256k1\033[0m > /'
172+
build_blst 2>&1 | sed -u $'s/^/\033[1;33mblst\033[0m > /'
173+
174+
verify_wasm "$ABS_PREFIX/lib/libsodium.a"
175+
verify_wasm "$ABS_PREFIX/lib/libsecp256k1.a"
176+
verify_wasm "$ABS_PREFIX/lib/libblst.a"
177+
178+
echo
179+
echo "Done. Installed to: $ABS_PREFIX"
180+
181+
FRAGMENT="$PROJECT_DIR/wasm-libs-without-nix.cabal"
182+
cat > "$FRAGMENT" <<EOF
183+
shared: True
184+
185+
package cardano-crypto-class
186+
extra-lib-dirs: $ABS_PREFIX/lib
187+
extra-include-dirs: $ABS_PREFIX/include
188+
189+
package cardano-crypto-praos
190+
extra-lib-dirs: $ABS_PREFIX/lib
191+
extra-include-dirs: $ABS_PREFIX/include
192+
EOF
193+
echo "Wrote project fragment: $FRAGMENT"
194+
195+
CABAL_PROJECT="$PROJECT_DIR/cabal.project"
196+
197+
if grep -qF "wasm-libs-without-nix.cabal" "$CABAL_PROJECT"; then
198+
echo "cabal.project already imports wasm-libs-without-nix.cabal — nothing to do."
199+
else
200+
read -r -p "Add 'if arch(wasm32) / import: wasm-libs-without-nix.cabal' block to cabal.project? [y/N] " answer || answer=""
201+
case "${answer,,}" in
202+
y|yes)
203+
cat >> "$CABAL_PROJECT" <<'EOF'
204+
205+
if arch(wasm32)
206+
import: wasm-libs-without-nix.cabal
207+
EOF
208+
echo "Added to $CABAL_PROJECT"
209+
;;
210+
*)
211+
cat <<'EOF'
212+
Skipped. To enable, append to cabal.project:
213+
214+
if arch(wasm32)
215+
import: wasm-libs-without-nix.cabal
216+
EOF
217+
;;
218+
esac
219+
fi

0 commit comments

Comments
 (0)