Run a main function via its package name

As a Scala newbie I am experimenting with scala-cli and I’m wondering how I can run a main function via its package name (instead via its source code’s file path).

I have a small project with a file structure like this:

├── project.scala
└── src
    └── main
        └── scala
            └── uk
                └── co
                    └── myorg
                        └── myarea
                            └── mypack
                                |── ...
                                |── MyApp.scala
                                └── ...

(I need this deep directory nesting because another package will in future access the package as uk.co.myorg.myarea.mypack.MyApp.)

MyApp.scala consists of a main function

package uk.co.myorg.myarea.mypack.MyApp

...

@main def main(): Unit =
  ...

I want to run this function by specifying the class, so I tried:

scala-cli run scala-cli run uk.co.myorg.myarea.mypack.MyApp

but I get

[error] uk.co.myorg.myarea.mypack.MyApp: input file not found

Even when I make main a “real” class method via

object MyApp:
  def main(args: Array[String]): Unit = 
    ...

it doesn’t work. The only way is by providing the file path:

scala-cli run src/main/scala/uk/co/myorg/myarea/mypack/MyApp.scala

Is there a way to run the main with scala-cli by specifying the class?

Any pointers are greatly appreciated.

does scala-cli run . not work? That should run the main class it finds in the current directory.

Then, to specify a main class…

1 Like

It does work! Very cool! Because there are other main functions (I haven’t talked about above) I do it like this:

scala-cli run . --main-class uk.co.myorg.myarea.mypacktwo.MyApp.main

and it does exactly what I want.

Thanks!

1 Like

Welcome to the Scala community, @halloleo
Glad it worked out! Scala-cli is awesome, and soon it will be just scala (in 3.5).

When in doubt, use

scala-cli run . --interactive

It will show you the full names of the main methods you can run. I have 45 of them:

❯ scala-cli run . --interactive
Starting compilation server
Compiling project (Scala 3.4.2, Scala Native 0.5.4)
Compiled project (Scala 3.4.2, Scala Native 0.5.4)
Found several main classes. Which would you like to run?
[0] ch01.testingBadStuff.run
[1] ch04.badExec.run
[2] ch07.simpleAsync.simpleAsync
[3] ch01.bug.run
[4] ch01.helloNative.run
[5] ch03.httpClient.run
...
1 Like

Hey, one thing to note is that JVM doesn’t understand packages as anything other than a namespace (that contain real things such as classes with main methods). So Scala CLI continues this.

So in general it doesn’t make sense to say “run program of this package name”. Unless you are requesting to scan for programs in that package?

1 Like

Probably @halloleo (Scala beginner, possibly new to Java / JVM as well?) used “package” and “namespace” interchangeably to mean the same thing.

Good point. That’s why scala-cli needs the ., right?

So in this case Scala CLI will understand . as the current directory, which it scans for source files, which then after compilation it scans the compilation output for classes with main methods.