Avoid absolute path hack
This commit is contained in:
parent
25875c7dc1
commit
ddc8b9097d
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
dist*
|
dist*
|
||||||
result
|
result
|
||||||
target
|
target
|
||||||
|
cabal.project.local*
|
||||||
|
|||||||
@ -1,13 +1,5 @@
|
|||||||
packages: .
|
packages: .
|
||||||
|
|
||||||
-- TODO a total hack
|
|
||||||
package garnet
|
|
||||||
extra-lib-dirs:
|
|
||||||
/home/gthomas/code/garnet/rust/target/release
|
|
||||||
/home/gthomas/code/garnet/rust/target/debug
|
|
||||||
extra-include-dirs:
|
|
||||||
/home/gthomas/code/garnet/rust
|
|
||||||
|
|
||||||
-- https://well-typed.com/blog/2026/02/hs-bindgen-alpha
|
-- https://well-typed.com/blog/2026/02/hs-bindgen-alpha
|
||||||
-- Haskell.nix doesn't seem to like `tag: release-0.1-alpha`, which the blog post suggests
|
-- Haskell.nix doesn't seem to like `tag: release-0.1-alpha`, which the blog post suggests
|
||||||
-- so we specify the equivalent commit SHAs manually instead
|
-- so we specify the equivalent commit SHAs manually instead
|
||||||
|
|||||||
@ -5,7 +5,12 @@ set -euo pipefail
|
|||||||
|
|
||||||
# Generate Haskell FFI bindings from Rust source code.
|
# Generate Haskell FFI bindings from Rust source code.
|
||||||
#
|
#
|
||||||
# Pipeline: cargo build -> cbindgen -> patch header -> hs-bindgen
|
# Pipeline:
|
||||||
|
# 1. cargo build - build the Rust static library
|
||||||
|
# 2. cbindgen - generate a C header from the Rust source
|
||||||
|
# 3. awk - patch the header for hs-bindgen compatibility
|
||||||
|
# 4. hs-bindgen-cli - generate Haskell FFI modules from the C header
|
||||||
|
# 5. cabal configure - point Cabal at the Rust build artifacts
|
||||||
#
|
#
|
||||||
# Prerequisites: run inside the Nix dev shell (provides gcc, cabal, cbindgen, hs-bindgen-cli).
|
# Prerequisites: run inside the Nix dev shell (provides gcc, cabal, cbindgen, hs-bindgen-cli).
|
||||||
|
|
||||||
@ -30,18 +35,21 @@ cbindgen \
|
|||||||
echo " Raw header written to $HEADER"
|
echo " Raw header written to $HEADER"
|
||||||
|
|
||||||
# --- Step 3: Patch the header for hs-bindgen compatibility ---
|
# --- Step 3: Patch the header for hs-bindgen compatibility ---
|
||||||
|
#
|
||||||
|
# Two patches are needed, both due to hs-bindgen limitations with cbindgen's
|
||||||
|
# output for #[repr(C, u8)] tagged enums:
|
||||||
|
#
|
||||||
|
# 1. cbindgen emits: enum Shape_Tag { Circle, Rectangle, };
|
||||||
|
# typedef uint8_t Shape_Tag;
|
||||||
|
# hs-bindgen needs: typedef uint8_t Shape_Tag;
|
||||||
|
# #define Circle 0
|
||||||
|
# #define Rectangle 1
|
||||||
|
# See: no upstream issue yet for hs-bindgen
|
||||||
|
#
|
||||||
|
# 2. cbindgen emits: union { ... }; (anonymous)
|
||||||
|
# hs-bindgen needs: union { ... } body; (named)
|
||||||
|
# See: https://github.com/well-typed/hs-bindgen/issues/1649
|
||||||
echo "=== Patching header ==="
|
echo "=== Patching header ==="
|
||||||
|
|
||||||
# Two patches are needed:
|
|
||||||
#
|
|
||||||
# Patch 1: Replace cbindgen's enum pattern with typedef + #defines.
|
|
||||||
# cbindgen emits: enum Shape_Tag { Circle, Rectangle, }; typedef uint8_t Shape_Tag;
|
|
||||||
# hs-bindgen needs: typedef uint8_t Shape_Tag; #define Circle 0 ...
|
|
||||||
#
|
|
||||||
# Patch 2: Name anonymous unions inside structs.
|
|
||||||
# cbindgen emits: union { ... };
|
|
||||||
# hs-bindgen needs: union { ... } body;
|
|
||||||
|
|
||||||
awk '
|
awk '
|
||||||
# State machine for enum->typedef+define transformation
|
# State machine for enum->typedef+define transformation
|
||||||
/^enum [A-Za-z_][A-Za-z0-9_]* \{$/ {
|
/^enum [A-Za-z_][A-Za-z0-9_]* \{$/ {
|
||||||
@ -94,11 +102,11 @@ pending_enum && /^typedef [A-Za-z0-9_]+ / {
|
|||||||
echo " Patched header at $HEADER"
|
echo " Patched header at $HEADER"
|
||||||
|
|
||||||
# --- Step 4: Derive system include paths for hs-bindgen's libclang ---
|
# --- Step 4: Derive system include paths for hs-bindgen's libclang ---
|
||||||
echo "=== Detecting system include paths ==="
|
#
|
||||||
|
|
||||||
# hs-bindgen uses libclang directly, which doesn't know about NixOS's
|
# hs-bindgen uses libclang directly, which doesn't know about NixOS's
|
||||||
# non-standard include locations. We extract them from cpp -v and pass
|
# non-standard include locations. We extract them from cpp -v and pass
|
||||||
# all of them — extra paths are harmless.
|
# all of them — extra paths are harmless.
|
||||||
|
echo "=== Detecting system include paths ==="
|
||||||
CLANG_OPTIONS=()
|
CLANG_OPTIONS=()
|
||||||
while IFS= read -r dir; do
|
while IFS= read -r dir; do
|
||||||
CLANG_OPTIONS+=("--clang-option" "-isystem$dir")
|
CLANG_OPTIONS+=("--clang-option" "-isystem$dir")
|
||||||
@ -122,6 +130,17 @@ hs-bindgen-cli preprocess \
|
|||||||
"${CLANG_OPTIONS[@]}" \
|
"${CLANG_OPTIONS[@]}" \
|
||||||
-I "$RUST_DIR" "$HEADER_NAME"
|
-I "$RUST_DIR" "$HEADER_NAME"
|
||||||
|
|
||||||
|
# --- Step 6: Configure Cabal ---
|
||||||
|
#
|
||||||
|
# Point Cabal at the Rust static library and C header. This writes
|
||||||
|
# cabal.project.local (gitignored) with absolute paths derived from
|
||||||
|
# the current working directory, avoiding hardcoded paths in cabal.project.
|
||||||
|
echo "=== Configuring Cabal ==="
|
||||||
|
cabal configure \
|
||||||
|
--extra-lib-dirs="$RUST_DIR/target/debug" \
|
||||||
|
--extra-lib-dirs="$RUST_DIR/target/release" \
|
||||||
|
--extra-include-dirs="$RUST_DIR"
|
||||||
|
|
||||||
echo "=== Done ==="
|
echo "=== Done ==="
|
||||||
echo "Generated Haskell bindings in $HASKELL_DIR/generated/"
|
echo "Generated Haskell bindings in $HASKELL_DIR/generated/"
|
||||||
echo "Run 'cabal run' to test."
|
echo "Run 'cabal run' to test."
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user