Skip to content

Commit ee0a8b2

Browse files
committed
Add support for passing java properties into scala-cli from .scala-jvmopts
1 parent e4d1c9e commit ee0a8b2

File tree

5 files changed

+73
-5
lines changed

5 files changed

+73
-5
lines changed

build.sc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import $file.project.settings, settings.{
1616
localRepoResourcePath,
1717
platformExecutableJarExtension,
1818
workspaceDirName,
19-
projectFileName
19+
projectFileName,
20+
jvmPropertiesFileName
2021
}
2122
import $file.project.deps, deps.customRepositories
2223
import $file.project.website
@@ -428,6 +429,7 @@ trait Core extends ScalaCliSbtModule with ScalaCliPublishModule with HasTests
428429
|
429430
| def workspaceDirName = "$workspaceDirName"
430431
| def projectFileName = "$projectFileName"
432+
| def jvmPropertiesFileName = "$jvmPropertiesFileName"
431433
|
432434
| def defaultGraalVMJavaVersion = ${deps.graalVmJavaVersion}
433435
| def defaultGraalVMVersion = "${deps.graalVmVersion}"

modules/cli/src/main/scala/scala/cli/ScalaCli.scala

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,33 @@ object ScalaCli {
163163
s"Java >= 17 is required to run $fullRunnerName (found Java $javaMajorVersion)"
164164
)
165165

166-
private def loadJavaPropertiesFromResources() = {
166+
def loadJavaProperties(cwd: os.Path) = {
167+
// load java properties from scala-cli-properties resource file
167168
val prop = new java.util.Properties()
168169
val cl = getClass.getResourceAsStream("/java-properties/scala-cli-properties")
169170
if cl != null then
170171
prop.load(cl)
171172
prop.stringPropertyNames().forEach(name => System.setProperty(name, prop.getProperty(name)))
173+
// load java properties from .scala-jvmopts located in the current working directory and filter only java properties and warning if someone used other options
174+
val jvmopts = cwd / Constants.jvmPropertiesFileName
175+
if os.exists(jvmopts) && os.isFile(jvmopts) then
176+
val jvmoptsContent = os.read(jvmopts)
177+
val jvmoptsLines = jvmoptsContent.linesIterator.toSeq
178+
val (javaOpts, otherOpts) = jvmoptsLines.partition(_.startsWith("-D"))
179+
javaOpts.foreach { opt =>
180+
opt.stripPrefix("-D").split("=", 2).match {
181+
case Array(key, value) => System.setProperty(key, value)
182+
case _ => System.err.println(s"Warning: Invalid java property: $opt")
183+
}
184+
}
185+
if otherOpts.nonEmpty then
186+
System.err.println(
187+
s"Warning: Only java properties are supported in .scala-jvmopts file. Other options are ignored: ${otherOpts.mkString(", ")} "
188+
)
172189
}
173190

174191
private def main0(args: Array[String]): Unit = {
175-
loadJavaPropertiesFromResources() // load java properties to detect launcher kind
192+
loadJavaProperties(cwd = os.pwd) // load java properties to detect launcher kind
176193
val remainingArgs = LauncherOptions.parser.stopAtFirstUnrecognized.parse(args.toVector) match {
177194
case Left(e) =>
178195
System.err.println(e.message)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cli.tests
2+
3+
import com.eed3si9n.expecty.Expecty.expect
4+
5+
import java.util.Properties
6+
7+
import scala.build.internal.Constants
8+
import scala.build.tests.TestInputs
9+
import scala.cli.ScalaCli
10+
import scala.util.Properties
11+
12+
class SetupScalaCLITests extends munit.FunSuite {
13+
14+
test(s"should read java properties from file") {
15+
val key = "scala-cli"
16+
val value = "true"
17+
val inputs = TestInputs(
18+
os.rel / Constants.jvmPropertiesFileName ->
19+
s"""-Xmx2048m
20+
|-Xms128m
21+
|-Xss8m
22+
|-D$key=$value
23+
|""".stripMargin
24+
)
25+
inputs.fromRoot(root =>
26+
// save current props to restore them after test
27+
val currentProps = System.getProperties.clone().asInstanceOf[Properties]
28+
ScalaCli.loadJavaProperties(root)
29+
expect(sys.props.get(key).contains(value))
30+
31+
// restore original props
32+
System.setProperties(currentProps)
33+
)
34+
}
35+
}

project/settings.sc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -836,8 +836,9 @@ trait ScalaCliModule extends ScalaModule {
836836
}
837837
}
838838

839-
def workspaceDirName = ".scala-build"
840-
def projectFileName = "project.scala"
839+
def workspaceDirName = ".scala-build"
840+
def projectFileName = "project.scala"
841+
def jvmPropertiesFileName = ".scala-jvmopts"
841842

842843
final case class License(licenseId: String, name: String, reference: String)
843844
object License {

website/docs/under-the-hood.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ In order set them, the `-D` command-line flags must be placed as the first optio
4646
scala-cli -Dfoo1=bar1 -Dfoo2=bar2 run ...
4747
```
4848

49+
The Scala CLI can also load Java properties from the `.scala-jvmopts` file present in the current working
50+
directory and import these Java properties into Scala CLI. Any java options in the `.scala-jvmopts` that are not
51+
recognizable as Java properties will be ignored.
52+
53+
The example below shows that the Java properties `foo1` and `foo2` from the `.scala-jvmopts` file will be passed
54+
into the Scala CLI:
55+
```bash ignore
56+
$ cat .scala-jvmopts
57+
-Dfoo1=bar1
58+
-Dfoo2=bar2
59+
$ scala-cli run ...
60+
```
61+
4962
:::note
5063
- `scala-cli run . -Dfoo=bar` would pass the java property into your Scala app
5164
- `scala-cli -Dfoo=bar run .` would pass the java property into `scala-cli.`

0 commit comments

Comments
 (0)