I have a Scala project that contains both Scala classes/objects as well as scripts. I am trying to run the scripts (that use the classes/objects to perform various actions) from command line. The way I am looking to do this is to create a shell that would be passed as argument the name of the script, as well as the arguments that the script itself takes.
My folder structure is as follows:
runner.sh -> script I am trying to implement to run the Scala scripts
bin/ -> script I am trying to implement to run the Scala scripts
lib/ -> -> rest of scala project, packed as multiple jars
I am currently creating a variable LIB_CLASSPATH
in the shell script that contains the contents of the lib/
folder and I am trying to run my scrips as follows:
java -cp $LIB_CLASSPATH ./bin/<name_of_script.scala> <parameters of the script>
I always get back the same error:
Could not find or load main class: ..lib/<name of jar>
-- <name of jar> is actually the first jar in the lib/ folder
I could use some guidance :)
Thanks
You can use Ammonite
(written by @lihaoyi).
It's a combination of a better Scala REPL, Shell, OPs library, and Script runner.
See the docs here - http://www.lihaoyi.com/Ammonite/
10 min talk showing how is it better for scripting & shell - https://www.youtube.com/watch?v=wk2-ZsQU358
I think it can be a good starting point as well. Talk was given by me :)
I would recommend using sbt native packager. See:
https://github.com/sbt/sbt-native-packager
You add this line to build.sbt:
enablePlugins(JavaAppPackaging)
And define a main class:
mainClass in Compile := Some("org.shapelogic.sc.javafx.ViewGui")
To run:
sbt stage
It create startup script located in a place like this:
target/universal/stage/bin/shapelogic
Here is an example of how I used the script:
target/universal/stage/bin/shapelogic -- -i image/440px-Lenna.png
If you want to run another class you can do this:
target/universal/stage/bin/shapelogic -main "org.shapelogic.sc.script.Threshold" -- i image/440px-Lenna.png
Here's a script that will do what you want. It's based on a script I use, but stripped down for clarity:
#!/bin/bash
# copies of or symlinks to all required jar files
# must be in one of the directories referenced by CP
if [ $# -eq 0 ]; then
echo "usage: ${0##*} <scala-script-path>" 1>&2
exit 1
fi
REQUIRED_JAR_DIRECTORIES=(
"/usr/local/olib/*"
"/usr/local/jlib/*"
)
CP=$(echo "${REQUIRED_JAR_DIRECTORIES[@]}" | tr ' ' ':')
case `uname` in
CYGWIN*)
CP=`cygpath -p -w "$CP"`
;;
esac
scala -deprecation -feature -classpath "$CP" "$@"
The easiest way to use this script is to place it in your PATH, and then add the following hash-bang line to the top of your scala script. Assuming you call this script 'scalaRunner', here's a standalone working scala script:
#!/usr/bin/env scalaRunner
println("Hello World!")
Here's one that's slightly more elaborate:
#!/usr/bin/env scalaRunner
if( args.isEmpty ){
printf("usage: <arg1> [<arg2> ..]\n")
sys.exit(1)
}
for( (arg,i) <- args.zipWithIndex ){
printf("arg %d: %s\n",i,arg)
}
If you import anything, just make sure all required jars are in the REQUIRED_JAR_DIRECTORIES.
In practice, you may want something more flexible than this script, especially with regard to specifying where required jars reside.