Skip to content

Commit

Permalink
Add support for passing java properties into scala-cli from .scala-jv…
Browse files Browse the repository at this point in the history
…mopts
  • Loading branch information
lwronski committed Jul 6, 2023
1 parent e4d1c9e commit 9e3a5c3
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 5 deletions.
4 changes: 3 additions & 1 deletion build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import $file.project.settings, settings.{
localRepoResourcePath,
platformExecutableJarExtension,
workspaceDirName,
projectFileName
projectFileName,
jvmPropertiesFileName
}
import $file.project.deps, deps.customRepositories
import $file.project.website
Expand Down Expand Up @@ -428,6 +429,7 @@ trait Core extends ScalaCliSbtModule with ScalaCliPublishModule with HasTests
|
| def workspaceDirName = "$workspaceDirName"
| def projectFileName = "$projectFileName"
| def jvmPropertiesFileName = "$jvmPropertiesFileName"
|
| def defaultGraalVMJavaVersion = ${deps.graalVmJavaVersion}
| def defaultGraalVMVersion = "${deps.graalVmVersion}"
Expand Down
21 changes: 19 additions & 2 deletions modules/cli/src/main/scala/scala/cli/ScalaCli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,33 @@ object ScalaCli {
s"Java >= 17 is required to run $fullRunnerName (found Java $javaMajorVersion)"
)

private def loadJavaPropertiesFromResources() = {
def loadJavaProperties(cwd: os.Path) = {
// load java properties from scala-cli-properties resource file
val prop = new java.util.Properties()
val cl = getClass.getResourceAsStream("/java-properties/scala-cli-properties")
if cl != null then
prop.load(cl)
prop.stringPropertyNames().forEach(name => System.setProperty(name, prop.getProperty(name)))
// load java properties from .scala-jvmopts located in the current working directory and filter only java properties and warning if someone used other options
val jvmopts = cwd / Constants.jvmPropertiesFileName
if os.exists(jvmopts) && os.isFile(jvmopts) then
val jvmoptsContent = os.read(jvmopts)
val jvmoptsLines = jvmoptsContent.linesIterator.toSeq
val (javaOpts, otherOpts) = jvmoptsLines.partition(_.startsWith("-D"))
javaOpts.foreach { opt =>
opt.stripPrefix("-D").split("=", 2).match {
case Array(key, value) => System.setProperty(key, value)
case _ => System.err.println(s"Warning: Invalid java property: $opt")
}
}
if otherOpts.nonEmpty then
System.err.println(
s"Warning: Only java properties are supported in .scala-jvmopts file. Other options are ignored: ${otherOpts.mkString(", ")} "
)
}

private def main0(args: Array[String]): Unit = {
loadJavaPropertiesFromResources() // load java properties to detect launcher kind
loadJavaProperties(cwd = os.pwd) // load java properties to detect launcher kind
val remainingArgs = LauncherOptions.parser.stopAtFirstUnrecognized.parse(args.toVector) match {
case Left(e) =>
System.err.println(e.message)
Expand Down
35 changes: 35 additions & 0 deletions modules/cli/src/test/scala/cli/tests/SetupScalaCLITests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cli.tests

import com.eed3si9n.expecty.Expecty.expect

import java.util.Properties

import scala.build.internal.Constants
import scala.build.tests.TestInputs
import scala.cli.ScalaCli
import scala.util.Properties

class SetupScalaCLITests extends munit.FunSuite {

test(s"should read java properties from file") {
val key = "scala-cli"
val value = "true"
val inputs = TestInputs(
os.rel / Constants.jvmPropertiesFileName ->
s"""-Xmx2048m
|-Xms128m
|-Xss8m
|-D$key=$value
|""".stripMargin
)
inputs.fromRoot(root =>
// save current props to restore them after test
val currentProps = System.getProperties.clone().asInstanceOf[Properties]
ScalaCli.loadJavaProperties(root)
expect(sys.props.get(key).contains(value))

// restore original props
System.setProperties(currentProps)
)
}
}
5 changes: 3 additions & 2 deletions project/settings.sc
Original file line number Diff line number Diff line change
Expand Up @@ -836,8 +836,9 @@ trait ScalaCliModule extends ScalaModule {
}
}

def workspaceDirName = ".scala-build"
def projectFileName = "project.scala"
def workspaceDirName = ".scala-build"
def projectFileName = "project.scala"
def jvmPropertiesFileName = ".scala-jvmopts"

final case class License(licenseId: String, name: String, reference: String)
object License {
Expand Down
13 changes: 13 additions & 0 deletions website/docs/under-the-hood.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ In order set them, the `-D` command-line flags must be placed as the first optio
scala-cli -Dfoo1=bar1 -Dfoo2=bar2 run ...
```

The Scala CLI can also load Java properties from the `.scala-jvmopts` file present in the current working
directory and import these Java properties into Scala CLI. Any java options in the `.scala-jvmopts` that are not
recognizable as Java properties will be ignored.

The example below example show that the Java properties `foo1` and `foo2` from the `.scala-jvmopts` file will be passed
into the Scala CLI:
```bash ignore
$ cat .scala-jvmopts
-Dfoo1=bar1
-Dfoo2=bar2
$ scala-cli run ...
```

:::note
- `scala-cli run . -Dfoo=bar` would pass the java property into your Scala app
- `scala-cli -Dfoo=bar run .` would pass the java property into `scala-cli.`
Expand Down

0 comments on commit 9e3a5c3

Please sign in to comment.