mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
Working on CLI
This commit is contained in:
parent
e885ebdbbb
commit
19a003669b
|
@ -39,6 +39,24 @@
|
||||||
<artifactId>commons-cli</artifactId>
|
<artifactId>commons-cli</artifactId>
|
||||||
<version>1.2</version>
|
<version>1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-classlib</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-metaprogramming-impl</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-jso-impl</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -59,6 +77,37 @@
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>org.teavm.cli.TeaVMRunner</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.cli;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.tooling.TeaVMToolLog;
|
||||||
|
|
||||||
|
public class AccumulatingTeaVMToolLog implements TeaVMToolLog {
|
||||||
|
private TeaVMToolLog delegatedLog;
|
||||||
|
private List<Message> pendingMessages = new ArrayList<>();
|
||||||
|
|
||||||
|
public AccumulatingTeaVMToolLog(TeaVMToolLog delegatedLog) {
|
||||||
|
this.delegatedLog = delegatedLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
for (Message message : pendingMessages) {
|
||||||
|
switch (message.kind) {
|
||||||
|
case INFO:
|
||||||
|
if (message.throwable != null) {
|
||||||
|
delegatedLog.info(message.text, message.throwable);
|
||||||
|
} else {
|
||||||
|
delegatedLog.info(message.text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DEBUG:
|
||||||
|
if (message.throwable != null) {
|
||||||
|
delegatedLog.debug(message.text, message.throwable);
|
||||||
|
} else {
|
||||||
|
delegatedLog.debug(message.text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
if (message.throwable != null) {
|
||||||
|
delegatedLog.warning(message.text, message.throwable);
|
||||||
|
} else {
|
||||||
|
delegatedLog.warning(message.text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
if (message.throwable != null) {
|
||||||
|
delegatedLog.error(message.text, message.throwable);
|
||||||
|
} else {
|
||||||
|
delegatedLog.error(message.text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pendingMessages.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String text) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.INFO, text, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String text) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.DEBUG, text, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warning(String text) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.WARNING, text, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String text) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.ERROR, text, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String text, Throwable e) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.INFO, text, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(String text, Throwable e) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.DEBUG, text, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void warning(String text, Throwable e) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.WARNING, text, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String text, Throwable e) {
|
||||||
|
pendingMessages.add(new Message(MessageKind.ERROR, text, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Message {
|
||||||
|
MessageKind kind;
|
||||||
|
String text;
|
||||||
|
Throwable throwable;
|
||||||
|
|
||||||
|
public Message(MessageKind kind, String text, Throwable throwable) {
|
||||||
|
this.kind = kind;
|
||||||
|
this.text = text;
|
||||||
|
this.throwable = throwable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MessageKind {
|
||||||
|
INFO,
|
||||||
|
DEBUG,
|
||||||
|
WARNING,
|
||||||
|
ERROR
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,15 +15,28 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.cli;
|
package org.teavm.cli;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
|
import java.nio.file.StandardWatchEventKinds;
|
||||||
|
import java.nio.file.WatchEvent;
|
||||||
|
import java.nio.file.WatchKey;
|
||||||
|
import java.nio.file.WatchService;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
import org.apache.commons.cli.HelpFormatter;
|
import org.apache.commons.cli.HelpFormatter;
|
||||||
|
@ -32,7 +45,6 @@ import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.cli.PosixParser;
|
import org.apache.commons.cli.PosixParser;
|
||||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||||
import org.teavm.tooling.ClassAlias;
|
|
||||||
import org.teavm.tooling.RuntimeCopyOperation;
|
import org.teavm.tooling.RuntimeCopyOperation;
|
||||||
import org.teavm.tooling.TeaVMTargetType;
|
import org.teavm.tooling.TeaVMTargetType;
|
||||||
import org.teavm.tooling.TeaVMTool;
|
import org.teavm.tooling.TeaVMTool;
|
||||||
|
@ -43,17 +55,21 @@ import org.teavm.vm.TeaVMProgressFeedback;
|
||||||
import org.teavm.vm.TeaVMProgressListener;
|
import org.teavm.vm.TeaVMProgressListener;
|
||||||
|
|
||||||
public final class TeaVMRunner {
|
public final class TeaVMRunner {
|
||||||
private static long startTime;
|
private static Options options = new Options();
|
||||||
private static long phaseStartTime;
|
private TeaVMTool tool = new TeaVMTool();
|
||||||
private static TeaVMPhase currentPhase;
|
private AccumulatingTeaVMToolLog log = new AccumulatingTeaVMToolLog(new ConsoleTeaVMToolLog());
|
||||||
private static String[] classPath;
|
private CommandLine commandLine;
|
||||||
|
private long startTime;
|
||||||
|
private long phaseStartTime;
|
||||||
|
private String[] classPath;
|
||||||
|
private boolean interactive;
|
||||||
|
|
||||||
private TeaVMRunner() {
|
static {
|
||||||
|
setupOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("static-access")
|
@SuppressWarnings("static-access")
|
||||||
public static void main(String[] args) {
|
private static void setupOptions() {
|
||||||
Options options = new Options();
|
|
||||||
options.addOption(OptionBuilder
|
options.addOption(OptionBuilder
|
||||||
.withArgName("target")
|
.withArgName("target")
|
||||||
.hasArg()
|
.hasArg()
|
||||||
|
@ -114,21 +130,21 @@ public final class TeaVMRunner {
|
||||||
.withDescription("Additional classpath that will be reloaded by TeaVM each time in wait mode")
|
.withDescription("Additional classpath that will be reloaded by TeaVM each time in wait mode")
|
||||||
.withLongOpt("classpath")
|
.withLongOpt("classpath")
|
||||||
.create('p'));
|
.create('p'));
|
||||||
options.addOption(OptionBuilder
|
|
||||||
.withLongOpt("classalias")
|
|
||||||
.withArgName("alias")
|
|
||||||
.hasArgs()
|
|
||||||
.withDescription("Alias names for classes. Specify as fully.qualified.Name:AliasName")
|
|
||||||
.create());
|
|
||||||
options.addOption(OptionBuilder
|
options.addOption(OptionBuilder
|
||||||
.withLongOpt("wasm-version")
|
.withLongOpt("wasm-version")
|
||||||
.withArgName("version")
|
.withArgName("version")
|
||||||
.hasArg()
|
.hasArg()
|
||||||
.withDescription("WebAssembly binary version (11, 12, 13)")
|
.withDescription("WebAssembly binary version (11, 12, 13)")
|
||||||
.create());
|
.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
private TeaVMRunner(CommandLine commandLine) {
|
||||||
|
this.commandLine = commandLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
printUsage(options);
|
printUsage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CommandLineParser parser = new PosixParser();
|
CommandLineParser parser = new PosixParser();
|
||||||
|
@ -136,11 +152,38 @@ public final class TeaVMRunner {
|
||||||
try {
|
try {
|
||||||
commandLine = parser.parse(options, args);
|
commandLine = parser.parse(options, args);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
printUsage(options);
|
printUsage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TeaVMTool tool = new TeaVMTool();
|
TeaVMRunner runner = new TeaVMRunner(commandLine);
|
||||||
|
runner.parseArguments();
|
||||||
|
runner.setUp();
|
||||||
|
runner.runAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseArguments() {
|
||||||
|
parseClassPathOptions();
|
||||||
|
parseTargetOption();
|
||||||
|
parseOutputOptions();
|
||||||
|
parseDebugOptions();
|
||||||
|
parseOptimizationOption();
|
||||||
|
parseIncrementalOptions();
|
||||||
|
parseJavaScriptOptions();
|
||||||
|
parseWasmOptions();
|
||||||
|
|
||||||
|
interactive = commandLine.hasOption('w');
|
||||||
|
|
||||||
|
String[] args = commandLine.getArgs();
|
||||||
|
if (args.length > 1) {
|
||||||
|
System.err.println("Unexpected arguments");
|
||||||
|
printUsage();
|
||||||
|
} else if (args.length == 1) {
|
||||||
|
tool.setMainClass(args[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseTargetOption() {
|
||||||
if (commandLine.hasOption("t")) {
|
if (commandLine.hasOption("t")) {
|
||||||
switch (commandLine.getOptionValue('t').toLowerCase()) {
|
switch (commandLine.getOptionValue('t').toLowerCase()) {
|
||||||
case "javascript":
|
case "javascript":
|
||||||
|
@ -153,12 +196,18 @@ public final class TeaVMRunner {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseOutputOptions() {
|
||||||
if (commandLine.hasOption("d")) {
|
if (commandLine.hasOption("d")) {
|
||||||
tool.setTargetDirectory(new File(commandLine.getOptionValue("d")));
|
tool.setTargetDirectory(new File(commandLine.getOptionValue("d")));
|
||||||
}
|
}
|
||||||
if (commandLine.hasOption("f")) {
|
if (commandLine.hasOption("f")) {
|
||||||
tool.setTargetFileName(commandLine.getOptionValue("f"));
|
tool.setTargetFileName(commandLine.getOptionValue("f"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseJavaScriptOptions() {
|
||||||
if (commandLine.hasOption("m")) {
|
if (commandLine.hasOption("m")) {
|
||||||
tool.setMinifying(true);
|
tool.setMinifying(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -177,21 +226,28 @@ public final class TeaVMRunner {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.err.println("Wrong parameter for -r option specified");
|
System.err.println("Wrong parameter for -r option specified");
|
||||||
printUsage(options);
|
printUsage();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseDebugOptions() {
|
||||||
if (commandLine.hasOption('g')) {
|
if (commandLine.hasOption('g')) {
|
||||||
tool.setDebugInformationGenerated(true);
|
tool.setDebugInformationGenerated(true);
|
||||||
}
|
}
|
||||||
|
if (commandLine.hasOption('S')) {
|
||||||
|
tool.setSourceMapsFileGenerated(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseOptimizationOption() {
|
||||||
if (commandLine.hasOption("O")) {
|
if (commandLine.hasOption("O")) {
|
||||||
int level;
|
int level;
|
||||||
try {
|
try {
|
||||||
level = Integer.parseInt(commandLine.getOptionValue("O"));
|
level = Integer.parseInt(commandLine.getOptionValue("O"));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
System.err.print("Wrong optimization level");
|
System.err.print("Wrong optimization level");
|
||||||
printUsage(options);
|
printUsage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (level) {
|
switch (level) {
|
||||||
|
@ -206,14 +262,12 @@ public final class TeaVMRunner {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.err.print("Wrong optimization level");
|
System.err.print("Wrong optimization level");
|
||||||
printUsage(options);
|
printUsage();
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandLine.hasOption('S')) {
|
private void parseIncrementalOptions() {
|
||||||
tool.setSourceMapsFileGenerated(true);
|
|
||||||
}
|
|
||||||
if (commandLine.hasOption('i')) {
|
if (commandLine.hasOption('i')) {
|
||||||
tool.setIncremental(true);
|
tool.setIncremental(true);
|
||||||
}
|
}
|
||||||
|
@ -222,98 +276,15 @@ public final class TeaVMRunner {
|
||||||
} else {
|
} else {
|
||||||
tool.setCacheDirectory(new File(tool.getTargetDirectory(), "teavm-cache"));
|
tool.setCacheDirectory(new File(tool.getTargetDirectory(), "teavm-cache"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseClassPathOptions() {
|
||||||
if (commandLine.hasOption('p')) {
|
if (commandLine.hasOption('p')) {
|
||||||
classPath = commandLine.getOptionValues('p');
|
classPath = commandLine.getOptionValues('p');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandLine.hasOption("classalias")) {
|
|
||||||
String[] aliasStrings = commandLine.getOptionValues("classalias");
|
|
||||||
|
|
||||||
for (String aliasString : aliasStrings) {
|
|
||||||
int i = aliasString.indexOf(':');
|
|
||||||
if (i == -1) {
|
|
||||||
System.err.print("Wrong alias specification");
|
|
||||||
printUsage(options);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassAlias alias = new ClassAlias();
|
private void parseWasmOptions() {
|
||||||
alias.setClassName(aliasString.substring(0, i));
|
|
||||||
alias.setAlias(aliasString.substring(i + 1));
|
|
||||||
tool.getClassAliases().add(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean interactive = commandLine.hasOption('w');
|
|
||||||
setupWasm(tool, commandLine, options);
|
|
||||||
|
|
||||||
args = commandLine.getArgs();
|
|
||||||
if (args.length > 1) {
|
|
||||||
System.err.println("Unexpected arguments");
|
|
||||||
printUsage(options);
|
|
||||||
return;
|
|
||||||
} else if (args.length == 1) {
|
|
||||||
tool.setMainClass(args[0]);
|
|
||||||
}
|
|
||||||
tool.setLog(new ConsoleTeaVMToolLog());
|
|
||||||
tool.getProperties().putAll(System.getProperties());
|
|
||||||
tool.setProgressListener(progressListener);
|
|
||||||
|
|
||||||
if (interactive) {
|
|
||||||
boolean quit = false;
|
|
||||||
BufferedReader reader;
|
|
||||||
try {
|
|
||||||
reader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
System.exit(-2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
build(tool);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(System.err);
|
|
||||||
}
|
|
||||||
System.out.println("Press enter to repeat or enter 'q' to quit");
|
|
||||||
try {
|
|
||||||
String line = reader.readLine().trim();
|
|
||||||
if (!line.isEmpty()) {
|
|
||||||
if (line.equals("q")) {
|
|
||||||
quit = true;
|
|
||||||
} else {
|
|
||||||
System.out.println("Unrecognized command");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
System.exit(-2);
|
|
||||||
}
|
|
||||||
} while (!quit);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
build(tool);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(System.err);
|
|
||||||
System.exit(-2);
|
|
||||||
}
|
|
||||||
if (!tool.getProblemProvider().getSevereProblems().isEmpty()) {
|
|
||||||
System.exit(-2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void build(TeaVMTool tool) throws TeaVMToolException {
|
|
||||||
resetClassLoader(tool);
|
|
||||||
currentPhase = null;
|
|
||||||
startTime = System.currentTimeMillis();
|
|
||||||
phaseStartTime = System.currentTimeMillis();
|
|
||||||
tool.generate();
|
|
||||||
reportPhaseComplete();
|
|
||||||
System.out.println("Build complete for " + ((System.currentTimeMillis() - startTime) / 1000.0) + " seconds");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setupWasm(TeaVMTool tool, CommandLine commandLine, Options options) {
|
|
||||||
if (commandLine.hasOption("wasm-version")) {
|
if (commandLine.hasOption("wasm-version")) {
|
||||||
String value = commandLine.getOptionValue("wasm-version");
|
String value = commandLine.getOptionValue("wasm-version");
|
||||||
try {
|
try {
|
||||||
|
@ -324,16 +295,229 @@ public final class TeaVMRunner {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.err.print("Wrong version value");
|
System.err.print("Wrong version value");
|
||||||
printUsage(options);
|
printUsage();
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
System.err.print("Wrong version value");
|
System.err.print("Wrong version value");
|
||||||
printUsage(options);
|
printUsage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void resetClassLoader(TeaVMTool tool) {
|
private void setUp() {
|
||||||
|
tool.setLog(log);
|
||||||
|
tool.getProperties().putAll(System.getProperties());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runAll() {
|
||||||
|
if (interactive) {
|
||||||
|
buildInteractive();
|
||||||
|
} else {
|
||||||
|
buildNonInteractive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildInteractive() {
|
||||||
|
InteractiveWatcher watcher = new InteractiveWatcher();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ProgressListenerImpl progressListener = new ProgressListenerImpl();
|
||||||
|
Thread thread = null;
|
||||||
|
try {
|
||||||
|
watcher.progressListener = progressListener;
|
||||||
|
thread = new Thread(watcher);
|
||||||
|
thread.start();
|
||||||
|
if (progressListener.cancelRequested.get()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
build(progressListener);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
} finally {
|
||||||
|
if (!progressListener.cancelRequested.get()) {
|
||||||
|
thread.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.out.println("Waiting for changes...");
|
||||||
|
watcher.waitForChange();
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Changes detected. Recompiling...");
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InteractiveWatcher implements Runnable {
|
||||||
|
volatile ProgressListenerImpl progressListener = new ProgressListenerImpl();
|
||||||
|
private WatchService watchService;
|
||||||
|
private Map<WatchKey, Path> keysToPath = new HashMap<>();
|
||||||
|
private Map<Path, WatchKey> pathsToKey = new HashMap<>();
|
||||||
|
|
||||||
|
InteractiveWatcher() {
|
||||||
|
try {
|
||||||
|
watchService = FileSystems.getDefault().newWatchService();
|
||||||
|
for (String entry : classPath) {
|
||||||
|
Path path = Paths.get(entry);
|
||||||
|
File file = path.toFile();
|
||||||
|
if (file.exists()) {
|
||||||
|
if (!file.isDirectory()) {
|
||||||
|
registerSingle(path.getParent());
|
||||||
|
} else {
|
||||||
|
register(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error setting up file watcher");
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
System.exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register(Path path) throws IOException {
|
||||||
|
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||||
|
@Override
|
||||||
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
|
||||||
|
throws IOException {
|
||||||
|
registerSingle(dir);
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerSingle(Path path) throws IOException {
|
||||||
|
WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
|
||||||
|
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
|
||||||
|
keysToPath.put(key, path);
|
||||||
|
pathsToKey.put(path, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Thread thread = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
waitForChange();
|
||||||
|
if (Thread.currentThread().isInterrupted()) {
|
||||||
|
progressListener.cancelRequested.set(true);
|
||||||
|
System.out.println("Classpath changed during compilation. Cancelling...");
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
if (thread.isAlive()) {
|
||||||
|
thread.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitForChange() throws InterruptedException, IOException {
|
||||||
|
take();
|
||||||
|
while (poll(750)) {
|
||||||
|
// continue polling
|
||||||
|
}
|
||||||
|
while (pollNow()) {
|
||||||
|
// continue polling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void take() throws InterruptedException, IOException {
|
||||||
|
while (true) {
|
||||||
|
WatchKey key = watchService.take();
|
||||||
|
if (key != null) {
|
||||||
|
if (!filter(key).isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean poll(int milliseconds) throws IOException, InterruptedException {
|
||||||
|
long end = System.currentTimeMillis() + milliseconds;
|
||||||
|
while (true) {
|
||||||
|
int timeToWait = (int) (end - System.currentTimeMillis());
|
||||||
|
WatchKey key = watchService.poll(timeToWait, TimeUnit.MILLISECONDS);
|
||||||
|
if (key == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!filter(key).isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean pollNow() throws IOException {
|
||||||
|
WatchKey key = watchService.poll();
|
||||||
|
if (key == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
filter(key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Path> filter(WatchKey key) throws IOException {
|
||||||
|
List<Path> result = new ArrayList<>();
|
||||||
|
for (WatchEvent<?> event : key.pollEvents()) {
|
||||||
|
Path path = filter(key, event);
|
||||||
|
if (path != null) {
|
||||||
|
result.add(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key.reset();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path filter(WatchKey baseKey, WatchEvent<?> event) throws IOException {
|
||||||
|
if (!(event.context() instanceof Path)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Path basePath = keysToPath.get(baseKey);
|
||||||
|
Path path = basePath.resolve((Path) event.context());
|
||||||
|
WatchKey key = pathsToKey.get(path);
|
||||||
|
|
||||||
|
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
|
||||||
|
if (key != null) {
|
||||||
|
pathsToKey.remove(path);
|
||||||
|
keysToPath.remove(key);
|
||||||
|
key.cancel();
|
||||||
|
}
|
||||||
|
} else if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
|
||||||
|
if (Files.isDirectory(path)) {
|
||||||
|
register(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildNonInteractive() {
|
||||||
|
try {
|
||||||
|
build(new ProgressListenerImpl());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
System.exit(-2);
|
||||||
|
}
|
||||||
|
if (!tool.getProblemProvider().getSevereProblems().isEmpty()) {
|
||||||
|
System.exit(-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void build(ProgressListenerImpl progressListener) throws TeaVMToolException {
|
||||||
|
tool.setProgressListener(progressListener);
|
||||||
|
resetClassLoader();
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
phaseStartTime = System.currentTimeMillis();
|
||||||
|
tool.generate();
|
||||||
|
reportPhaseComplete();
|
||||||
|
System.out.println("Build complete for " + ((System.currentTimeMillis() - startTime) / 1000.0) + " seconds");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetClassLoader() {
|
||||||
if (classPath == null || classPath.length == 0) {
|
if (classPath == null || classPath.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -351,13 +535,17 @@ public final class TeaVMRunner {
|
||||||
tool.setClassLoader(new URLClassLoader(urls, TeaVMRunner.class.getClassLoader()));
|
tool.setClassLoader(new URLClassLoader(urls, TeaVMRunner.class.getClassLoader()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TeaVMProgressListener progressListener = new TeaVMProgressListener() {
|
class ProgressListenerImpl implements TeaVMProgressListener {
|
||||||
|
private TeaVMPhase currentPhase;
|
||||||
|
AtomicBoolean cancelRequested = new AtomicBoolean();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TeaVMProgressFeedback progressReached(int progress) {
|
public TeaVMProgressFeedback progressReached(int progress) {
|
||||||
return TeaVMProgressFeedback.CONTINUE;
|
return cancelRequested.get() ? TeaVMProgressFeedback.CANCEL : TeaVMProgressFeedback.CONTINUE;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
|
public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
|
||||||
|
log.flush();
|
||||||
if (currentPhase != phase) {
|
if (currentPhase != phase) {
|
||||||
if (currentPhase != null) {
|
if (currentPhase != null) {
|
||||||
reportPhaseComplete();
|
reportPhaseComplete();
|
||||||
|
@ -382,15 +570,16 @@ public final class TeaVMRunner {
|
||||||
}
|
}
|
||||||
currentPhase = phase;
|
currentPhase = phase;
|
||||||
}
|
}
|
||||||
return TeaVMProgressFeedback.CONTINUE;
|
return cancelRequested.get() ? TeaVMProgressFeedback.CANCEL : TeaVMProgressFeedback.CONTINUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
private static void reportPhaseComplete() {
|
private void reportPhaseComplete() {
|
||||||
System.out.println(" complete for " + ((System.currentTimeMillis() - phaseStartTime) / 1000.0) + " seconds");
|
System.out.println(" complete for " + ((System.currentTimeMillis() - phaseStartTime) / 1000.0) + " seconds");
|
||||||
|
log.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printUsage(Options options) {
|
private static void printUsage() {
|
||||||
HelpFormatter formatter = new HelpFormatter();
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
formatter.printHelp("java " + TeaVMRunner.class.getName() + " [OPTIONS] [qualified.main.Class]", options);
|
formatter.printHelp("java " + TeaVMRunner.class.getName() + " [OPTIONS] [qualified.main.Class]", options);
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user