Skip to content

Commit 334dd0e

Browse files
Add --command and --scratch-dir to run command (#1163)
1 parent 3c9b118 commit 334dd0e

File tree

8 files changed

+314
-91
lines changed

8 files changed

+314
-91
lines changed

modules/build/src/main/scala/scala/build/internal/Runner.scala

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,20 @@ object Runner {
9999
}
100100
}
101101

102-
def runJvm(
102+
private def envCommand(env: Map[String, String]): Seq[String] =
103+
env.toVector.sortBy(_._1).map {
104+
case (k, v) =>
105+
s"$k=$v"
106+
}
107+
108+
def jvmCommand(
103109
javaCommand: String,
104110
javaArgs: Seq[String],
105111
classPath: Seq[File],
106112
mainClass: String,
107113
args: Seq[String],
108-
logger: Logger,
109-
allowExecve: Boolean = false,
110-
cwd: Option[os.Path] = None
111-
): Process = {
114+
extraEnv: Map[String, String] = Map.empty
115+
): Seq[String] = {
112116

113117
val command =
114118
Seq(javaCommand) ++
@@ -120,10 +124,27 @@ object Runner {
120124
) ++
121125
args
122126

127+
envCommand(extraEnv) ++ command
128+
}
129+
130+
def runJvm(
131+
javaCommand: String,
132+
javaArgs: Seq[String],
133+
classPath: Seq[File],
134+
mainClass: String,
135+
args: Seq[String],
136+
logger: Logger,
137+
allowExecve: Boolean = false,
138+
cwd: Option[os.Path] = None,
139+
extraEnv: Map[String, String] = Map.empty
140+
): Process = {
141+
142+
val command = jvmCommand(javaCommand, javaArgs, classPath, mainClass, args, Map.empty)
143+
123144
if (allowExecve)
124-
maybeExec("java", command, logger, cwd = cwd)
145+
maybeExec("java", command, logger, cwd = cwd, extraEnv = extraEnv)
125146
else
126-
run(command, logger, cwd = cwd)
147+
run(command, logger, cwd = cwd, extraEnv = extraEnv)
127148
}
128149

129150
private def endsWithCaseInsensitive(s: String, suffix: String): Boolean =
@@ -155,6 +176,23 @@ object Runner {
155176
}
156177
}
157178

179+
def jsCommand(
180+
entrypoint: File,
181+
args: Seq[String],
182+
jsDom: Boolean = false
183+
): Seq[String] = {
184+
185+
val nodePath = findInPath("node").fold("node")(_.toString)
186+
val command = Seq(nodePath, entrypoint.getAbsolutePath) ++ args
187+
188+
if (jsDom)
189+
// FIXME We'd need to replicate what JSDOMNodeJSEnv does under-the-hood to get the command in that case.
190+
// --command is mostly for debugging purposes, so I'm not sure it matters much here…
191+
sys.error("Cannot get command when JSDOM is enabled.")
192+
else
193+
"node" +: command.tail
194+
}
195+
158196
def runJs(
159197
entrypoint: File,
160198
args: Seq[String],
@@ -168,31 +206,17 @@ object Runner {
168206
import logger.{log, debug}
169207

170208
val nodePath = findInPath("node").fold("node")(_.toString)
171-
val command = Seq(nodePath, entrypoint.getAbsolutePath) ++ args
172209

173-
log(
174-
s"Running ${command.mkString(" ")}",
175-
" Running" + System.lineSeparator() +
176-
command.iterator.map(_ + System.lineSeparator()).mkString
177-
)
210+
if (!jsDom && allowExecve && Execve.available()) {
178211

179-
lazy val envJs =
180-
if (jsDom)
181-
new JSDOMNodeJSEnv(
182-
JSDOMNodeJSEnv.Config()
183-
.withExecutable(nodePath)
184-
.withArgs(Nil)
185-
.withEnv(Map.empty)
186-
)
187-
else new NodeJSEnv(
188-
NodeJSEnv.Config()
189-
.withExecutable(nodePath)
190-
.withArgs(Nil)
191-
.withEnv(Map.empty)
192-
.withSourceMap(sourceMap)
212+
val command = Seq(nodePath, entrypoint.getAbsolutePath) ++ args
213+
214+
log(
215+
s"Running ${command.mkString(" ")}",
216+
" Running" + System.lineSeparator() +
217+
command.iterator.map(_ + System.lineSeparator()).mkString
193218
)
194219

195-
if (!jsDom && allowExecve && Execve.available()) {
196220
debug("execve available")
197221
Execve.execve(
198222
command.head,
@@ -202,6 +226,23 @@ object Runner {
202226
sys.error("should not happen")
203227
}
204228
else {
229+
230+
val envJs =
231+
if (jsDom)
232+
new JSDOMNodeJSEnv(
233+
JSDOMNodeJSEnv.Config()
234+
.withExecutable(nodePath)
235+
.withArgs(Nil)
236+
.withEnv(Map.empty)
237+
)
238+
else new NodeJSEnv(
239+
NodeJSEnv.Config()
240+
.withExecutable(nodePath)
241+
.withArgs(Nil)
242+
.withEnv(Map.empty)
243+
.withSourceMap(sourceMap)
244+
)
245+
205246
val inputs = Seq(
206247
if (esModule) Input.ESModule(entrypoint.toPath)
207248
else Input.Script(entrypoint.toPath)

modules/cli-options/src/main/scala/scala/cli/commands/RunOptions.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@ final case class RunOptions(
2323
@Recurse
2424
compileCross: CompileCrossOptions = CompileCrossOptions(),
2525
@Recurse
26-
mainClass: MainClassOptions = MainClassOptions()
27-
)
26+
mainClass: MainClassOptions = MainClassOptions(),
27+
@Group("Run")
28+
@HelpMessage("Print the command that would have been run (one argument per line), rather than running it")
29+
command: Boolean = false,
30+
@Group("Run")
31+
@HelpMessage("Temporary / working directory where to write generated launchers")
32+
scratchDir: Option[String] = None
33+
)
2834
// format: on
2935

3036
object RunOptions {

modules/cli/src/main/scala/scala/cli/commands/Package.scala

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -759,11 +759,19 @@ object Package extends ScalaCommand[PackageOptions] {
759759
config: ScalaJsLinkerConfig,
760760
fullOpt: Boolean,
761761
noOpt: Boolean,
762-
logger: Logger
762+
logger: Logger,
763+
scratchDirOpt: Option[os.Path] = None
763764
): Either[BuildException, os.Path] =
764765
Library.withLibraryJar(build, dest.last.stripSuffix(".jar")) { mainJar =>
765-
val classPath = mainJar +: build.artifacts.classPath
766-
val linkingDir = os.temp.dir(prefix = "scala-cli-js-linking")
766+
val classPath = mainJar +: build.artifacts.classPath
767+
val delete = scratchDirOpt.isEmpty
768+
scratchDirOpt.foreach(os.makeDir.all(_))
769+
val linkingDir =
770+
os.temp.dir(
771+
dir = scratchDirOpt.orNull,
772+
prefix = "scala-cli-js-linking",
773+
deleteOnExit = delete
774+
)
767775
either {
768776
value {
769777
ScalaJsLinker.link(
@@ -814,7 +822,8 @@ object Package extends ScalaCommand[PackageOptions] {
814822
os.copy(sourceMapJs, sourceMapDest, replaceExisting = true)
815823
logger.message(s"Emitted js source maps to: $sourceMapDest")
816824
}
817-
os.remove.all(linkingDir)
825+
if (delete)
826+
os.remove.all(linkingDir)
818827
dest
819828
}
820829
else {

0 commit comments

Comments
 (0)