about summary refs log tree commit diff
path: root/third_party/bazel/rules_haskell/tests/cc_haskell_import
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/bazel/rules_haskell/tests/cc_haskell_import')
-rw-r--r--third_party/bazel/rules_haskell/tests/cc_haskell_import/BUILD.bazel70
-rw-r--r--third_party/bazel/rules_haskell/tests/cc_haskell_import/LibA.hs8
-rw-r--r--third_party/bazel/rules_haskell/tests/cc_haskell_import/LibB.hs9
-rw-r--r--third_party/bazel/rules_haskell/tests/cc_haskell_import/cbits.c5
-rw-r--r--third_party/bazel/rules_haskell/tests/cc_haskell_import/main.c11
-rw-r--r--third_party/bazel/rules_haskell/tests/cc_haskell_import/python_add_one.py18
6 files changed, 121 insertions, 0 deletions
diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/BUILD.bazel b/third_party/bazel/rules_haskell/tests/cc_haskell_import/BUILD.bazel
new file mode 100644
index 0000000000..c896314500
--- /dev/null
+++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/BUILD.bazel
@@ -0,0 +1,70 @@
+load(
+    "@io_tweag_rules_haskell//haskell:haskell.bzl",
+    "haskell_library",
+)
+
+package(default_testonly = 1)
+
+haskell_library(
+    name = "hs-lib-a",
+    srcs = ["LibA.hs"],
+    deps = [
+        "//tests/data:ourclibrary",
+        "//tests/hackage:base",
+    ],
+)
+
+haskell_library(
+    name = "hs-lib-b",
+    srcs = ["LibB.hs"],
+    deps = [
+        ":hs-lib-a",
+        "//tests/hackage:base",
+    ],
+)
+
+cc_binary(
+    name = "cc-bin",
+    srcs = [
+        "main.c",
+    ],
+    # TODO support linking with static haskell libraries.
+    linkstatic = False,
+    tags = ["requires_threaded_rts"],
+    visibility = ["//tests:__subpackages__"],
+    deps = [
+        ":hs-lib-b",
+        "@ghc//:threaded-rts",
+    ],
+)
+
+# We go one step further and use the Haskell library from above
+# to build a static .so which is then loaded with a Python script
+# and calls the Haskell function constructed from GHC C FFI.
+
+# shared library which python will dlopen
+cc_binary(
+    name = "hs-lib-b-wrapped.so",
+    linkshared = 1,
+    linkstatic = 0,
+    tags = ["requires_threaded_rts"],
+    visibility = ["//tests:__subpackages__"],
+    deps = [
+        ":hs-lib-b",
+        "@ghc//:threaded-rts",
+    ],
+)
+
+# just dlopens hb-lib-b-wrapped.so and prints it
+py_binary(
+    name = "python_add_one",
+    srcs = ["python_add_one.py"],
+    data = [
+        ":hs-lib-b-wrapped.so",
+    ],
+    default_python_version = "PY3",
+    srcs_version = "PY3ONLY",
+    tags = ["requires_threaded_rts"],
+    visibility = ["//tests:__subpackages__"],
+    deps = ["@bazel_tools//tools/python/runfiles"],
+)
diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibA.hs b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibA.hs
new file mode 100644
index 0000000000..db8e442e5a
--- /dev/null
+++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibA.hs
@@ -0,0 +1,8 @@
+module LibA (add_one) where
+
+import Data.Int (Int32)
+
+foreign import ccall "c_add_one" c_add_one' :: Int32 -> Int32
+
+add_one :: Int32 -> Int32
+add_one x = c_add_one' x
diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibB.hs b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibB.hs
new file mode 100644
index 0000000000..5904463b51
--- /dev/null
+++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/LibB.hs
@@ -0,0 +1,9 @@
+module LibB (add_one_hs) where
+
+import LibA (add_one)
+import Data.Int (Int32)
+
+foreign export ccall add_one_hs :: Int32 -> IO Int32
+
+add_one_hs :: Int32 -> IO Int32
+add_one_hs x = pure $! add_one x + 0
diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/cbits.c b/third_party/bazel/rules_haskell/tests/cc_haskell_import/cbits.c
new file mode 100644
index 0000000000..587d26ba28
--- /dev/null
+++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/cbits.c
@@ -0,0 +1,5 @@
+#include <stdint.h>
+
+int32_t c_add_one(int32_t x) {
+  return 1 + x;
+}
diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/main.c b/third_party/bazel/rules_haskell/tests/cc_haskell_import/main.c
new file mode 100644
index 0000000000..661174e5df
--- /dev/null
+++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/main.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include "HsFFI.h"
+
+extern HsInt32 add_one_hs(HsInt32 a0);
+
+int main(int argc, char *argv[]) {
+  hs_init(&argc, &argv);
+  printf("Adding one to 5 through Haskell is %d\n", add_one_hs(5));
+  hs_exit();
+  return 0;
+}
diff --git a/third_party/bazel/rules_haskell/tests/cc_haskell_import/python_add_one.py b/third_party/bazel/rules_haskell/tests/cc_haskell_import/python_add_one.py
new file mode 100644
index 0000000000..b400102d1c
--- /dev/null
+++ b/third_party/bazel/rules_haskell/tests/cc_haskell_import/python_add_one.py
@@ -0,0 +1,18 @@
+import os
+import ctypes
+from bazel_tools.tools.python.runfiles import runfiles
+import subprocess
+
+r = runfiles.Create()
+
+path = r.Rlocation('io_tweag_rules_haskell/tests/cc_haskell_import/hs-lib-b-wrapped.so')
+
+foreignlib = ctypes.cdll.LoadLibrary(path)
+
+# ATTN: If you remove this print *statement* hs_init will segfault!
+# If you use the python3 print *function*, it will segfault as well!
+# TODO: wtf?
+print foreignlib
+
+foreignlib.hs_init()
+assert(str(foreignlib.add_one_hs(1)) == "2")