Starting a new ClojureScript project in 2022. Setup suggestions

Yes precisely. I was going to say it should be all of three to five commands to go from nothing installed to a project not only installed but running in active development.

I use jenv to manage which jdk I currently have in operation and if I run into mystery issues I’ll often just jump back and forth between, say, graal, openjdk or oracle just for kicks.

I feel like these odd issues just come down to something going wrong with some link in the chain. Which making sure versions match and software is installed properly generally fixes.

I don’t believe that’s it. 1.11.1.xxxx will all fall under the same 1.11.1 version when declaring dependencies per-project

1 Like

You could still use brew on Linux, that’s what I do as well, I’d recommend it, does make a lot of things easier when there’s isn’t always official Ubuntu repo packages for all the things. Just FYI: Homebrew on Linux — Homebrew Documentation

What happens when you run:

clj -version

The Clojure CLI is pretty new, and things were changing quite quickly, so ya, even a minor version could have added the tools supports.

I would also try:

clojure -T

Don’t type clj, type clojure. I’d be surprised, since both work for me, but I’m currently on a mac, so maybe rlwrap does something weird for you.

Otherwise, there’s something wrong maybe with your install.

Also, if you don’t want to learn how to use the new official build and deps tooling and Clojure command line, you can still use lein, a lot of people still use lein. You can at any time in the future choose to learn the new stuff and migrate your project to them.

clj -version
WARNING: When invoking clojure.main, use -M
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
-version (No such file or directory)

Full report at:
/tmp/clojure-2320301461189067898.edn

Meanwhile

clojure -T
-T is no longer supported, use -A with repl, -M for main, or -X for exec

clj -version
WARNING: When invoking clojure.main, use -M
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 > (FileInputStream.java:-2).
-version (No such file or directory)

Ok, can you just try uninstalling and re-installing?

Something is definitely wrong on your side.

Did you alias clj in your shell to something specific?

Seconding everything said by didibus.

I’m sorry this is frustrating because I sympathize when trying to start an effort seemingly fails for me before I can even get to step 1! It’s happened to me a lot. I hope you can get it dialed in because I’ve found the fruits of developing in this environment so rewarding.

I personally am absolutely no expert with any step of software development. Let alone the complexities of this language which has struck me from day 1 as advanced! But major steps have been taken by a lot of hands to smooth out the sharp corners.

These errors look really unusual and unrelated to any of the project tooling we’re discussing here. I’d emphasize reinstalling fresh. I also advocate for homebrew on unix-like systems.

1 Like

Ah … this is interesting.

One of the things I had been trying was @seancorfield’s instructions here : GitHub - seancorfield/clj-new: Generate new projects based on clj, Boot, or Leiningen Templates!

Specifically with the section entitled “Installation via deps.edn”

In that directory I had made a deps.edn file based on his suggestion there. And when I ran

clj -Mtools 

I got

clj -Mtools
Clojure 1.11.1
user=> 

But actually when running the same thing outside that directory, I’m seeing

clj -Mtools
Clojure 1.10.1
user=> 

So maybe I only have 1.10.1 installed “globally” and I was being misled by trying some of the things in that local context that was defined by having that deps.edn in the directory.

This would probably explain some of the mystery.

So, OK, what I need to do is to update Clojure cli.tools from 1.10 to 1.11

Is there really no way to do that except using homebrew? I don’t really want to bring yet another package manager into my life, as I already seem to have way too many.

But I assume clj doesn’t know how to upgrade itself then?

Ya, there’s a shell script installer as well, see here:
https://clojure.org/guides/install_clojure

1 Like

OK. Thanks.

I think I must have used that the first time I installed clj.tools, but at some point afterwards I must have allowed Ubuntu’s package manager to take over.

Though, do you remember how you installed it in the first place? You probably want to follow the same?

Like it’s possible someone packaged Clojure inside of apt.

1 Like

Exactly, there IS a clojure apt package. And that’s still at 1.10.1

I think I did install clojure.tools from Clojure’s own download script once upon a time. But I must have seen that at some point and thought it better to let apt take over.

Obviously that’s part of my problem. And I’ll at least solve that.

Then back to the main issue of creating a project :slight_smile:

Though I think it would be good if ANY of the tools / methods I tried to create new projects with could have just accurately reported that the reason they failed was that my version was outdated. :-/

I’m still very mystified that everyone recommends clj -Tsomething and I was getting

-T is no longer supported, use -A with repl, -M for main, or -X for exec

if the problem was that my stuff was outdated. Has -T been brought back as an option?

Nice!

Check out these changelogs.

1.10.3.933 (July 28, 2021)

  • Tools - git-based programs that can be installed with a local name. Tools can provide their own usage context in deps.edn.

    • Added new auto-installed tool named tools with functions install, list, remove. See reference.
    • Install a tool with clojure -Ttools install <lib> <coord> :as <toolname>
    • Run a tool with clojure -T<toolname> fn (also takes -X style args)

Clojure CLI

  • New -T option is like -X (executes a function) but does not use the project classpath, instead uses tool classpath (and adds :paths ["."] by default). -T:aliases is otherwise same as -X. -Ttoolname resolves named tool by name and uses that tool lib.

1.10.3.1020 (Nov 5, 2021)

Clean up exception handling for -X/-T

1.10.3.1040 (Dec 1, 2021)

  • Improved error handling for unknown tool with -T or -X:deps find-versions

So the tools flag was added a lot more recently than I thought. I was assuming it was created sometime before 1.10, then that’s my mistake in initially posting and not having a disclaimer about minimum version requirements. Hope it’s getting on the right track

1 Like

Ya it was brought back, but as a different thing. Like I said, the CLI was quickly iterating for a bit, trying to figure out how to best work, taking feedback from people, and making changes.

Also, the version of Clojure your project or REPL uses, and the version of the Clojure CLI you have don’t have to be the same. You can use the CLI and tools.deps with an older Clojure version to pull down a newer Clojure version to launch your own REPL or APP.

Might be a bit confusing, but it also makes sense in a way.

The Clojure CLI is a bash script with shell commands like -T, -M, -X, -version, and all that.

The shell script delegates the implementation of most commands to a Clojure program which is tools.deps. Tools.deps itself will depend on the “global” version of Clojure installed to run. But what tools.deps does is pull down dependencies to run other Clojure programs, your own basically, so it can pull down a newer version of Clojure to use locally for your project, even if your global version in older.

My point is, don’t think of clj and clojure command as Clojure itself, think of them as the Clojure CLI (command line interface), which is not the actual Clojure compiler and runtime.

4 Likes

And, since I’m here explaining. lein was like a self-contained thing, it did make it a bit easier, but it was not as simple or extendable.

You had all the plugins that would try and monkeypatch things, and it was hard to externally maintain and all that.

Now things are a bit more separated into different area of responsibilities.

  1. The Clojure CLI (command line interface)

First, you got the command line interface, which is clojure. Like I said, that’s a shell script, its all the commands you have to do things like start a REPL, launch an application (within the context of an alias), and all that.

  1. Tools.deps

This manages dependencies and settings for launching Clojure programs with the right set of dependencies and the correct main or init function to call. It’s a Clojure library, you can use it as a library, or you can use it through the Clojure CLI.

This library is configured with the deps.edn file where you can specify paths and dependencies and all that.

  1. Tools.build

This manages build tasks, like generate doc, run tests, create an Uberjar, etc.

This is also a Clojure library, and it is always used as a library. So the way its meant to be used is you create a Clojure program, by convention build.clj at the root, and from that program you require tools.build. Then you do whatever you want for your build tasks leveraging tools.build to make it easier.

Finally, the magic trick that this all creates is that everything just becomes simple Clojure programs with utility libraries. And since the Clojure CLI can be used to launch Clojure programs, that’s all you need to create new “commands” on the CLI itself.

It means you don’t have to change the CLI code to add a new CLI “command”. You can just specify an alias, and use -M, -T, -T:, or -X to call the “command”, which is just a Clojure program exposing either a main method -M, or a callable function -X.

And depending if the program needs to be launched within the context of your project or not, you use -T or -T: instead of -M and -X.

Its a bit less easy at first, but once you get it, it makes a lot more sense, where lein was more magical and obtuse. The new way builds upon simple things that combine.

9 Likes

Well yes.

Thanks, that’s one of the best explanations I’ve seen. And I kind of understand a lot better.

Nevertheless I don’t think it was necessary to expose quite so much breakable dependency management on the users, even if the Clojure team wanted a more flexible system built from components.

I’m sure it would have been possible to give users an experience somewhere between the lein “just works” one and the current degree of confusion without sacrificing this flexibility.

I don’t see why, for example, tools.build and tools.deps couldn’t have been written to work with older versions of Clojure itself. They presumably aren’t doing anything very exotic or cutting edge. Just reading EDN and pulling files from remote servers. Does that need to be version 1.11.1.x as opposed to anything after about 1.5? And if they needed a recent version of the CLI itself, why couldn’t they just say “Sorry, this tool needs CLI version X” which would be far easier address?

Anyway, I’ve now upgraded and seem to have successfully installed clj-new, so now onto my next problems.

I do think there can be something between lein and this, but I think the core team expects the community to figure what that is, and build it on top of the core abstractions. There’s this for example: GitHub - babashka/neil: A CLI to add common aliases and features to deps.edn-based projects. that does make things feel a bit more “lein” like.

It does work with older versions of Clojure as well. But the commands you were running didn’t work with older versions of the CLI.

What you’re asking for is forward compatibility. You want newer commands to work with older CLIs.

What it gives you is only backwards compatibility, older commands will still work, or throw an appropriate error, when used with newer versions of the CLI.

There’s very little software that ever promises forward compatibility, because how can you make new things work with old things?

You did hit a bit of a confusing edge case I admit, where at the time the error message would have been correct, and what used to be done with -T did need to be done with -M, but since then has also changed to no longer be the case. It was like a good intention of making it clear at the time that turned into a more confusing message later for you. Not sure it was easy to predict.

I will grant you one thing, knowing what version you’re using of the CLI and finding the documentation appropriate for that version is not easy. I’ve been bitten by it as well, where you look at the documentation on clojure.org (or follow along some blog) and assume you’ve got the same version, but it turns out not.

That said, I expect this to stabilize all quite soon, and these will be forgotten inconveniences.

2 Likes

We had a better on-ramping story in 2012. 10 years later, I would hesitate to bring someone in under the new vision - which is still undergoing breaking changes. Most of these “new” problems were already forgotten (albeit with different classes of gripes) under the legacy tooling.

At least with lein, you had a project.clj and a single point of confusion / source of truth (localized to the project level, with some external complexity if profiles.clj entered into the mix). Now you need to manage deps.edn and its aliases, tools.build and its build.clj, and glue them together to approximate what we already had - with the side benefit of having more flexibility and purity going forward. It is reminding me of the configuration morass that cropped up with the cljs tooling. I question if the juice was worth the squeeze at this point, but the herd has moved forward.

4 Likes

We had a better on-ramping story in 2012.

Yes!

1 Like

Copied from other thread:

I seem to have found a solution that works for me. Using clj-new (which now works thanks to me updating to most recent CLI tools) and the figwheel-main template.

clojure -Tclj-new create :template figwheel-main :name myname/myapp :args '["+deps","–reagent"]'

Then run the app with

clojure -M:fig:build

I hope this helps anyone else with similar confusion to me.

Thanks again everyone.

Yeah, it’s shocking how hard it is to fire up a new clojure project. I’m sure clojure is losing loads of potential users due to how frustrating the tooling is just to get started.

Even now I tend to copy an older project and delete everything that I don’t want in new one.

1 Like

What gets me is not so much that it’s hard.

But that it’s way HARDER than it was 10 years ago.

That should horrify everyone who loves Clojure.

Or rather, it’s probably still OK … in general … to use Lein. But because of so much contradictory documentation out there, it’s more confusing than in 2014 when Lein was your only and default choice. Now more than half of the introductory / beginners / tutorial web pages you’ll find will be giving you contradictory, confusing and possibly non-working advice.