diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e48906b..56ec1548 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ env: jobs: run-tests-with-ubuntu: - name: Run Tests with ubuntu runner + name: with bazel runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -28,6 +28,7 @@ jobs: restore-keys: | repo-cache-${{ runner.os }}-nixpkgs-${{ env.cache-version }}- - run: | + nix-shell --pure --run "bazel run $BAZEL_ARGS //:gazelle" nix-shell --pure --run "bazel test --test_output=all //... $BAZEL_ARGS" - uses: actions/cache/save@v3 if: github.ref == 'refs/heads/master' @@ -36,9 +37,48 @@ jobs: ~/repo-cache ~/disk-cache key: repo-cache-${{ runner.os }}-nixpkgs-${{ env.cache-version }}-${{ github.run_id }}-${{ github.run_attempt }} + - name: gazelle check + run: | + if ! git diff --exit-code + then + echo Repository files have changed + echo You might need to run: nix-shell --run "\"bazel run //:gazelle\"" + echo and commit the resulting changes. + exit 1 + fi + + run-tests-with-stack: + name: with stack + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v22 + - name: Configure + run: | + mkdir -p ~/repo-cache ~/disk-cache + echo build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host > .bazelrc.local + - name: Get Stack snapshot install directory + id: stack-snapshot + # NOTE: `stack path` must run at least once prior to caching to ensure the directory + # exists and is populated. + run: | + stack --nix path --snapshot-install-root + echo "dir=$(stack --nix path --snapshot-install-root)" > "${GITHUB_OUTPUT}" + - uses: actions/cache@v4 + with: + path: ${{ steps.stack-snapshot.outputs.dir }} + key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }} + restore-keys: ${{ runner.os }}-stack- + - name: Build + run: | + stack --nix build + - name: Test + if: ${{ runner.os == 'Linux' }} + run: | + stack --nix test run-tests-with-darwin: - name: Run Tests with darwin runner + name: with bazel in darwin runs-on: macos-11 steps: diff --git a/BUILD.bazel b/BUILD.bazel index dff62f0d..11c324dc 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,36 +1,80 @@ exports_files(["nixpkgs.nix"]) +# gazelle:exclude {benchmarks,examples,jvm-streaming,jvm-batching} +# gazelle:resolve gazelle_cabal jvm @openjdk//:lib + load( "@rules_haskell//haskell:defs.bzl", "ghc_plugin", + "haskell_binary", "haskell_library", + "haskell_test", ) cc_library( name = "bctable", - hdrs = ["cbits/bctable.h"], srcs = ["cbits/bctable.c"], + hdrs = ["cbits/bctable.h"], strip_include_prefix = "cbits", ) +ghc_plugin( + name = "inline-java-plugin", + args = ["$(JAVABASE)/bin/javac"], + module = "Language.Java.Inline.Plugin", + toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"], + tools = ["@bazel_tools//tools/jdk:current_java_runtime"], + visibility = ["//visibility:public"], + deps = [":inline-java"], +) + +load( + "@bazel_gazelle//:def.bzl", + "DEFAULT_LANGUAGES", + "gazelle", + "gazelle_binary", +) + +gazelle( + name = "gazelle", + gazelle = ":gazelle_binary", +) + +gazelle_binary( + name = "gazelle_binary", + languages = DEFAULT_LANGUAGES + ["@io_tweag_gazelle_cabal//gazelle_cabal"], +) + +# rule generated from inline-java.cabal by gazelle_cabal haskell_library( name = "inline-java", # cbits/bctable.h is included here so it can be found by Plugin.hs # at the same location when building with bazel as with stack. - srcs = glob(['src/**/*.hs', - 'src/**/*.hsc', - 'cbits/bctable.h', - ]), + srcs = [ + "cbits/bctable.h", # keep + "src/GhcPlugins/Extras.hs", + "src/Language/Java/Inline.hs", + "src/Language/Java/Inline/Internal.hs", + "src/Language/Java/Inline/Internal/Magic.hsc", + "src/Language/Java/Inline/Internal/QQMarker.hs", + "src/Language/Java/Inline/Internal/QQMarker/Names.hs", + "src/Language/Java/Inline/Internal/QQMarker/Safe.hs", + "src/Language/Java/Inline/Plugin.hs", + "src/Language/Java/Inline/Safe.hs", + "src/Language/Java/Inline/Unsafe.hs", + ], + ghcopts = ["-DVERSION_inline_java=\"0.10.0\""], + hidden_modules = ["GhcPlugins.Extras"], + version = "0.10.0", visibility = ["//visibility:public"], deps = [ + ":bctable", # keep "//jni", "//jvm", - ":bctable", "@stackage//:Cabal", "@stackage//:base", "@stackage//:bytestring", "@stackage//:directory", - "@stackage//:filemanip", "@stackage//:filepath", "@stackage//:ghc", "@stackage//:language-java", @@ -43,12 +87,63 @@ haskell_library( ], ) -ghc_plugin( - name = "inline-java-plugin", - args = ["$(JAVABASE)/bin/javac"], - module = "Language.Java.Inline.Plugin", - toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"], - tools = ["@bazel_tools//tools/jdk:current_java_runtime"], +# rule generated from inline-java.cabal by gazelle_cabal +haskell_test( + name = "spec", + srcs = [ + "tests/Language/Java/Inline/SafeSpec.hs", + "tests/Language/Java/InlineSpec.hs", + "tests/Main.hs", + "tests/SafeSpec.hs", + "tests/Spec.hs", + ], + extra_srcs = ["@openjdk//:rpath"], # keep + ghcopts = [ + "-optl-Wl,@$(location @openjdk//:rpath)", # keep + "-DVERSION_inline_java=\"0.10.0\"", + "-threaded", + "-DHSPEC_DISCOVER_HSPEC_DISCOVER_PATH=$(location @stackage-exe//hspec-discover)", + ], + main_file = "tests/Main.hs", + plugins = [":inline-java-plugin"], + tools = ["@stackage-exe//hspec-discover"], + version = "0.10.0", visibility = ["//visibility:public"], - deps = [":inline-java"], + deps = [ + "//:inline-java", # keep + "//jni", + "//jvm", + "@stackage//:QuickCheck", + "@stackage//:base", + "@stackage//:hspec", + "@stackage//:linear-base", + "@stackage//:quickcheck-unicode", + "@stackage//:text", + "@stackage//:vector", + ], +) + +# rule generated from inline-java.cabal by gazelle_cabal +haskell_binary( + name = "micro-benchmarks", + srcs = ["benchmarks/micro/Main.hs"], + extra_srcs = ["@openjdk//:rpath"], # keep + ghcopts = [ + "-optl-Wl,@$(location @openjdk//:rpath)", # keep + "-DVERSION_inline_java=\"0.10.0\"", + "-threaded", + ], + main_file = "benchmarks/micro/Main.hs", + plugins = [":inline-java-plugin"], + version = "0.10.0", + visibility = ["//visibility:public"], + deps = [ + "//:inline-java", # keep + "//jni", + "//jvm", + "@stackage//:base", + "@stackage//:criterion", + "@stackage//:deepseq", + "@stackage//:singletons", + ], ) diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 00000000..9a994af6 --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/WORKSPACE b/WORKSPACE index 35b389c0..f8eb868a 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -64,6 +64,7 @@ stack_snapshot( "filepath", "ghc", "hspec", + "hspec-discover", "inline-c", "language-java", "monad-logger", @@ -98,6 +99,10 @@ stack_snapshot( "ghc-boot-th", "pretty", "transformers", + # gazelle_cabal dependencies + "json", # keep + "path", # keep + "path-io", # keep ], extra_deps = { "zlib" : ["@zlib.dev//:zlib"] }, components_dependencies = { @@ -109,6 +114,10 @@ stack_snapshot( "lib", "lib:attoparsec-internal", ], + "hspec-discover": [ + "lib", + "exe", + ], }, local_snapshot = "//:snapshot-9.0.2.yaml", # stack = "@stack_ignore_global_hints//:bin/stack" if ghc_version == "9.0.1" else None, @@ -144,12 +153,6 @@ haskell_register_ghc_nixpkgs( ], ) -nixpkgs_package( - name = "sed", - attribute_path = "gnused", - repository = "@nixpkgs", -) - nixpkgs_package( name = "hspec-discover", attribute_path = "haskellPackages.hspec-discover", @@ -250,3 +253,69 @@ maven_install( "https://repo1.maven.org/maven2", ], ) + +# gazelle setup + +http_archive( + name = "rules_nixpkgs_go", + sha256 = "30271f7bd380e4e20e4d7132c324946c4fdbc31ebe0bbb6638a0f61a37e74397", + strip_prefix = "rules_nixpkgs-0.13.0/toolchains/go", + urls = ["https://github.com/tweag/rules_nixpkgs/releases/download/v0.13.0/rules_nixpkgs-0.13.0.tar.gz"], +) + +http_archive( + name = "io_bazel_rules_go", + sha256 = "f2dcd210c7095febe54b804bb1cd3a58fe8435a909db2ec04e31542631cf715c", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.31.0/rules_go-v0.31.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.31.0/rules_go-v0.31.0.zip", + ], +) + +http_archive( + name = "bazel_gazelle", + sha256 = "de69a09dc70417580aabf20a28619bb3ef60d038470c7cf8442fafcf627c21cb", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz", + "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz", + ], +) + +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository") + +############################################################ +# Define your own dependencies here using go_repository. +# Else, dependencies declared by rules_go/gazelle will be used. +# The first declaration of an external repository "wins". +############################################################ + +load("@rules_nixpkgs_go//:go.bzl", "nixpkgs_go_configure") + +nixpkgs_go_configure( + repository = "@nixpkgs", +) + +load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") + +go_rules_dependencies() + +gazelle_dependencies() + + +http_archive( + name = "io_tweag_gazelle_cabal", + strip_prefix = "gazelle_cabal-ca8f68e250bea33815fb373320f9610582c42083", + sha256 = "bd2ee67943007723b3425bf2fcbdb6b41b269c7bc03f01e40683d4b5f3984b3b", + url = "https://github.com/tweag/gazelle_cabal/archive/ca8f68e.zip", +) + +load("@rules_haskell//haskell:cabal.bzl", "stack_snapshot") +load("@io_tweag_gazelle_cabal//:defs.bzl", "gazelle_cabal_dependencies") +gazelle_cabal_dependencies() + +go_repository( + name = "org_golang_x_xerrors", + importpath = "golang.org/x/xerrors", + sum = "h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=", + version = "v0.0.0-20200804184101-5ec99f83aff1", +) diff --git a/benchmarks/micro/BUILD.bazel b/benchmarks/micro/BUILD.bazel deleted file mode 100644 index 839e555e..00000000 --- a/benchmarks/micro/BUILD.bazel +++ /dev/null @@ -1,25 +0,0 @@ -load( - "@rules_haskell//haskell:defs.bzl", - "haskell_binary", -) - -haskell_binary( - name = "bench", - srcs = glob(['**/*.hs']), - extra_srcs = ["@openjdk//:rpath"], - compiler_flags = [ - "-optl-Wl,@$(location @openjdk//:rpath)", - "-threaded", - ], - deps = [ - "//jvm", - "//jni", - "//:inline-java", - "@stackage//:base", - "@stackage//:criterion", - "@stackage//:deepseq", - "@stackage//:singletons", - "@stackage//:text", - ], - plugins = ["//:inline-java-plugin"], -) diff --git a/inline-java.cabal b/inline-java.cabal new file mode 100644 index 00000000..0e9c6c72 --- /dev/null +++ b/inline-java.cabal @@ -0,0 +1,99 @@ +name: inline-java +version: 0.10.0 +synopsis: Java interop via inline Java code in Haskell modules. +description: Please see README.md. +homepage: http://github.com/tweag/inline-java#readme +license: BSD3 +license-file: LICENSE +author: Tweag I/O +maintainer: m@tweag.io +copyright: 2015-2016 EURL Tweag. +category: FFI, JVM, Java +build-type: Simple +cabal-version: 2.0 +extra-source-files: + CHANGELOG.md + README.md + +source-repository head + type: git + location: https://github.com/tweag/inline-java + +library + hs-source-dirs: src + c-sources: cbits/bctable.c + cc-options: -std=c99 -Wall -Werror + include-dirs: cbits/ + includes: bctable.h + install-includes: bctable.h + exposed-modules: + Language.Java.Inline + Language.Java.Inline.Safe + Language.Java.Inline.Internal + Language.Java.Inline.Internal.Magic + Language.Java.Inline.Internal.QQMarker + Language.Java.Inline.Internal.QQMarker.Names + Language.Java.Inline.Internal.QQMarker.Safe + Language.Java.Inline.Plugin + Language.Java.Inline.Unsafe + other-modules: + GhcPlugins.Extras + build-depends: + base >=4.14.0.0 && <5, + bytestring >=0.10, + Cabal >=1.24.2, + directory >=1.2, + filepath >=1, + ghc >=9.0.2 && <9.2, + jni >=0.8 && <0.9, + jvm >=0.6 && <0.7, + language-java >=0.2, + linear-base ==0.1.0, + mtl >=2.2.1, + process >=1.2, + text >=1.2, + template-haskell >=2.10, + temporary >=1.2 + default-language: Haskell2010 + +test-suite spec + type: + exitcode-stdio-1.0 + hs-source-dirs: tests + main-is: Main.hs + other-modules: + SafeSpec + Spec + Language.Java.Inline.SafeSpec + Language.Java.InlineSpec + build-depends: + base, + jni, + jvm, + hspec, + inline-java, + linear-base, + QuickCheck, + quickcheck-unicode, + text, + vector + default-language: Haskell2010 + ghc-options: -threaded + cpp-options: -DHSPEC_DISCOVER_HSPEC_DISCOVER_PATH=hspec-discover + build-tool-depends: + hspec-discover:hspec-discover + +benchmark micro-benchmarks + type: exitcode-stdio-1.0 + main-is: Main.hs + hs-source-dirs: benchmarks/micro + build-depends: + base >=4.8 && <5, + criterion, + deepseq >=1.4.2, + inline-java, + jni, + jvm, + singletons + default-language: Haskell2010 + ghc-options: -threaded diff --git a/jni/BUILD.bazel b/jni/BUILD.bazel index a96bfde6..a24313d0 100644 --- a/jni/BUILD.bazel +++ b/jni/BUILD.bazel @@ -1,66 +1,42 @@ load( "@rules_haskell//haskell:defs.bzl", + "haskell_binary", "haskell_library", + "haskell_test", ) -# Note cat-tokens -# -# This is a script to concatenate tokens after CPP preprocessing. -# -# On OSX we used to rely on cpphs to concatenate tokens in -# definitions like -# -# define GET_FIELD(name, hs_rettype, c_rettype) \ -# get/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> IO hs_rettype; -# -# The C preprocessor in OSX would otherwise replace the -# comments with whitespaces. -# -# Using cpphs, however, required a couple of hacks to workaround -# https://github.com/haskell/cabal/issues/4278 -# https://gitlab.haskell.org/ghc/ghc/-/issues/17185 -# -# And moreover, when using rules_haskell, ghc passes response files to cpphs, -# which are unsupported. -# https://github.com/tweag/rules_haskell/pull/836 -# -# Therefore, we currently resolve concatenation with a custom -# preprocessor to avoid the pile of hacks. The concatenator operator is ####. -# -# define GET_FIELD(name, hs_rettype, c_rettype) \ -# get####name####Field :: Coercible o (J a) => o -> JFieldID -> IO hs_rettype; -# -genrule( - name = "cat-tokens-sh", - srcs = [], - executable = 1, - outs = ["cat-tokens.sh"], - tools = ["@sed//:bin"], - cmd = """ -cat > $@ < \\$$3 -exit \\$$? -END - """, -) - +# rule generated from jni/jni.cabal by gazelle_cabal haskell_library( name = "jni", - srcs = glob([ - 'src/common/**/*.hs', 'src/common/**/*.hsc', - 'src/linear-types/**/*.hs', - ]), - extra_srcs = ["//jni:cat-tokens-sh"], - compiler_flags = ["-F", "-pgmF$(location cat-tokens-sh)"], + srcs = [ + "src/common/Foreign/JNI.hs", + "src/common/Foreign/JNI/Internal.hs", + "src/common/Foreign/JNI/Internal/BackgroundWorker.hs", + "src/common/Foreign/JNI/Internal/RWLock.hs", + "src/common/Foreign/JNI/NativeMethod.hsc", + "src/common/Foreign/JNI/String.hs", + "src/common/Foreign/JNI/Types.hs", + "src/common/Foreign/JNI/Unsafe.hs", + "src/common/Foreign/JNI/Unsafe/Internal.hs", + "src/common/Foreign/JNI/Unsafe/Internal/Introspection.hs", + "src/linear-types/Foreign/JNI/Safe.hs", + "src/linear-types/Foreign/JNI/Types/Safe.hs", + ], + ghcopts = [ + "-DVERSION_jni=\"0.8.0\"", + "-DJNI_CAT_TOKENS_PATH=$(location :cat-tokens)", + ], + tools = [":cat-tokens"], + version = "0.8.0", + visibility = ["//visibility:public"], deps = [ "@openjdk//:lib", "@stackage//:async", "@stackage//:base", "@stackage//:bytestring", "@stackage//:choice", - "@stackage//:containers", "@stackage//:constraints", + "@stackage//:containers", "@stackage//:deepseq", "@stackage//:inline-c", "@stackage//:linear-base", @@ -68,6 +44,48 @@ haskell_library( "@stackage//:stm", "@stackage//:text", ], - tools = ["@sed//:bin"], +) + +# rule generated from jni/jni.cabal by gazelle_cabal +haskell_test( + name = "spec", + timeout = "short", + srcs = [ + "tests/Foreign/JNISpec.hs", + "tests/Main.hs", + "tests/Spec.hs", + ], + # keep + extra_srcs = ["@openjdk//:rpath"], + ghcopts = [ + "-DVERSION_jni=\"0.8.0\"", + "-threaded", + "-lpthread", + "-DHSPEC_DISCOVER_HSPEC_DISCOVER_PATH=$(location @stackage-exe//hspec-discover)", + "-optl-Wl,@$(location @openjdk//:rpath)", # keep + ], + main_file = "tests/Main.hs", + tools = ["@stackage-exe//hspec-discover"], + version = "0.8.0", visibility = ["//visibility:public"], + deps = [ + ":jni", + "@stackage//:base", + "@stackage//:hspec", + "@stackage//:singletons-base", + ], +) + +# rule generated from jni/jni.cabal by gazelle_cabal +haskell_binary( + name = "cat-tokens", + srcs = ["cat-tokens/Main.hs"], + ghcopts = ["-DVERSION_jni=\"0.8.0\""], + main_file = "cat-tokens/Main.hs", + version = "0.8.0", + visibility = ["//visibility:public"], + deps = [ + "@stackage//:base", + "@stackage//:bytestring", + ], ) diff --git a/jni/Setup.hs b/jni/Setup.hs new file mode 100644 index 00000000..9a994af6 --- /dev/null +++ b/jni/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/jni/cat-tokens b/jni/cat-tokens deleted file mode 100755 index ece4547a..00000000 --- a/jni/cat-tokens +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -( echo "{-# LINE 1 \"$1\" #-}" ; sed 's/####//g' $2) > $3 -exit $? - diff --git a/jni/cat-tokens/Main.hs b/jni/cat-tokens/Main.hs new file mode 100644 index 00000000..4a38d519 --- /dev/null +++ b/jni/cat-tokens/Main.hs @@ -0,0 +1,52 @@ +-- | Takes three file paths, and copies the file at the second location to the +-- third location, replacing occurrences of #### with the empty string. +-- +-- The first location is used to prepend the output with a line pragma. +-- +-- > {-# LINE 1 "firstLocation" #-} +-- +-- +-- This is a script to concatenate tokens after CPP preprocessing. +-- +-- On OSX we used to rely on cpphs to concatenate tokens in +-- definitions like +-- +-- > define GET_FIELD(name, hs_rettype, c_rettype) \ +-- > get/**/name/**/Field :: Coercible o (J a) => o -> JFieldID -> IO hs_rettype; +-- +-- The C preprocessor in OSX would otherwise replace the +-- comments with whitespaces. +-- +-- Using cpphs, however, required a couple of hacks to workaround +-- https://github.com/haskell/cabal/issues/4278 +-- https://gitlab.haskell.org/ghc/ghc/-/issues/17185 +-- +-- And moreover, when using rules_haskell, ghc passes response files to cpphs, +-- which are unsupported. +-- https://github.com/tweag/rules_haskell/pull/836 +-- +-- Therefore, we currently resolve concatenation with a custom +-- preprocessor to avoid the pile of hacks. The concatenator operator is ####. +-- +-- > define GET_FIELD(name, hs_rettype, c_rettype) \ +-- > get####name####Field :: Coercible o (J a) => o -> JFieldID -> IO hs_rettype; +-- +module Main where + +import qualified Data.ByteString as BS +import qualified Data.ByteString.Char8 as C8 +import System.Environment +import System.IO + +main :: IO () +main = do + [srcF, inF, outF] <- getArgs + bs <- BS.readFile inF + hOut <- openBinaryFile outF WriteMode + hPutStrLn hOut $ "{-# LINE 1 \"" ++ srcF ++ "\" #-}"; + mapM_ (BS.hPut hOut) $ tokenise bs + hClose hOut + +tokenise :: BS.ByteString -> [BS.ByteString] +tokenise y = h : if BS.null t then [] else tokenise (BS.drop 4 t) + where (h, t) = BS.breakSubstring (C8.pack "####") y diff --git a/jni/jni.cabal b/jni/jni.cabal new file mode 100644 index 00000000..5bb85d7e --- /dev/null +++ b/jni/jni.cabal @@ -0,0 +1,85 @@ +name: jni +version: 0.8.0 +synopsis: Complete JNI raw bindings. +description: Please see README.md. +homepage: https://github.com/tweag/inline-java/tree/master/jni#readme +license: BSD3 +license-file: LICENSE +author: Tweag I/O +maintainer: m@tweag.io +copyright: 2015-2016 EURL Tweag. +category: FFI, JVM, Java +build-type: Simple +cabal-version: 2.0 +extra-source-files: README.md + +source-repository head + type: git + location: https://github.com/tweag/inline-java + subdir: jni + +library + hs-source-dirs: src/common src/linear-types + cc-options: -std=c11 + extra-libraries: jvm + exposed-modules: + Foreign.JNI + Foreign.JNI.Types + Foreign.JNI.String + Foreign.JNI.Internal + Foreign.JNI.Internal.BackgroundWorker + Foreign.JNI.Internal.RWLock + Foreign.JNI.NativeMethod + Foreign.JNI.Safe + Foreign.JNI.Types.Safe + Foreign.JNI.Unsafe + Foreign.JNI.Unsafe.Internal + Foreign.JNI.Unsafe.Internal.Introspection + build-depends: + async >=2.2.2, + base >=4.14 && <5, + bytestring >=0.10, + choice >=0.2.0, + containers >=0.5, + constraints >=0.8, + deepseq >=1.4.2, + inline-c >=0.6, + linear-base ==0.1.0, + singletons-base ==3.0, + stm >= 2.3, + text >= 1.2.3 + default-language: Haskell2010 + -- XXX issues with CPP make more convenient using + -- a custom preprocessor to deal with concatenation. + -- See jni/cat-tokens/Main.hs. + cpp-options: -DJNI_CAT_TOKENS_PATH=cat-tokens + build-tool-depends: + jni:cat-tokens + +executable cat-tokens + hs-source-dirs: cat-tokens + main-is: Main.hs + build-depends: + base, + bytestring + default-language: Haskell2010 + +test-suite spec + type: + exitcode-stdio-1.0 + hs-source-dirs: tests + main-is: Main.hs + other-modules: + Foreign.JNISpec + Spec + build-depends: + base, + hspec, + singletons-base, + jni + default-language: Haskell2010 + extra-libraries: pthread + ghc-options: -threaded + cpp-options: -DHSPEC_DISCOVER_HSPEC_DISCOVER_PATH=hspec-discover + build-tool-depends: + hspec-discover:hspec-discover diff --git a/jni/src/common/Foreign/JNI/Unsafe/Internal.hs b/jni/src/common/Foreign/JNI/Unsafe/Internal.hs index 28cd55f5..e64d2124 100644 --- a/jni/src/common/Foreign/JNI/Unsafe/Internal.hs +++ b/jni/src/common/Foreign/JNI/Unsafe/Internal.hs @@ -10,10 +10,10 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-} +{-# OPTIONS_GHC -fno-warn-name-shadowing -F -pgmF JNI_CAT_TOKENS_PATH #-} -- XXX This file uses #### for concatenating tokens with a preprocessor in --- a portable way. See note cat-tokens in jni/BUILD.bazel. +-- a portable way. See note cat-tokens in jni/cat-tokens/Main.hs. module Foreign.JNI.Unsafe.Internal ( -- * JNI functions diff --git a/jni/src/linear-types/Foreign/JNI/Safe.hs b/jni/src/linear-types/Foreign/JNI/Safe.hs index 1f8687bc..45b313cc 100644 --- a/jni/src/linear-types/Foreign/JNI/Safe.hs +++ b/jni/src/linear-types/Foreign/JNI/Safe.hs @@ -60,8 +60,10 @@ {-# LANGUAGE LinearTypes #-} {-# LANGUAGE NoImplicitPrelude #-} +{-# OPTIONS_GHC -fno-warn-name-shadowing -F -pgmF JNI_CAT_TOKENS_PATH #-} + -- XXX This file uses #### for concatenating tokens with a preprocessor in --- a portable way. See note cat-tokens in jni/BUILD.bazel. +-- a portable way. See cat-tokens/Main.hs. module Foreign.JNI.Safe ( module Foreign.JNI.Safe @@ -303,11 +305,12 @@ deleteGlobalRefNonFinalized o = liftPreludeIO (JNI.deleteGlobalRef o) -- run in a thread where the reference is not valid. newLocalRef :: (MonadIO m, Coercible o (J ty)) => o %1-> m (o, o) newLocalRef = Unsafe.toLinear $ \o -> - liftPreludeIO ((,) o . coerce . J <$> JNI.newLocalRef (unJ . coerce $ o)) + liftPreludeIO + ((,) o . coerce . J <$> JNI.newLocalRef (unJ . coerce Prelude.$ o)) deleteLocalRef :: (MonadIO m, Coercible o (J ty)) => o %1-> m () deleteLocalRef = Unsafe.toLinear $ \o -> - liftPreludeIO (JNI.deleteLocalRef (unJ . coerce $ o)) + liftPreludeIO (JNI.deleteLocalRef (unJ . coerce Prelude.$ o)) -- | Runs the given computation in a local frame, which ensures that -- if it throws an exception, all live local references created during diff --git a/jni/tests/BUILD.bazel b/jni/tests/BUILD.bazel deleted file mode 100644 index 75e6f549..00000000 --- a/jni/tests/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load( - "@rules_haskell//haskell:defs.bzl", - "haskell_test", -) - -haskell_test( - name = "spec", - srcs = glob(['**/*.hs']), - extra_srcs = ["@openjdk//:rpath"], - compiler_flags = [ - "-optl-Wl,@$(location @openjdk//:rpath)", - "-DHSPEC_DISCOVER=$(location @hspec-discover//:bin)", - "-threaded", - ], - timeout = "short", - tools = ["@hspec-discover//:bin"], - deps = [ - "//jni", - "@stackage//:base", - "@stackage//:hspec", - "@stackage//:singletons-base", - ], -) diff --git a/jni/tests/Spec.hs b/jni/tests/Spec.hs index 753d8a2a..911f571f 100644 --- a/jni/tests/Spec.hs +++ b/jni/tests/Spec.hs @@ -1,2 +1,2 @@ {-# LANGUAGE CPP #-} -{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER -optF --module-name=Spec #-} +{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER_HSPEC_DISCOVER_PATH -optF --module-name=Spec #-} diff --git a/jvm-types/BUILD.bazel b/jvm-types/BUILD.bazel index 1229de87..ebc1681b 100644 --- a/jvm-types/BUILD.bazel +++ b/jvm-types/BUILD.bazel @@ -1,26 +1,26 @@ load( - "@rules_haskell//haskell:defs.bzl", - "haskell_library", + "@rules_haskell//haskell:defs.bzl", + "haskell_library", ) java_library( name = "jar", srcs = glob(["src/main/java/**/*.java"]), - deps = ["//jvm-batching:jar"], visibility = ["//visibility:public"], + deps = ["//jvm-batching:jar"], ) haskell_library( name = "jvm-types", - srcs = glob(['src/main/haskell/**/*.hs']), - visibility = ["//visibility:public"], + srcs = glob(["src/main/haskell/**/*.hs"]), plugins = ["//:inline-java-plugin"], + visibility = ["//visibility:public"], deps = [ ":jar", + "//:inline-java", "//jni", "//jvm", "//jvm-batching", - "//:inline-java", "@stackage//:base", "@stackage//:distributed-closure", "@stackage//:singletons", diff --git a/jvm-types/src/test/haskell/BUILD.bazel b/jvm-types/src/test/haskell/BUILD.bazel index 921528ce..ceb9c385 100644 --- a/jvm-types/src/test/haskell/BUILD.bazel +++ b/jvm-types/src/test/haskell/BUILD.bazel @@ -1,18 +1,18 @@ load( - "@rules_haskell//haskell:defs.bzl", - "haskell_test", + "@rules_haskell//haskell:defs.bzl", + "haskell_test", ) haskell_test( name = "spec", + size = "small", srcs = glob(["**/*.hs"]), - extra_srcs = ["@openjdk//:rpath"], compiler_flags = [ "-optl-Wl,@$(location @openjdk//:rpath)", "-DHSPEC_DISCOVER=$(location @hspec-discover//:bin)", "-threaded", ], - size = "small", + extra_srcs = ["@openjdk//:rpath"], plugins = ["//:inline-java-plugin"], tools = ["@hspec-discover//:bin"], deps = [ diff --git a/jvm/BUILD.bazel b/jvm/BUILD.bazel index c7bab02f..9e90d944 100644 --- a/jvm/BUILD.bazel +++ b/jvm/BUILD.bazel @@ -1,20 +1,28 @@ load( - "@rules_haskell//haskell:defs.bzl", - "haskell_library", + "@rules_haskell//haskell:defs.bzl", + "haskell_binary", + "haskell_library", + "haskell_test", ) +# rule generated from jvm/jvm.cabal by gazelle_cabal haskell_library( name = "jvm", - srcs = glob([ - 'src/common/**/*.hs', - 'src/linear-types/**/*.hs', - ]), + srcs = [ + "src/common/Language/Java.hs", + "src/common/Language/Java/Internal.hs", + "src/common/Language/Java/Unsafe.hs", + "src/linear-types/Language/Java/Safe.hs", + ], + ghcopts = ["-DVERSION_jvm=\"0.6.0\""], + version = "0.6.0", + visibility = ["//visibility:public"], deps = [ "//jni", "@stackage//:base", "@stackage//:bytestring", - "@stackage//:constraints", "@stackage//:choice", + "@stackage//:constraints", "@stackage//:distributed-closure", "@stackage//:exceptions", "@stackage//:linear-base", @@ -22,7 +30,63 @@ haskell_library( "@stackage//:template-haskell", "@stackage//:text", "@stackage//:vector", - ] + [ - ], + ], +) + +# rule generated from jvm/jvm.cabal by gazelle_cabal +haskell_test( + name = "spec", + srcs = [ + "tests/Language/JavaSpec.hs", + "tests/Main.hs", + "tests/Spec.hs", + ], + # keep + extra_srcs = ["@openjdk//:rpath"], + ghcopts = [ + "-DVERSION_jvm=\"0.6.0\"", + "-threaded", + "-lpthread", + "-DHSPEC_DISCOVER_HSPEC_DISCOVER_PATH=$(location @stackage-exe//hspec-discover)", + "-optl-Wl,@$(location @openjdk//:rpath)", # keep + ], + main_file = "tests/Main.hs", + tools = ["@stackage-exe//hspec-discover"], + version = "0.6.0", + visibility = ["//visibility:public"], + deps = [ + ":jvm", + "//jni", + "@stackage//:QuickCheck", + "@stackage//:base", + "@stackage//:bytestring", + "@stackage//:hspec", + "@stackage//:quickcheck-text", + "@stackage//:text", + ], +) + +# rule generated from jvm/jvm.cabal by gazelle_cabal +haskell_binary( + name = "micro-benchmarks", + srcs = ["benchmarks/Main.hs"], + # keep + extra_srcs = ["@openjdk//:rpath"], + ghcopts = [ + "-DVERSION_jvm=\"0.6.0\"", + "-threaded", + "-optl-Wl,@$(location @openjdk//:rpath)", # keep + ], + main_file = "benchmarks/Main.hs", + version = "0.6.0", visibility = ["//visibility:public"], + deps = [ + ":jvm", + "//jni", + "@stackage//:base", + "@stackage//:criterion", + "@stackage//:deepseq", + "@stackage//:singletons", + "@stackage//:text", + ], ) diff --git a/jvm/Setup.hs b/jvm/Setup.hs new file mode 100644 index 00000000..9a994af6 --- /dev/null +++ b/jvm/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/jvm/benchmarks/BUILD.bazel b/jvm/benchmarks/BUILD.bazel deleted file mode 100644 index e6b8a87a..00000000 --- a/jvm/benchmarks/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load( - "@rules_haskell//haskell:defs.bzl", - "haskell_binary", -) - -haskell_binary( - name = "bench", - srcs = glob(['**/*.hs']), - extra_srcs = ["@openjdk//:rpath"], - compiler_flags = [ - "-optl-Wl,@$(location @openjdk//:rpath)", - "-threaded", - ], - deps = [ - "//jvm", - "//jni", - "@stackage//:base", - "@stackage//:criterion", - "@stackage//:deepseq", - "@stackage//:singletons", - "@stackage//:text", - ], -) diff --git a/jvm/jvm.cabal b/jvm/jvm.cabal new file mode 100644 index 00000000..391c9641 --- /dev/null +++ b/jvm/jvm.cabal @@ -0,0 +1,80 @@ +name: jvm +version: 0.6.0 +synopsis: Call JVM methods from Haskell. +description: Please see README.md. +homepage: http://github.com/tweag/inline-java/tree/master/jvm#readme +license: BSD3 +license-file: LICENSE +author: Tweag I/O +maintainer: m@tweag.io +copyright: 2015-2016 EURL Tweag. +category: FFI, JVM, Java +build-type: Simple +cabal-version: 2.0 +extra-source-files: README.md + +source-repository head + type: git + location: https://github.com/tweag/inline-java + subdir: jvm + +library + hs-source-dirs: src/common src/linear-types + exposed-modules: + Language.Java + Language.Java.Internal + Language.Java.Safe + Language.Java.Unsafe + build-depends: + base >=4.14 && <5, + bytestring >=0.10, + constraints >=0.8, + choice >=0.1, + distributed-closure >=0.3, + exceptions >=0.8, + jni >=0.8.0 && <0.9, + linear-base ==0.1.0, + singletons >=2.6, + text >=1.2, + template-haskell, + vector >=0.11 + default-language: Haskell2010 + +test-suite spec + type: + exitcode-stdio-1.0 + hs-source-dirs: tests + main-is: Main.hs + other-modules: + Language.JavaSpec + Spec + build-depends: + base, + bytestring, + hspec, + jni, + jvm, + QuickCheck, + quickcheck-text, + text + default-language: Haskell2010 + extra-libraries: pthread + ghc-options: -threaded + cpp-options: -DHSPEC_DISCOVER_HSPEC_DISCOVER_PATH=hspec-discover + build-tool-depends: + hspec-discover:hspec-discover + +benchmark micro-benchmarks + type: exitcode-stdio-1.0 + main-is: Main.hs + hs-source-dirs: benchmarks + build-depends: + base >=4.8 && <5, + criterion, + deepseq >=1.4.2, + jni, + jvm, + singletons, + text >=1.2 + default-language: Haskell2010 + ghc-options: -threaded diff --git a/jvm/tests/BUILD.bazel b/jvm/tests/BUILD.bazel deleted file mode 100644 index ade4e1a0..00000000 --- a/jvm/tests/BUILD.bazel +++ /dev/null @@ -1,28 +0,0 @@ -load( - "@rules_haskell//haskell:defs.bzl", - "haskell_test", -) - -haskell_test( - name = "spec", - srcs = glob(['**/*.hs']), - extra_srcs = ["@openjdk//:rpath"], - compiler_flags = [ - "-optl-Wl,@$(location @openjdk//:rpath)", - "-DHSPEC_DISCOVER=$(location @hspec-discover//:bin)", - "-threaded", - ], - timeout = "short", - tools = ["@hspec-discover//:bin"], - deps = [ - "//jvm", - "//jni", - "@stackage//:base", - "@stackage//:bytestring", - "@stackage//:hspec", - "@stackage//:QuickCheck", - "@stackage//:quickcheck-text", - "@stackage//:quickcheck-unicode", - "@stackage//:text", - ], -) diff --git a/jvm/tests/Spec.hs b/jvm/tests/Spec.hs index 753d8a2a..911f571f 100644 --- a/jvm/tests/Spec.hs +++ b/jvm/tests/Spec.hs @@ -1,2 +1,2 @@ {-# LANGUAGE CPP #-} -{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER -optF --module-name=Spec #-} +{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER_HSPEC_DISCOVER_PATH -optF --module-name=Spec #-} diff --git a/nixpkgs.nix b/nixpkgs.nix index 794d0745..de81a1fc 100644 --- a/nixpkgs.nix +++ b/nixpkgs.nix @@ -3,7 +3,9 @@ # # by going to a commit before the one introducing the regression. args: -let pkgs = import (fetchTarball "https://github.com/tweag/nixpkgs/archive/73ad5f9e147.tar.gz") args; +let pkgs = import (fetchTarball { + sha256 = "01j7nhxbb2kjw38yk4hkjkkbmz50g3br7fgvad6b1cjpdvfsllds"; + url = "https://github.com/tweag/nixpkgs/archive/73ad5f9e147.tar.gz";}) args; stack_ignore_global_hints = pkgs.writeScriptBin "stack" '' #!${pkgs.stdenv.shell} # Skips the --global-hints parameter to stack. This is diff --git a/shell-stack.nix b/shell-stack.nix new file mode 100644 index 00000000..1caa0666 --- /dev/null +++ b/shell-stack.nix @@ -0,0 +1,35 @@ +{ + pkgs ? import ./nixpkgs.nix { }, + ghcAttr ? "ghc902", +}: + +with pkgs; + +let + openjdk = openjdk11; + jvmlibdir = + if stdenv.isLinux + then "${openjdk}/lib/openjdk/lib/server" + else "${openjdk}/jre/lib/server"; + # XXX Workaround https://gitlab.haskell.org/ghc/ghc/-/issues/11042 + libHack = if stdenv.isDarwin then { + DYLD_LIBRARY_PATH = [jvmlibdir]; + } else { + LD_LIBRARY_PATH = [jvmlibdir]; + }; +in +haskell.lib.buildStackProject ({ + name = "inline-java"; + ghc = pkgs.haskell.compiler.${ghcAttr}; + buildInputs = [ + openjdk + git + # Needed to get correct locale for tests with encoding + glibcLocales + # to avoid CA certificate failures on macOS CI + cacert + ]; + # XXX Workaround https://gitlab.haskell.org/ghc/ghc/-/issues/11042 + extraArgs = ["--extra-lib-dirs=${jvmlibdir}"]; + LANG = "en_US.UTF-8"; +} // libHack) diff --git a/shell.nix b/shell.nix index 074fa36f..f8f7c551 100644 --- a/shell.nix +++ b/shell.nix @@ -40,7 +40,7 @@ mkShell { elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then ARCH="linux" fi - echo "[!] It looks like you are using a ''${ARCH} nix-based system. In order to build this project, you need to add the two following host_platform entries to your .bazelrc.local file." + echo "[!] It looks like you are using a ''${ARCH} nix-based system. In order to build this project, you need to add the following host_platform entry to your .bazelrc.local file." echo "" echo "build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host" fi diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 00000000..87237745 --- /dev/null +++ b/stack.yaml @@ -0,0 +1,15 @@ +resolver: lts-19.30 + +packages: +- jni +- jvm +- . + +extra-deps: +- github: tweag/distributed-closure + commit: b92e75ec81e646703c7bde4f578a7352ee34f1ad +- linear-base-0.1.0 + +nix: + shell-file: ./shell-stack.nix + path: ["nixpkgs=./nixpkgs.nix"] diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel deleted file mode 100644 index 3e8dd89d..00000000 --- a/tests/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -load( - "@rules_haskell//haskell:defs.bzl", - "haskell_test", -) - -haskell_test( - name = "spec", - srcs = glob(['**/*.hs']), - extra_srcs = ["@openjdk//:rpath"], - compiler_flags = [ - "-optl-Wl,@$(location @openjdk//:rpath)", - "-DHSPEC_DISCOVER=$(location @hspec-discover//:bin)", - "-threaded", - ], - deps = [ - "//jni", - "//jvm", - "//:inline-java", - "@stackage//:base", - "@stackage//:hspec", - "@stackage//:linear-base", - "@stackage//:text", - "@stackage//:QuickCheck", - "@stackage//:quickcheck-unicode", - "@stackage//:unix", - "@stackage//:vector", - ], - size = "small", - plugins = ["//:inline-java-plugin"], - tools = ["@hspec-discover//:bin"], -) diff --git a/tests/SafeSpec.hs b/tests/SafeSpec.hs index fec06403..695e0943 100644 --- a/tests/SafeSpec.hs +++ b/tests/SafeSpec.hs @@ -1,2 +1,2 @@ {-# LANGUAGE CPP #-} -{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER -optF --module-name=SafeSpec #-} +{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER_HSPEC_DISCOVER_PATH -optF --module-name=SafeSpec #-} diff --git a/tests/Spec.hs b/tests/Spec.hs index 753d8a2a..911f571f 100644 --- a/tests/Spec.hs +++ b/tests/Spec.hs @@ -1,2 +1,2 @@ {-# LANGUAGE CPP #-} -{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER -optF --module-name=Spec #-} +{-# OPTIONS_GHC -F -pgmF HSPEC_DISCOVER_HSPEC_DISCOVER_PATH -optF --module-name=Spec #-}