Fork me on GitHub
#babashka
<
2021-05-20
>
ghosttoaster02:05:29

does bb handle aliases? -A:dev and such?

ghosttoaster02:05:48

I guess the better questions is how do I load fuctions in to the user namespace?

borkdude07:05:30

@U3F5EM2TD Can you explain your use case? bb has an :tasks {:init ...} section where you can put startup code when you invoke a task

borkdude07:05:50

It also has a BABASHKA_PRELOADS environment variable that can contain code that is always executed before anything else

ghosttoaster17:05:01

I just wanted to preload some helpful functions in the user namespace for this one project.

ghosttoaster17:05:12

Let me try the tasks thing that could be it. I'm assuming BABASHKA_PRELOADS runs on every evocation of bb? And I only need this helper code for this project and only during development.

borkdude17:05:07

> I'm assuming BABASHKA_PRELOADS runs on every evocation of bb?

borkdude11:05:08

babashka 0.4.2-0.4.3: - Better error handling in parallel tasks - Add more agent functions and fix binding conveyance in send-via - Better transit support for pods (fixes issue with mysql pod and java.time.LocalDateTime results) - Misc. other improvements

πŸ‘ 9
πŸ‘ 2
babashka 10
2
littleli14:05:11

Not many developers realize it, but your little "clojure interpreter" has a support of concurrency such that virtually all popular scripting languages can't compete with at all πŸ‘

clojure-spin 15
richiardiandrea16:05:08

FWIW I tried the static 0.4.1 release and it works like a charm πŸ˜‰

borkdude16:05:58

A hack that might be coming to bb some day as well ;)

πŸ˜„ 4
😎 2
kokada17:05:36

This would be really useful to have, something that I miss from Python in my Babashka scripts

kokada17:05:09

BTW, could this also be turned in a JVM library (like babashka.fs is)? Asking because one of the nice things of Babashka is that my codebase is 100% compatible with Clojure proper too

kokada17:05:28

(But if isn't, no problem too, I can probably workaround just this case. The important part is just that I can call the function to set the env, not that it actually works in Clojure)

borkdude17:05:44

Yes, I want to release this is a library which can be used within babashka, but the hardest part is the name. Perhaps babashka.core? ;)

borkdude17:05:56

Perhaps some util lib that can be used across more graalvm projects

borkdude18:05:02

but again, the name

borkdude18:05:40

I have another function that could be in it: "exec"-ing the current process into another one

borkdude18:05:01

Perhaps I should call the lib babashka.native

borkdude18:05:14

or babashka.os

jeroenvandijk18:05:47

Babashka.x πŸ˜…

borkdude18:05:31

What does the x stand for?

borkdude18:05:49

perhaps babashka.svm or babashka.graal or so

jeroenvandijk18:05:56

There are probably better names indeed

borkdude18:05:21

those calls only work in a native image so the name must probably reflect that

jeroenvandijk18:05:03

So it would be a library specific to native image or even a smaller subset?

borkdude18:05:12

yes, set-env and exec sould only work in a native image. but those functions could be useful to all graalvm native projects

borkdude18:05:34

but I could also make a babashka.aux library with all sorts of useful functions

borkdude18:05:43

e.g. get-env could also be in there

jeroenvandijk19:05:02

My 2 cents; I don’t recognize the name svm, but maybe other graal people do. aux could be anything I guess. So graal and native sound most descriptive to me.

kokada21:05:32

I would suggest to follow the Python naming suggestions here, so babashka.os seems ok to me

kokada21:05:24

babashka.graalvm.os doesn't seem bad too, or some variation of it

kokada21:05:53

(But not sure about native, this may be confusing depending of the context)

borkdude21:05:19

yeah, I like babaska.os as well, but we also have babashka.process

kokada21:05:29

For me this split makes sense, for the same reason Python has subprocess and os

borkdude21:05:29

but it would be confusing maybe to have get-env in babashka.process since process is about spawning new processes and os is about the current process perhaps?

kokada21:05:11

IMO, os for me is for calling OS specific calls, so Python's os exposes things like os.chdir and os.getenv (but there are implementations for them on Windows too, even when they're no-ops)

kokada21:05:19

While process is related to subprocess

borkdude21:05:50

yeah, I like it

borkdude21:05:28

Right now I'm testing set-env in babashka itself. There it doesn't work, weirdly enough.

2
borkdude21:05:36

While in the isolated case it works.

kokada21:05:46

BTW, any reason this library needs to be GraalVM specific? For example, couldn't we use JNI to implement a Java version compatible :thinking_face: ?

kokada21:05:46

(Not saying that you need to implement it, just asking if it wouldn't make sense to make it more "generic")

borkdude21:05:11

Yeah, if that works, I would be ok with it. Not sure if that works though :)

borkdude21:05:33

$ ./bb -e '(babashka.utils/set-env "FOO" "BAR") (prn (System/getenv "FOO"))'
:setting "FOO" "BAR"
setenv FOO BAR
null
null
nil

borkdude21:05:43

(branch set-env :-s)

kokada21:05:32

Well, let me try this on Linux

borkdude21:05:08

Note that the standalone case (in original post) does work

kokada21:05:57

Thanks, this saves me the working of trying to build it πŸ™‚

borkdude21:05:12

These binaries are posted to #babashka-circleci-builds

kokada21:05:02

> These binaries are posted to #babashka-circleci-builds I always forget about this πŸ˜…

kokada21:05:20

Tried the same example as above, yep, not working

kokada21:05:26

Well, let me setup a GraalVM environment since I generally build those things with Docker πŸ˜…

kokada21:05:32

./setenv foo bar
?

borkdude21:05:48

it should print bar

kokada21:05:21

./setenv foo bar
bar
Yep, looks ok

borkdude21:05:34

ok, I copied that code over to babashka

borkdude21:05:41

and there it doesn't work, weird right

kokada21:05:26

Yeah, weird

borkdude22:05:46

I also printed the return value now. It's 0.

$ ./bb -e '(babashka.utils/set-env "FOO" "bar") (prn (System/getenv "FOO"))'
:setting "FOO" "bar"
setenv FOO bar
null
null
0
nil

borkdude22:05:55

which suggests it should work right

kokada22:05:09

Maybe it is not propagating to the Babashka process :thinking_face: ?

kokada22:05:50

Can you print the result of System/getenv right after setting it (still inside the Java code)?

kokada22:05:59

Ah sorry, looking at the code this is exactly what you do

kokada22:05:10

And right there it is already returning null

kokada22:05:12

BTW, if this ever work correctly maybe it makes sense to also implement unsetenv

kokada02:05:03

Well, it is really strange:

diff --git a/src-java/babashka/impl/Graal.java b/src-java/babashka/impl/Graal.java
index 9754185..604b5f6 100644
--- a/src-java/babashka/impl/Graal.java
+++ b/src-java/babashka/impl/Graal.java
@@ -18,23 +18,22 @@ public class Graal {
 
         @Override
         public List<String> getHeaderFiles() {
-            return Collections.singletonList("<stdlib.h>");
+            return Collections.singletonList("<stdio.h>");
         }
     }
 
     @CFunction
-    private static native int setenv(CCharPointer name, CCharPointer value, int overwrite);
+    private static native int puts(CCharPointer name);
 
     // API
     public static int setEnv(String name, String value) {
-        int ret = 0;
+        int ret = -1;
         System.out.println("setenv" + " " + name + " " + value);
         try (CCharPointerHolder nameHolder = CTypeConversion.toCString(name);
              CCharPointerHolder valueHolder = CTypeConversion.toCString(value)) {
-            ret = setenv(nameHolder.get(), valueHolder.get(), 1);
-            System.out.println(System.getenv(name));
+            ret = puts(nameHolder.get());
+            System.out.println(Integer.toString(ret));
         }
-        System.out.println(System.getenv(name));
         return ret;
     }
user=> (babashka.utils/set-env "this is the text that should be printed" "")
:setting "this is the text that should be printed" ""
setenv this is the text that should be printed
this is the text that should be printed
40
40
nil
Definitively seems to be working, but the setenv does seems to do its job but it doesn't actually set the variable :thinking_face:

borkdude10:05:59

In the latest commit on the set-env branch this now works:

$ ./bb -e "(require '[babashka.os :as os])" -e '(prn (os/set-env "FOO" "BAR")) (prn (os/get-env "FOO"))'
true
"BAR"

jeroenvandijk10:05:22

Nice! FOO should also be set outside of bb, right? So echo $FOO returns "BAR"?

borkdude10:05:41

I don't think that is how it works

borkdude10:05:54

a process cannot set the environment of the parent process I think

jeroenvandijk10:05:10

Ah ok so it would be useful for processes relying on env vars invoked from within the babashka process, is that right?

borkdude10:05:20

yeah, although I don't know if processes invoked from babashka using processbuilder will even see the effect, since Java has its own way of handling this

borkdude10:05:23

ah good, that seems to work:

./bb -e "(require '[babashka.os :as os])" -e '(prn (os/set-env "dude" "1337")) @(babashka.process/process ["env"] {:inherit true})'

borkdude10:05:44

but you can already set those env vars as an arg to babashka.process so for that use case it doesn't really matter

jeroenvandijk11:05:00

Maybe for nested process calls that you dont control :thinking_face:

kokada13:05:56

Well, this cache actually makes sense since there is no way to set environment variables in JDK

kokada13:05:01

Good to know that it works

borkdude13:05:25

I discovered also a Windows edge case. They don't support setenv, only _putenv ;)

borkdude13:05:41

which looks like _putenv("FOO=bar");

borkdude13:05:50

no problem, can work around it ;)

kokada13:05:58

@U04V15CAJ Could we also have unsetenv wrapper?

borkdude13:05:01

but all in all it may not be such a good idea to include this, although it works

borkdude13:05:42

@UFDRD93RR sure, we can support it if it works with GraalVM. But why would we do so?

kokada13:05:20

For my usecase, I would like to set environment variables for the current process since I use them for some things While I could use another mechanism to have this "state" (like an atom), the subprocess also needs to inherit those environment variables So to use atom+`babashka.process`, I would probably need to always inject this environment variables to every subprocess (not exactly bad, but this gets old quickly)

borkdude13:05:09

@UFDRD93RR we could support this, but it can be confusing when people also use System/getenv

borkdude13:05:29

so as a rule: when you use os/set-env you should also use os/get-env

kokada13:05:42

We could document this no :thinking_face: ?

borkdude13:05:51

but if a library already uses System/getenv it doesn't work as expected for them

borkdude13:05:29

e.g. (os/set-env "JAVA_CMD" "foo/java") followed by (clojure "something") would not work, since clojure uses System/getenv

kokada13:05:33

Huh... Good point

borkdude13:05:15

In bb tasks you could accomplish setting an env variable with (shell {:extra-env {"FOO" "BAR"}} "bb some-other-task")

borkdude13:05:44

just invoke bb another time

kokada13:05:45

Huh... You gave me a good idea

kokada13:05:51

To have a task that starts the program

kokada13:05:01

With the correct environment variables set

kokada14:05:01

Well, I think it will not work for this case

kokada14:05:17

Since I need to parse the filename from the current script too

borkdude16:05:16

@UFDRD93RR Can you explain what you mean by this?

kokada16:05:35

Well, it is actually complicated We have a binary (let's call foo) that is symlinked multiple times including the country info So foo-br is "foo for Brazil", foo-mx is "foo for Mexico" So I have to get the current script filename, parse it and set the environment variable (`FOO_COUNTRY=br` for foo-br)

kokada16:05:53

Nowadays we use the (in)famous #_shell code here hack

kokada16:05:12

There is some alternatives, I could create a separate file that calls the main one and just set this environment variable

kokada16:05:23

But after analyzing the code, the actual code works well enough and I don't think it would have any advantage of changing this now

kokada16:05:39

Just reducing the usage of shell, but it is already small enough

kokada16:05:26

(BTW, the most usage of the shell in this case is actually another shell script that I use to bootstrap babashka if not installed, this script can't be written in Babashka anyway since I would have a classic chicken-egg problem)

borkdude16:05:40

So is there any change you want or is it fine like it is?

kokada16:05:09

IMO, I would like to have something like babashka.os/set-env, but only if we could make it work with System/getenv, otherwise I think the drawbacks are worse than the benefits

borkdude16:05:44

we could patch System/getenv but this would not work with calls that don't go through the interpreter

borkdude16:05:09

so my initial hunch is not to hack it in, unless we see clear benefits

kokada16:05:04

I think we can leave as is, if I (or someone else) find some case that it can't be workaround without changing the current env we could add with all the warnings and bells

kokada16:05:34

(I feel like that I may hit this issue in the future again, but I also feel that this would be a good time to rethink the way do some things)

kokada16:05:20

@U04V15CAJ Sorry about all the inconvenience about this, at least we now know that this is possible (with caveats)

borkdude17:05:45

@UFDRD93RR Absolutely no problem, I just started investigating to see if it was possible at all. And now I learned a bunch about C interop ;)

πŸ™Œ 2
kokada17:05:48

Yeah, I found it fantastic that it is relatively easy to do C interop in GraalVM, and also the binary is still static (at least when using C stdlib)

borkdude17:05:38

yeah, I learned that when you do JNI the binary is no longer static

borkdude17:05:06

this is a benefit of using the C interop by GraalVM, that musl binaries can still be fully static

πŸ‘ 2