does bb handle aliases? -A:dev and such?
I guess the better questions is how do I load fuctions in to the user namespace?
@cdimara Can you explain your use case?
bb has an :tasks {:init ...}
section where you can put startup code when you invoke a task
It also has a BABASHKA_PRELOADS
environment variable that can contain code that is always executed before anything else
I just wanted to preload some helpful functions in the user namespace for this one project.
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.
> I'm assuming BABASHKA_PRELOADS runs on every evocation of bb?
correct
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
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 π
FWIW I tried the static 0.4.1
release and it works like a charm π
A hack that might be coming to bb some day as well ;)
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"
Nice! FOO
should also be set outside of bb, right? So echo $FOO
returns "BAR"
?
I don't think that is how it works
a process cannot set the environment of the parent process I think
Ah ok so it would be useful for processes relying on env vars invoked from within the babashka process, is that right?
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
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})'
but you can already set those env vars as an arg to babashka.process
so for that use case it doesn't really matter
Maybe for nested process calls that you dont control :thinking_face:
Well, this cache actually makes sense since there is no way to set environment variables in JDK
Good to know that it works
I discovered also a Windows edge case. They don't support setenv
, only _putenv
;)
which looks like _putenv("FOO=bar");
no problem, can work around it ;)
@borkdude Could we also have unsetenv
wrapper?
but all in all it may not be such a good idea to include this, although it works
@thiagokokada sure, we can support it if it works with GraalVM. But why would we do so?
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)
@thiagokokada we could support this, but it can be confusing when people also use System/getenv
so as a rule: when you use os/set-env
you should also use os/get-env
We could document this no :thinking_face: ?
but if a library already uses System/getenv
it doesn't work as expected for them
e.g. (os/set-env "JAVA_CMD" "foo/java")
followed by (clojure "something")
would not work, since clojure
uses System/getenv
Huh... Good point
In bb tasks you could accomplish setting an env variable with (shell {:extra-env {"FOO" "BAR"}} "bb some-other-task")
just invoke bb another time
Huh... You gave me a good idea
To have a task that starts the program
With the correct environment variables set
Well, I think it will not work for this case
Since I need to parse the filename from the current script too
@thiagokokada Can you explain what you mean by this?
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
)
Nowadays we use the (in)famous #_shell code here
hack
There is some alternatives, I could create a separate file that calls the main one and just set this environment variable
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
Just reducing the usage of shell, but it is already small enough
(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)
So is there any change you want or is it fine like it is?
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
we could patch System/getenv
but this would not work with calls that don't go through the interpreter
so my initial hunch is not to hack it in, unless we see clear benefits
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
(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)
@borkdude Sorry about all the inconvenience about this, at least we now know that this is possible (with caveats)
@thiagokokada Absolutely no problem, I just started investigating to see if it was possible at all. And now I learned a bunch about C interop ;)
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
)
yeah, I learned that when you do JNI the binary is no longer static
this is a benefit of using the C interop by GraalVM, that musl binaries can still be fully static
This would be really useful to have, something that I miss from Python in my Babashka scripts
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
(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)
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? ;)
Perhaps some util lib that can be used across more graalvm projects
but again, the name
I have another function that could be in it: "exec"-ing the current process into another one
Basically these three things: https://github.com/babashka/babashka/labels/native
Perhaps I should call the lib babashka.native
or babashka.os
Babashka.x
π
What does the x
stand for?
Exec + a var
perhaps babashka.svm
or babashka.graal
or so
There are probably better names indeed
Than X I mean
those calls only work in a native image so the name must probably reflect that
So it would be a library specific to native image or even a smaller subset?
yes, set-env
and exec
sould only work in a native image. but those functions could be useful to all graalvm native projects
but I could also make a babashka.aux
library with all sorts of useful functions
e.g. get-env
could also be in there
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.
ok thanks
I would suggest to follow the Python naming suggestions here, so babashka.os
seems ok to me
babashka.graalvm.os
doesn't seem bad too, or some variation of it
(But not sure about native
, this may be confusing depending of the context)
yeah, I like babaska.os
as well, but we also have babashka.process
For me this split makes sense, for the same reason Python has subprocess
and os
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?
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)
While process
is related to subprocess
yeah, I like it
Right now I'm testing set-env
in babashka itself. There it doesn't work, weirdly enough.
While in the isolated case it works.
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: ?
(Not saying that you need to implement it, just asking if it wouldn't make sense to make it more "generic")
Yeah, if that works, I would be ok with it. Not sure if that works though :)
$ ./bb -e '(babashka.utils/set-env "FOO" "BAR") (prn (System/getenv "FOO"))'
:setting "FOO" "BAR"
setenv FOO BAR
null
null
nil
(branch set-env
:-s)
Well, let me try this on Linux
Note that the standalone case (in original post) does work
@thiagokokada Here is the built branch: https://19176-201467090-gh.circle-artifacts.com/0/release/babashka-0.4.4-SNAPSHOT-linux-amd64-static.tar.gz
Thanks, this saves me the working of trying to build it π
These binaries are posted to #babashka-circleci-builds
> These binaries are posted to #babashka-circleci-builds I always forget about this π
Tried the same example as above, yep, not working
And this one? https://gist.github.com/borkdude/335c9911cabf4db6d47cc772b4c69d4d
Well, let me setup a GraalVM environment since I generally build those things with Docker π
sure
./setenv foo bar
?yes
it should print bar
./setenv foo bar
bar
Yep, looks okok, I copied that code over to babashka
and there it doesn't work, weird right
Yeah, weird
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
which suggests it should work right
Maybe it is not propagating to the Babashka process :thinking_face: ?
Can you print the result of System/getenv
right after setting it (still inside the Java code)?
Ah sorry, looking at the code this is exactly what you do
And right there it is already returning null
BTW, if this ever work correctly maybe it makes sense to also implement unsetenv