Coursier: Native Script Runner

Created on 15 Feb 2021  Â·  6Comments  Â·  Source: coursier/coursier

Hello 👋

I am proposing that Coursier should ship with a script runner that can run scripts as native executables. Here is a POC (using Python but I'm happy to rewrite if proposal is accepted) https://gist.github.com/tabdulradi/da4977d006689f775ee9a9dc3d1a8bdd

Coursier contains all the needed functionalities like dependencies fetching and creating native executables from Jars. All we need is to also compile single files and cache the executables somewhere hidden from the user.

Must have Goals:

  • Ability to have external dependencies
  • Ability to run as native second time a script runs
  • Ability to set Scala version (not implemented in the POC)
  • Support multi line shebangs (to play nice with nix-shell interpreter)

Nice to have Goals:

  • Ability to switch between Graal, Scala-native or normal JVM runners (implemented in POC)
  • Not invent syntax for dependencies (implemented in POC as args in the shebang)

Non Goals:

  • Compile multi file scripts
  • Ability to share or distribute the executables

Most helpful comment

Thanks for elaborating Tamer. Sounds useful for an organization which is into Nix. Shame that Scala compiler doesn't like shebangs, it sort-of ruins the developer experience for people who would like to have IDE support for hacks like that (unless one would go for something like JBang edit command).

Since Scala is a flexible language, I imagined a way to support shebangs by introducing some extra values into scope, for example:

@ import scala.language.postfixOps 
import scala.language.postfixOps

@ def / = () 
defined function /

@ def #!/ = new { def bin(slash: Any) = new { def env = "see? valid Scala" } } 
defined function #!/

@ #!/bin/env 
res17: String = "see? valid Scala"

but that becomes a rabbit hole quickly.

All 6 comments

At first, I'd say I'm not sure it's something coursier itself should handle… There's nothing related to compilation in it. It'd be a better fit for Ammonite (see https://github.com/lihaoyi/Ammonite/issues/1119, plus it should be possible to have a native-image-based launcher for Ammonite to run such scripts, possibly by offloading their compilation in Ammonite to bloop), or tsk too.

That said, adding cargo or poetry -like features in cs (to compile or run things) has been brought up in the past, and having those would make sense for new comers I guess…

Let me write an issue about a possible way to extend cs externally, with new commands. Then maybe a project handling what you describe could be picked transparently as an "external sub-command" by cs.

Just so you know, the packaging capabilities of coursier are published in a specific module (io.get-coursier::coursier-launcher) that basically has no dependencies, so it would be easy to re-use that from another project.

Ok, jotted down a few ideas here.

Hi @tabdulradi, would you be okay to share your scripting use-case which involves multi line shebangs nix shell interpreter?

I'm asking because tsk doesn't use the classic shebang on purpose, to keep the source file valid Scala (and get great IDE support in exchange). I'm curious if that decision breaks any usecases (and which ones).

I am referring to NixOs and Nix package manager ability to download and install other interpreters on the fly if the shebang looks some thing like this

#! /usr/bin/env nix-shell
#! nix-shell -i python -p python

print "Hello world!"

In an organisation where everyone has Nix installed, you don't need to ask users to install Python, Scala or whatever you need in your script.
However the target interpreter has to support multiple lines shebang. Something like NodeJs only supports one line shebangs then complain that second line isn't valid Javascript syntax.
Because Scalac doesn't understand shebangs I have to copy the file somewhere and comment out the header.

Thanks for elaborating Tamer. Sounds useful for an organization which is into Nix. Shame that Scala compiler doesn't like shebangs, it sort-of ruins the developer experience for people who would like to have IDE support for hacks like that (unless one would go for something like JBang edit command).

Since Scala is a flexible language, I imagined a way to support shebangs by introducing some extra values into scope, for example:

@ import scala.language.postfixOps 
import scala.language.postfixOps

@ def / = () 
defined function /

@ def #!/ = new { def bin(slash: Any) = new { def env = "see? valid Scala" } } 
defined function #!/

@ #!/bin/env 
res17: String = "see? valid Scala"

but that becomes a rabbit hole quickly.

Was this page helpful?
0 / 5 - 0 ratings