ys can now generate code that can be run by bb:
$ ys -e 'say: 6 * 7'
42
$ ys -ce 'say: 6 * 7'
(say (mul+ 6 7))
$ ys -ce 'say: 6 * 7' --v0 --deps=+bb
(when (System/getProperty "babashka.version")
((requiring-resolve 'babashka.deps/add-deps)
'{:deps {org.yamlscript/ys.v0 {:mvn/version "0.2.27"}}}))
(ns main (:require ys.v0))
(ys.v0/init)
(say (mul+ 6 7))
$ ys -ce 'say: 6 * 7' --v0 --deps=+bb | bb /dev/stdin
42
but this requires that java be available even when the deps are fully satisfied (iow, even when java is never called).
I was going to submit a PR for this, but thought I'd check here in case I was missing something.
Is there a way to require that installed dep without needed java installed?is it required? I wouldn't think so, I may be missing something though
https://github.com/borkdude/deps.clj/blob/7c70e8e04f19fc662d3653609da6929173a4981c/src/borkdude/deps.clj#L272-L286 gets called early here: https://github.com/borkdude/deps.clj/blob/7c70e8e04f19fc662d3653609da6929173a4981c/src/borkdude/deps.clj#L933 and throws when which java or $JAVA_HOME/bin/java are not found. But in my case when the deps are already installed, java is never called.
Here's (somewhat humorous) proof:
$ ys/bin/ys -ce 'say: 6 * 7' --v0 --deps=+bb | bb /dev/stdin
----- Error --------------------------------------------------------------------
Type: java.lang.Exception
Message: Couldn't find 'java'. Please set JAVA_HOME.
Location: /dev/stdin:2:3
----- Context ------------------------------------------------------------------
1:
^--- Couldn't find 'java'. Please set JAVA_HOME.
----- Stack trace --------------------------------------------------------------
borkdude.deps/get-java-cmd -
borkdude.deps/-main -
clojure.core/apply -
babashka.impl.deps/add-deps/fn--24653/fn--24654 -
clojure.core/apply -
clojure.core/with-bindings* -
babashka.impl.deps/add-deps/fn--24653 -
babashka.impl.deps/add-deps -
user - /dev/stdin:2:3
user - /dev/stdin:1:1
$ mkdir bin
$ touch bin/java
$ chmod +x bin/java
$ export JAVA_HOME=$PWD
$ ys/bin/ys -ce 'say: 6 * 7' --v0 --deps=+bb | bb /dev/stdin
42
$ java is required to fetch the deps initially. that it isn't required the second time you actually run it, is only a caching detail
I understand. But I would like to run bb when my deps are already fetched without needing java.
it doesn't call java, it just ensures it's there. why would it be useful to not have java if you need it the first time?
what if there were other ways to fetch deps? or imagine a container image with deps and bb installed. why should that require java? it seems trivial to not check for java until you actually need to use it.
I'm happy to make a PR for this.
> or imagine a container image with deps and bb installed. why should that require java? in this case you probably shouldn't be using add-deps but just use an uberjar or uberscript
deps.clj is mirroring the clj bash script btw, I don't want to make changes that it doesn't have - could you double check that script?
sure. but clj needs java always. bb just needs it for a this stuff.
bb needs java when you use add-deps :)
maybe I misunderstand you. weren't you using add-deps?
in the future this may change btw, the clojure CLI may be getting mvn etc baked in without java via graalvm native-image, but this is the future
My use case is that I want ys to compile to code that can be run with bb.
So I created a org.yamlscript/ys.v0 jar and that will get installed when ys is installed.
$ ys/bin/ys -ce 'say: 6 * 7' --v0 --deps=+bb | bb /dev/stdin
42
That should just work for the next ys release.
But right now it requires java even though bb will never call it.
I got that example above to run with this fake/empty file java executable.
$ ls -l $JAVA_HOME/bin
total 0
-rwxr-xr-x 1 ingy ingy 0 Jul 16 22:05 java*
the code that ys generating for that is:
$ ys/bin/ys -ce 'say: 6 * 7' --v0 --deps=+bb
(when (System/getProperty "babashka.version")
((requiring-resolve 'babashka.deps/add-deps)
'{:deps {org.yamlscript/ys.v0 {:mvn/version "0.2.27"}}}))
(ns main (:require ys.v0))
(ys.v0/init)
(say (mul+ 6 7))
Is there better code for ys to generate for this, that would solve my problem?you could just a fully standalone script without add.deps for bb to run and install that using bbin
either via an uberjar (`bb uberjar` ) or uberscript (`bb uberscript`)
add-deps is great, but not for containers, etc
you could also bypass the deps mechanism by just downloading the jar yourself and add it to the classpath manually
but I think the uberjar approach would be saner
I'm trying to say that I'm fixing ys so that people could use bb to run ys code. but bb is requiring that a java be found and for no reason. I'll never need java for this.
you need java to execute add-deps. what do you not understand about this?
add-deps doesn't call java if I already have org.yamlscript/ys.v0 installed. Installing ys installs that jar.
that's not the only requirement
add-deps is dependent on which script you execute it from, and if there's another bb.edn in your project, and if the classpath has been calculated before. this caching mechanism lives in .cpcache directories. it's not as simple as "the only jar I'm requesting is already there"
but if you're downloading the jar yourself, you could just use bb.classpath/add-classpath to add the jar yourself, no java needed
Alice is a ys user and a bb user but doesn't have java. She installs the newest ys because she heard it could compile to code that works with bb. The ys installer installed the new ys binary and also all the deps jars needed to run any ys code. She gets this when she tries it out:
$ ys/bin/ys -ce 'say: 6 * 7' --v0 --deps=+bb | bb /dev/stdin
----- Error --------------------------------------------------------------------
Type: java.lang.Exception
Message: Couldn't find 'java'. Please set JAVA_HOME.
She doesn't want to install java so she creates a fake java like this:
$ mkdir -p bin; touch bin/java; chmod +x bin/java; export JAVA_HOME=$PWD
now it works:
$ ys/bin/ys -ce 'say: 6 * 7' --v0 --deps=+bb | bb /dev/stdin
42
If bb delayed the java check, this would all just work.If Ingy would read what I wrote about add-classpath, Alice wouldn't have to complain about this ;)
this is a typical example of an X-Y problem. You ask to solve problem X but what you have is actually problem Y which can be solved in a better way since you already know the location of your jar. The answer is (babashka.classpath/add-classpath "your-jar.jar")
Moreover delaying that java check isn't going to fix your problem, it's not how it works (explanation above, please read agani)
I see. I'll try (babashka.classpath/add-classpath "your-jar.jar")
See also bb -cp.
https://book.babashka.org/#usage
@teodorlu I know about bb -cp . I just didn't know about babashka.classpath/add-classpath
But I don't want people to need to do special things for bb.
Including having a java, which is the biggest reason people use bb. (no java required).
So now I have changed things so this works:
$ cat foo.ys
!ys-0
nums =: 3 .. 9
answer =: add(nums*)
name =: ENV.USER:uc1
say: "$name, the answer is '$answer'!"
$ ys --compile --deps=+bb --output=foo foo.ys
$ ls -l foo
-rwxr-xr-x 1 ingy ingy 745 Jul 17 11:18 foo*
$ cat foo
#!/usr/bin/env bb
(when (System/getProperty "babashka.version")
(let [m2 (str (System/getProperty "user.home") "/.m2/repository/")
jars [(str m2 "org/yamlscript/ys.v0/0.2.27/ys.v0-0.2.27.jar")
(str m2 "org/clojure/data.json/2.4.0/data.json-2.4.0.jar")]]
(if (every? #(.exists (java.io.File. %)) jars)
((requiring-resolve 'babashka.classpath/add-classpath)
(clojure.string/join java.io.File/pathSeparator jars))
((requiring-resolve 'babashka.deps/add-deps)
'{:deps {org.yamlscript/ys.v0 {:mvn/version "0.2.27"}}}))))
(ns main (:require ys.v0))
(ys.v0/init)
(def nums (rng 3 9))
(def answer (apply add nums))
(def name (uc1 (get+ ENV 'USER)))
(say (str name ", the answer is '" answer "'!"))
$ ./foo
Ingy, the answer is '42'!
$ bb foo
Ingy, the answer is '42'!
I also had --deps=+bb -o foo generate a shebang line (and make the output file executable), so now the ys user can compile to standalone executables that use bb without even thinking about bb.
I wish it worked with the simpler add-deps genned code I had before but on the bright side this will work without a patched bb.BTW I patched bb like this https://gist.github.com/ingydotnet/f1751167f2fd3d6bda27c44d277680bb
and built a bb from source and moved it to /tmp/bb and it works like this:
$ YS_BB_ADD_DEPS=1 ys --compile --deps=+bb -e 'say: 6 * 7'
(when (System/getProperty "babashka.version")
((requiring-resolve 'babashka.deps/add-deps)
'{:deps {org.yamlscript/ys.v0 {:mvn/version "0.2.27"}}}))
(ns main (:require ys.v0))
(ys.v0/init)
(say (mul+ 6 7))
$ YS_BB_ADD_DEPS=1 ys --compile --deps=+bb -e 'say: 6 * 7' | /tmp/bb /dev/stdin
42
But I'll just stick with the back compat code gen. It's not terrible. 🙂
There isn't even a need to put your jar in mvn and mess with that dir. you could just just make it a text script to download in a folder specific for ys
Good point. I'll need to see how things play out with other dialects like glj lg and jolt.
I am trying to run bb tasks inside a claude cloud sandbox, and it seems there's a corner case bug. I hate to paste AI output verbatim so I'll try to paraphrase:
When there's a proxy whose CA is in a custom trustore (specified for JVM under - and friends), babashka usually works fine. But, if you have a :deps key in your bb.edn, in a fresh environment, babashka will try to first download clojure-tools.zip from clojure/brew-install - and THAT call doesn't respect the trustStore.
babashka will honor CLJ_JVM_OPTS while downloading this stuff
but I guess it could also forward this one to deps.clj - I actually thought it did, but maybe you can point your AI at deps.clj to see if it can verify that
ah ok, that works, thanks. I can't really trust the AI's word these days, they tend to generalise really fast. I will try to isolate in a new session but it seems it might have been a fluke. A separate thing that seems to correct, is that GitHub repos are blocked from within Claude sessions. Not sure what the logic is (even with network being open). So I end up having to download the clj tools from http://download.clojure.org instead and placing them in a well-known location. Unless this is another AI hallucination that I have to double check again.
> GitHub repos are blocked from within Claude sessions do you mean in a sandbox?
you can probably configure this. just ask claude to do it
Yes, in the cloud version of Claude.
you're developing in a box hosted by claude?
Sometimes - I can start a session from my phone. Nothing too special, it's the basic http://claude.ai cloud runtime. It is also useful in routines... bug report -> triage and possible a PR fixing it. Super nice and these days with playwright it can even do browser validation (for webapps).
ah ok
And you can configure environments there so it starts "warm" without the AI trying to figure out how to install whatever you need. Hence me hitting some walls with the weird proxies they have.
let me know if you think deps.clj / bb should change something
well "should" is probably not the right word. E.g. that JDK_JAVA_OPTIONS is already setup by claude for the common java case, but should bb honor that? Arguably not, but it would make it one less paper cut for clojure users.
it does honor CLJ_JAVA_OPTS
I mean, the deps.clj part does
Something else is this github thing: https://code.claude.com/docs/en/claude-code-on-the-web#github-proxy
> The proxy limits GitHub API and release-asset requests to repositories attached to the session, regardless of the environment’s https://code.claude.com/docs/en/claude-code-on-the-web#access-levels. Setup scripts that download release assets from unattached repositories return a 403. Committed files from public repositories are fetched through , which the https://code.claude.com/docs/en/claude-code-on-the-web#security-proxy handles instead. That domain is in the default https://code.claude.com/docs/en/claude-code-on-the-web#default-allowed-domains, so the files stay reachable unless the environment’s https://code.claude.com/docs/en/claude-code-on-the-web#access-levels excludes it.
If bb was downloading the clojure tools from http://download.clojure.org, it would also work fine.
doesn't it do that? I thought the clojure tools are on http://clojure.org
tell me where deps.clj is downloading something from github again.. my context is a little stale ;)
yes, CLJ_JVM_OPTS works great. Just you need ot know that, and Claude doesn't seem to know it. Their sandbox only caters to the mainstream stuff. Perhaps we can open a ticket on the claude side of things to add that 😉
is JDK_JAVA_OPTIONS`` a standard thing? if so, then the JVM called by bb to download the tools should automatically pick up on that
yes, it's a standard thing, introduce in Java 9. It affects JDKs launched by the java command (I guess, all of them). There's an older JAVA_TOOL_OPTIONS that affects also javac/jar/javadoc etc. I'm testing more in the sandbox and will report back.
then I have no clue why it doesn't just work already? maybe you can try to repro this locally?
Seems like bb/deps.clj is trying to download
=== full deps.clj tool-install output (CLJ_JVM_OPTS set, fresh HOME) ===
Clojure tools not yet in expected location: /tmp/tmp.Iqxk9e9wpE/.deps.clj/1.12.4.1618/ClojureTools/clojure-tools-1.12.4.1618.jar
Downloading to /tmp/tmp.Iqxk9e9wpE/.deps.clj/1.12.4.1618/ClojureTools/clojure-tools.zip
java.io.IOException: Server returned HTTP response code: 403 for URL:
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:2028)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1629)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:223)
at ClojureToolsDownloader.main(ClojureToolsDownloader.java:19)
at borkdude.deps$clojure_tools_download_java_BANG_.invokeStatic(deps.clj:524) oh I see
well, we could hammer http://clojure.org instead I guess - I've heard it's a box running in Rich's private AWS account ;)
let me nail that trust store thing first. And I will have to check again to see what's going on. http://raw.githubusercontent.com works but I'm not sure if those are exposed there.
java is only spawned if clj-jvm-options is set. Code snippet:
(or (when *clojure-tools-download-fn* ; (1) custom hook, normally nil
(*clojure-tools-download-fn* {...}))
(when (seq clj-jvm-opts) ; (2) ONLY if CLJ_JVM_OPTS present
(when debug (warn "Attempting download using java subprocess... (requires Java11+)"))
(clojure-tools-download-java! {:url ct-url-str :dest (str zip-file)
:proxy-opts proxy-opts :clj-jvm-opts clj-jvm-opts
:sha256-url sha256-url-str}))
No clue if this should also honor JDK_JAVA_OPTIONS or not... smells like a breaking change to me, your call though 🙂