diff --git a/project.clj b/project.clj index 56ae74f0..837d4ec4 100644 --- a/project.clj +++ b/project.clj @@ -12,7 +12,6 @@ "deps.clj/src" "deps.clj/resources"] ;; for debugging Reflector.java code: ;; :java-source-paths ["sci/reflector/src-java"] - :java-source-paths ["src-java"] :resource-paths ["resources" "sci/resources"] :dependencies [[org.clojure/clojure "1.11.0-alpha1"] [borkdude/edamame "0.0.11"] @@ -75,7 +74,9 @@ :feature/selmer {:dependencies [[com.clojure-goes-fast/clj-async-profiler "0.4.1"] [com.opentable.components/otj-pg-embedded "0.13.3"]]}] - :uberjar {:global-vars {*assert* false} + :uberjar {:java-source-paths ["src-java"] + :dependencies [[org.graalvm.nativeimage/svm "21.1.0"]] + :global-vars {*assert* false} :jvm-opts ["-Dclojure.compiler.direct-linking=true" "-Dclojure.spec.skip-macros=true" "-Dborkdude.dynaload.aot=true"] diff --git a/src-java/babashka/impl/Graal.java b/src-java/babashka/impl/Graal.java new file mode 100644 index 00000000..6321a9d6 --- /dev/null +++ b/src-java/babashka/impl/Graal.java @@ -0,0 +1,41 @@ +package babashka.impl; + +import org.graalvm.nativeimage.c.function.CFunction; +import org.graalvm.nativeimage.c.function.CFunction.Transition; +import org.graalvm.nativeimage.c.function.CLibrary; +import org.graalvm.nativeimage.c.CContext; +import org.graalvm.nativeimage.c.type.CCharPointer; +import com.oracle.svm.core.c.ProjectHeaderFile; +import org.graalvm.nativeimage.c.type.CTypeConversion; +import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder; +import java.util.List; +import java.util.Collections; + +@CContext(Graal.MyDirectives.class) +public class Graal { + + static class MyDirectives implements CContext.Directives { + + @Override + public List getHeaderFiles() { + return Collections.singletonList(""); + } + } + + @CFunction + private static native int setenv(CCharPointer name, CCharPointer value, int overwrite); + + // API + public static void setEnv(String name, String value) { + try (CCharPointerHolder nameHolder = CTypeConversion.toCString(name); + CCharPointerHolder valueHolder = CTypeConversion.toCString(value)) { + setenv(nameHolder.get(), valueHolder.get(), 1); + } + } + + // public static void main(String[] args) { + // setEnv(args[0], args[1]); + // System.out.println(System.getenv(args[0])); + // } +} + diff --git a/src/babashka/impl/utils.clj b/src/babashka/impl/utils.clj new file mode 100644 index 00000000..d9b8b046 --- /dev/null +++ b/src/babashka/impl/utils.clj @@ -0,0 +1,13 @@ +(ns babashka.impl.utils + {:no-doc true} + (:require [babashka.utils :as utils] + [sci.core :as sci])) + +(def uns (sci/create-ns 'babashka.utils nil)) + +(def utils-namespace + {'set-env (sci/copy-var utils/set-env uns)}) + + + + diff --git a/src/babashka/main.clj b/src/babashka/main.clj index b0328a8a..f13a0780 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -34,6 +34,7 @@ [babashka.impl.tasks :as tasks :refer [tasks-namespace]] [babashka.impl.test :as t] [babashka.impl.tools.cli :refer [tools-cli-namespace]] + [babashka.impl.utils :refer [utils-namespace]] [babashka.nrepl.server :as nrepl-server] [babashka.wait :as wait] [clojure.edn :as edn] @@ -314,6 +315,7 @@ Use bb run --help to show this help output. 'clojure.java.shell shell-namespace 'babashka.wait {'wait-for-port wait/wait-for-port 'wait-for-path wait/wait-for-path} + 'babashka.utils utils-namespace 'babashka.signal {'pipe-signal-received? pipe-signal-received?} 'clojure.java.io io-namespace 'cheshire.core cheshire-core-namespace diff --git a/src/babashka/utils.clj b/src/babashka/utils.clj new file mode 100644 index 00000000..dd748138 --- /dev/null +++ b/src/babashka/utils.clj @@ -0,0 +1,9 @@ +(ns babashka.utils) + +(defmacro when-graal [& body] + (when (resolve 'babashka.impl.Graal) + `(do ~@body))) + +(defn set-env [name value] + (when-graal + (babashka.impl.Graal/setEnv name value)))