From 5a538d1c57ea9778064411646153b6f41ac6f380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Wro=C5=84ski?= Date: Thu, 29 Dec 2022 17:45:00 +0100 Subject: [PATCH] Add support for running jar as an input --- .../main/scala/scala/build/CrossSources.scala | 1 + .../scala/scala/build/input/Element.scala | 5 +++++ .../scala/build/input/ElementsUtils.scala | 1 + .../main/scala/scala/build/input/Inputs.scala | 1 + .../preprocessing/JavaPreprocessor.scala | 19 +++++++++++++++++-- .../cli/integration/RunTestDefinitions.scala | 18 ++++++++++++++++++ website/docs/commands/run.md | 13 +++++++++++++ 7 files changed, 56 insertions(+), 2 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/CrossSources.scala b/modules/build/src/main/scala/scala/build/CrossSources.scala index ee6a063894..ba74c309e3 100644 --- a/modules/build/src/main/scala/scala/build/CrossSources.scala +++ b/modules/build/src/main/scala/scala/build/CrossSources.scala @@ -268,6 +268,7 @@ object CrossSources { else if (sourcePath.ext == "scala") Right(Seq(SourceScalaFile(dir, subPath))) else if (sourcePath.ext == "sc") Right(Seq(Script(dir, subPath))) else if (sourcePath.ext == "java") Right(Seq(JavaFile(dir, subPath))) + else if (sourcePath.ext == "jar") Right(Seq(JarFile(dir, subPath))) else if (sourcePath.ext == "md") Right(Seq(MarkdownFile(dir, subPath))) else { val msg = diff --git a/modules/build/src/main/scala/scala/build/input/Element.scala b/modules/build/src/main/scala/scala/build/input/Element.scala index 798b7be7ed..b8160ca73c 100644 --- a/modules/build/src/main/scala/scala/build/input/Element.scala +++ b/modules/build/src/main/scala/scala/build/input/Element.scala @@ -85,6 +85,11 @@ final case class JavaFile(base: os.Path, subPath: os.SubPath) lazy val path: os.Path = base / subPath } +final case class JarFile(base: os.Path, subPath: os.SubPath) + extends OnDisk with SourceFile { + lazy val path: os.Path = base / subPath +} + final case class CFile(base: os.Path, subPath: os.SubPath) extends OnDisk with SourceFile with Compiled { lazy val path: os.Path = base / subPath diff --git a/modules/build/src/main/scala/scala/build/input/ElementsUtils.scala b/modules/build/src/main/scala/scala/build/input/ElementsUtils.scala index 00cad854d7..3c7acddc34 100644 --- a/modules/build/src/main/scala/scala/build/input/ElementsUtils.scala +++ b/modules/build/src/main/scala/scala/build/input/ElementsUtils.scala @@ -59,6 +59,7 @@ object ElementsUtils { case _: CFile => "c:" case _: Script => "sc:" case _: MarkdownFile => "md:" + case _: JarFile => "jar:" } Iterator(prefix, elem.path.toString, "\n").map(bytes) case v: Virtual => diff --git a/modules/build/src/main/scala/scala/build/input/Inputs.scala b/modules/build/src/main/scala/scala/build/input/Inputs.scala index ea160995d1..24e70d9fd4 100644 --- a/modules/build/src/main/scala/scala/build/input/Inputs.scala +++ b/modules/build/src/main/scala/scala/build/input/Inputs.scala @@ -286,6 +286,7 @@ object Inputs { else if arg.endsWith(".sc") then Right(Seq(Script(dir, subPath))) else if arg.endsWith(".scala") then Right(Seq(SourceScalaFile(dir, subPath))) else if arg.endsWith(".java") then Right(Seq(JavaFile(dir, subPath))) + else if arg.endsWith(".jar") then Right(Seq(JarFile(dir, subPath))) else if arg.endsWith(".c") || arg.endsWith(".h") then Right(Seq(CFile(dir, subPath))) else if arg.endsWith(".md") then Right(Seq(MarkdownFile(dir, subPath))) else if os.isDir(path) then Right(Seq(Directory(path))) diff --git a/modules/build/src/main/scala/scala/build/preprocessing/JavaPreprocessor.scala b/modules/build/src/main/scala/scala/build/preprocessing/JavaPreprocessor.scala index 84acac1b96..5dbbec0566 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/JavaPreprocessor.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/JavaPreprocessor.scala @@ -9,9 +9,9 @@ import java.nio.charset.StandardCharsets import scala.build.EitherCps.{either, value} import scala.build.Logger import scala.build.errors.BuildException -import scala.build.input.{Inputs, JavaFile, SingleElement, VirtualJavaFile} +import scala.build.input.{Inputs, JarFile, JavaFile, SingleElement, VirtualJavaFile} import scala.build.internal.JavaParserProxyMaker -import scala.build.options.BuildRequirements +import scala.build.options.{BuildOptions, BuildRequirements, ClassPathOptions} import scala.build.preprocessing.ExtractedDirectives.from import scala.build.preprocessing.PreprocessingUtil.optionsAndPositionsFromDirectives import scala.build.preprocessing.ScalaPreprocessor._ @@ -109,6 +109,21 @@ final case class JavaPreprocessor( } Some(res) + case jar: JarFile => Some(either { + val buildOptions = BuildOptions().copy( + classPathOptions = ClassPathOptions( + extraClassPath = Seq(jar.path) + ) + ) + Seq(PreprocessedSource.OnDisk( + jar.path, + Some(buildOptions), + Some(BuildRequirements()), + Nil, + None, + None + )) + }) case _ => None } } diff --git a/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala b/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala index a4b7e698ef..194aa6d923 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala @@ -1008,6 +1008,24 @@ abstract class RunTestDefinitions(val scalaVersionOpt: Option[String]) } } + test("run jar file") { + val inputs = TestInputs( + os.rel / "Hello.scala" -> + s"""object Hello extends App { + | println("Hello World") + |}""".stripMargin + ) + inputs.fromRoot { root => + // build jar + val helloJarPath = root / "Hello.jar" + os.proc(TestUtil.cli, "package", ".", "--library", "-o", helloJarPath).call(cwd = root) + + // run jar + val output = os.proc(TestUtil.cli, helloJarPath).call(cwd = root).out.trim() + expect(output == "Hello World") + } + } + if (actualScalaVersion.startsWith("3")) test("should throw exception for code compiled by scala 3.1.3") { val exceptionMsg = "Throw exception in Scala" diff --git a/website/docs/commands/run.md b/website/docs/commands/run.md index 45b5a2fd01..3702eada26 100644 --- a/website/docs/commands/run.md +++ b/website/docs/commands/run.md @@ -106,6 +106,19 @@ You can also add java options with the using directive `//> using javaOpt`: //> using javaOpt "-Xmx1g", "-Dfoo=bar" ``` +### JAR + +`scala-cli` lets you run JAR files just like any other input. + +```bash ignore +scala-cli Hello.jar +``` + +```text +Hello World +``` + +When you provide a JAR file as input to `scala-cli`, it will be added to the `classPath`. ## Define source files in using directives