mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 23:01:29 +03:00
CLI & Debug runner (#124)
This commit is contained in:
parent
5316ffb011
commit
11dc690b21
5
.gitignore
vendored
5
.gitignore
vendored
@ -79,3 +79,8 @@ javadoc/
|
||||
#######################
|
||||
bench-report.xml
|
||||
|
||||
##############
|
||||
## Binaries ##
|
||||
##############
|
||||
|
||||
enso
|
||||
|
@ -1,7 +1,89 @@
|
||||
package org.enso.interpreter;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
import org.graalvm.polyglot.Context;
|
||||
import org.graalvm.polyglot.Source;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/** The main CLI entry point class. */
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Unimplemented");
|
||||
private static final String RUN_OPTION = "run";
|
||||
private static final String HELP_OPTION = "help";
|
||||
|
||||
/**
|
||||
* Builds the {@link Options} object representing the CLI syntax.
|
||||
*
|
||||
* @return an {@link Options} object representing the CLI syntax
|
||||
*/
|
||||
private static Options buildOptions() {
|
||||
Option help = Option.builder("h").longOpt(HELP_OPTION).desc("Displays this message.").build();
|
||||
Option run =
|
||||
Option.builder()
|
||||
.hasArg(true)
|
||||
.numberOfArgs(1)
|
||||
.argName("file")
|
||||
.longOpt(RUN_OPTION)
|
||||
.desc("Runs a specified Enso file.")
|
||||
.build();
|
||||
|
||||
Options options = new Options();
|
||||
options.addOption(help).addOption(run);
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the help message to the standard output.
|
||||
*
|
||||
* @param options object representing the CLI syntax
|
||||
*/
|
||||
public static void printHelp(Options options) {
|
||||
new HelpFormatter().printHelp(Constants.LANGUAGE_ID, options);
|
||||
}
|
||||
|
||||
/** Terminates the process with a failure exit code. */
|
||||
public static void exitFail() {
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/** Terminates the process with a success exit code. */
|
||||
public static void exitSuccess() {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point for the CLI program.
|
||||
*
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
Options options = buildOptions();
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
CommandLine line;
|
||||
try {
|
||||
line = parser.parse(options, args);
|
||||
} catch (ParseException e) {
|
||||
printHelp(options);
|
||||
exitFail();
|
||||
return;
|
||||
}
|
||||
if (line.hasOption(HELP_OPTION)) {
|
||||
printHelp(options);
|
||||
exitSuccess();
|
||||
return;
|
||||
}
|
||||
if (!line.hasOption(RUN_OPTION)) {
|
||||
printHelp(options);
|
||||
exitFail();
|
||||
return;
|
||||
}
|
||||
|
||||
File file = new File(line.getOptionValue(RUN_OPTION));
|
||||
|
||||
Context context =
|
||||
Context.newBuilder(Constants.LANGUAGE_ID).out(System.out).in(System.in).build();
|
||||
Source source = Source.newBuilder(Constants.LANGUAGE_ID, file).build();
|
||||
context.eval(source);
|
||||
}
|
||||
}
|
||||
|
33
build.sbt
33
build.sbt
@ -1,3 +1,5 @@
|
||||
import scala.sys.process._
|
||||
|
||||
// Global Configuration
|
||||
organization := "org.enso"
|
||||
scalaVersion := "2.12.8"
|
||||
@ -16,6 +18,8 @@ javacOptions ++= Seq("-source", "12", "-target", "1.8")
|
||||
lazy val Benchmark = config("bench") extend Test
|
||||
lazy val bench = taskKey[Unit]("Run Benchmarks")
|
||||
lazy val benchOnly = inputKey[Unit]("Run benchmarks by name substring")
|
||||
lazy val buildNativeImage =
|
||||
taskKey[Unit]("Build native image for the Enso executable")
|
||||
|
||||
// Global Project
|
||||
lazy val enso = (project in file("."))
|
||||
@ -79,16 +83,6 @@ val truffleRunOptions = Seq(
|
||||
javaOptions += s"-Dgraal.TruffleBackgroundCompilation=false"
|
||||
)
|
||||
|
||||
val truffleDebugOptions = Seq(
|
||||
javaOptions += s"-Dgraal.PrintGraph=Network",
|
||||
javaOptions += s"-Dgraal.Dump=Truffle:2",
|
||||
javaOptions += s"-Dgraal.TraceTruffleCompilation=true",
|
||||
javaOptions += s"-Dgraal.TraceTruffleCompilationCallTree=true",
|
||||
javaOptions += s"-Dgraal.TraceTruffleInlining=true",
|
||||
javaOptions += s"-Dgraal.TraceTrufflePerformanceWarnings=true",
|
||||
javaOptions += s"-Dgraal.TruffleBackgroundCompilation=false"
|
||||
)
|
||||
|
||||
val jmh = Seq(
|
||||
"org.openjdk.jmh" % "jmh-core" % "1.21" % Benchmark,
|
||||
"org.openjdk.jmh" % "jmh-generator-annprocess" % "1.21" % Benchmark
|
||||
@ -99,6 +93,7 @@ lazy val interpreter = (project in file("Interpreter"))
|
||||
mainClass in (Compile, run) := Some("org.enso.interpreter.Main"),
|
||||
version := "0.1"
|
||||
)
|
||||
.settings(commands += RunDebugCommand.runDebug)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"com.chuusai" %% "shapeless" % "2.3.3",
|
||||
@ -114,7 +109,8 @@ lazy val interpreter = (project in file("Interpreter"))
|
||||
"org.scalacheck" %% "scalacheck" % "1.14.0" % Test,
|
||||
"org.scalactic" %% "scalactic" % "3.0.8" % Test,
|
||||
"org.scalatest" %% "scalatest" % "3.2.0-SNAP10" % Test,
|
||||
"org.typelevel" %% "cats-core" % "2.0.0-M4"
|
||||
"org.typelevel" %% "cats-core" % "2.0.0-M4",
|
||||
"commons-cli" % "commons-cli" % "1.4"
|
||||
),
|
||||
libraryDependencies ++= jmh
|
||||
)
|
||||
@ -135,6 +131,19 @@ lazy val interpreter = (project in file("Interpreter"))
|
||||
parallelExecution in Test := false,
|
||||
logBuffered in Test := false
|
||||
)
|
||||
.settings(
|
||||
buildNativeImage := Def
|
||||
.task {
|
||||
val javaHome = System.getProperty("java.home")
|
||||
val nativeImagePath = s"$javaHome/bin/native-image"
|
||||
val classPath = (Runtime / fullClasspath).value.files.mkString(":")
|
||||
val cmd =
|
||||
s"$nativeImagePath --macro:truffle --no-fallback --initialize-at-build-time -cp $classPath ${(Compile / mainClass).value.get} enso"
|
||||
cmd !
|
||||
}
|
||||
.dependsOn(Compile / compile)
|
||||
.value
|
||||
)
|
||||
.configs(Benchmark)
|
||||
.settings(
|
||||
logBuffered := false,
|
||||
@ -145,7 +154,7 @@ lazy val interpreter = (project in file("Interpreter"))
|
||||
import complete.Parsers.spaceDelimited
|
||||
val name = spaceDelimited("<name>").parsed match {
|
||||
case List(name) => name
|
||||
case _ => throw new IllegalArgumentException("Expected one argument.")
|
||||
case _ => throw new IllegalArgumentException("Expected one argument.")
|
||||
}
|
||||
Def.task {
|
||||
(testOnly in Benchmark).toTask(" -- -z " + name).value
|
||||
|
80
project/RunDebugCommand.scala
Normal file
80
project/RunDebugCommand.scala
Normal file
@ -0,0 +1,80 @@
|
||||
import sbt.Keys.javaOptions
|
||||
import sbt._
|
||||
|
||||
/** Command allowing to run the CLI program with additional JVM-level flags.
|
||||
* The supported flags are:
|
||||
* * `--dumpGraphs`: dumps IGV output of the program
|
||||
* * `--showCompilations`: prints Truffle compilation traces
|
||||
* * `--printAssembly`: prints the disassembler output
|
||||
* Any CLI arguments should be passed following `--` like so:
|
||||
* {{{
|
||||
* runDebug --dumpGraphs --printAssembly -- --run myFile.enso
|
||||
* }}}
|
||||
*/
|
||||
object RunDebugCommand {
|
||||
|
||||
val truffleNoBackgroundCompilationOptions = Seq(
|
||||
"-Dgraal.TruffleBackgroundCompilation=false"
|
||||
)
|
||||
|
||||
val truffleDumpGraphsOptions = Seq(
|
||||
"-Dgraal.PrintGraph=Network",
|
||||
"-Dgraal.Dump=Truffle:2"
|
||||
)
|
||||
|
||||
val truffleShowCompilationsOptions = Seq(
|
||||
"-Dgraal.TraceTruffleCompilation=true",
|
||||
"-Dgraal.TraceTruffleCompilationCallTree=true",
|
||||
"-Dgraal.TraceTruffleInlining=true",
|
||||
"-Dgraal.TraceTrufflePerformanceWarnings=true"
|
||||
)
|
||||
|
||||
val trufflePrintAssemblyOptions = Seq(
|
||||
"-XX:CompileCommand=print,*OptimizedCallTarget.callRoot",
|
||||
"-XX:CompileCommand=exclude,*OptimizedCallTarget.callRoot"
|
||||
)
|
||||
|
||||
val dumpGraphsOption = "--dumpGraphs"
|
||||
|
||||
val showCompilationsOptions = "--showCompilations"
|
||||
|
||||
val printAssemblyOption = "--printAssembly"
|
||||
|
||||
val argSeparator = "--"
|
||||
|
||||
val commandName = "runDebug"
|
||||
|
||||
/** The main logic for parsing and transforming the debug flags into JVM level flags */
|
||||
def runDebug: Command = Command.args(commandName, "<arguments>") {
|
||||
(state, args) =>
|
||||
val (debugFlags, prefixedRunArgs) = args.span(_ != argSeparator)
|
||||
val runArgs = " " + prefixedRunArgs.drop(1).mkString(" ")
|
||||
val dumpGraphsOpts =
|
||||
if (debugFlags.contains(dumpGraphsOption)) truffleDumpGraphsOptions
|
||||
else Seq()
|
||||
val showCompilationsOpts =
|
||||
if (debugFlags.contains(showCompilationsOptions))
|
||||
truffleShowCompilationsOptions
|
||||
else Seq()
|
||||
val printAssemblyOpts =
|
||||
if (debugFlags.contains(printAssemblyOption))
|
||||
trufflePrintAssemblyOptions
|
||||
else Seq()
|
||||
val javaOpts: Seq[String] = Seq(
|
||||
truffleNoBackgroundCompilationOptions,
|
||||
dumpGraphsOpts,
|
||||
showCompilationsOpts,
|
||||
printAssemblyOpts
|
||||
).flatten
|
||||
|
||||
val extracted = Project.extract(state)
|
||||
val withJavaOpts = extracted.appendWithoutSession(
|
||||
Seq(Compile / Keys.run / Keys.javaOptions ++= javaOpts),
|
||||
state
|
||||
)
|
||||
Project
|
||||
.extract(withJavaOpts)
|
||||
.runInputTask(Compile / Keys.run, runArgs, withJavaOpts)
|
||||
state
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user