mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add Maven option to run TeaVM in a separate process
This commit is contained in:
parent
0f951f8c86
commit
fc799afcda
|
@ -1,14 +1,15 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="IDEA JPS Debug" type="Remote" factoryName="Remote">
|
||||
<configuration default="false" name="IDEA JPS Debug" type="Remote">
|
||||
<option name="USE_SOCKET_TRANSPORT" value="true" />
|
||||
<option name="SERVER_MODE" value="false" />
|
||||
<option name="SHMEM_ADDRESS" value="javadebug" />
|
||||
<option name="SHMEM_ADDRESS" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="5005" />
|
||||
<option name="AUTO_RESTART" value="false" />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="5005" />
|
||||
<option name="LOCAL" value="false" />
|
||||
</RunnerSettings>
|
||||
<method />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
|
@ -48,6 +48,7 @@
|
|||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
|
@ -77,6 +78,7 @@
|
|||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-util</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
|
|
|
@ -33,6 +33,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
|||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 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.tooling;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.tooling.sources.SourceFileProvider;
|
||||
|
||||
public interface BaseTeaVMTool {
|
||||
void setTargetDirectory(File targetDirectory);
|
||||
|
||||
void setMinifying(boolean minifying);
|
||||
|
||||
void setIncremental(boolean incremental);
|
||||
|
||||
void setDebugInformationGenerated(boolean debugInformationGenerated);
|
||||
|
||||
void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated);
|
||||
|
||||
void setSourceFilesCopied(boolean sourceFilesCopied);
|
||||
|
||||
Properties getProperties();
|
||||
|
||||
List<ClassHolderTransformer> getTransformers();
|
||||
|
||||
void setLog(TeaVMToolLog log);
|
||||
|
||||
void setClassLoader(ClassLoader classLoader);
|
||||
|
||||
void addSourceFileProvider(SourceFileProvider sourceFileProvider);
|
||||
}
|
|
@ -21,6 +21,7 @@ import org.teavm.callgraph.CallGraphNode;
|
|||
import org.teavm.callgraph.CallSite;
|
||||
import org.teavm.diagnostics.DefaultProblemTextConsumer;
|
||||
import org.teavm.diagnostics.Problem;
|
||||
import org.teavm.diagnostics.ProblemProvider;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.TextLocation;
|
||||
|
@ -31,9 +32,12 @@ public final class TeaVMProblemRenderer {
|
|||
}
|
||||
|
||||
public static void describeProblems(TeaVM vm, TeaVMToolLog log) {
|
||||
CallGraph cg = vm.getDependencyInfo().getCallGraph();
|
||||
describeProblems(vm.getDependencyInfo().getCallGraph(), vm.getProblemProvider(), log);
|
||||
}
|
||||
|
||||
public static void describeProblems(CallGraph cg, ProblemProvider problems, TeaVMToolLog log) {
|
||||
DefaultProblemTextConsumer consumer = new DefaultProblemTextConsumer();
|
||||
for (Problem problem : vm.getProblemProvider().getProblems()) {
|
||||
for (Problem problem : problems.getProblems()) {
|
||||
consumer.clear();
|
||||
problem.render(consumer);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
|
@ -22,6 +22,8 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -61,7 +63,7 @@ import org.teavm.vm.TeaVMOptimizationLevel;
|
|||
import org.teavm.vm.TeaVMProgressListener;
|
||||
import org.teavm.vm.TeaVMTarget;
|
||||
|
||||
public class TeaVMTool implements BaseTeaVMTool {
|
||||
public class TeaVMTool {
|
||||
private File targetDirectory = new File(".");
|
||||
private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
|
||||
private String targetFileName = "";
|
||||
|
@ -73,7 +75,7 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
private boolean sourceFilesCopied;
|
||||
private boolean incremental;
|
||||
private File cacheDirectory = new File("./teavm-cache");
|
||||
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||
private List<String> transformers = new ArrayList<>();
|
||||
private List<String> classesToPreserve = new ArrayList<>();
|
||||
private TeaVMToolLog log = new EmptyTeaVMToolLog();
|
||||
private ClassLoader classLoader = TeaVMTool.class.getClassLoader();
|
||||
|
@ -99,7 +101,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return targetDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetDirectory(File targetDirectory) {
|
||||
this.targetDirectory = targetDirectory;
|
||||
}
|
||||
|
@ -116,7 +117,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return minifying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinifying(boolean minifying) {
|
||||
this.minifying = minifying;
|
||||
}
|
||||
|
@ -125,7 +125,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return incremental;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIncremental(boolean incremental) {
|
||||
this.incremental = incremental;
|
||||
}
|
||||
|
@ -142,7 +141,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return debugInformationGenerated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDebugInformationGenerated(boolean debugInformationGenerated) {
|
||||
this.debugInformationGenerated = debugInformationGenerated;
|
||||
}
|
||||
|
@ -159,7 +157,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return sourceMapsFileGenerated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated) {
|
||||
this.sourceMapsFileGenerated = sourceMapsFileGenerated;
|
||||
}
|
||||
|
@ -168,18 +165,15 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return sourceFilesCopied;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceFilesCopied(boolean sourceFilesCopied) {
|
||||
this.sourceFilesCopied = sourceFilesCopied;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClassHolderTransformer> getTransformers() {
|
||||
public List<String> getTransformers() {
|
||||
return transformers;
|
||||
}
|
||||
|
||||
|
@ -191,7 +185,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLog(TeaVMToolLog log) {
|
||||
this.log = log;
|
||||
}
|
||||
|
@ -220,7 +213,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
@ -289,7 +281,6 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
return resources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
|
||||
sourceFileProviders.add(sourceFileProvider);
|
||||
}
|
||||
|
@ -377,7 +368,7 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
vm.setOptimizationLevel(optimizationLevel);
|
||||
|
||||
vm.installPlugins();
|
||||
for (ClassHolderTransformer transformer : transformers) {
|
||||
for (ClassHolderTransformer transformer : resolveTransformers(classLoader)) {
|
||||
vm.add(transformer);
|
||||
}
|
||||
if (mainClass != null) {
|
||||
|
@ -402,10 +393,8 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
log.info("Output file successfully built");
|
||||
} else if (problemProvider.getSevereProblems().isEmpty()) {
|
||||
log.info("Output file built with warnings");
|
||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||
} else {
|
||||
log.info("Output file built with errors");
|
||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||
}
|
||||
|
||||
File outputFile = new File(targetDirectory, outputName);
|
||||
|
@ -507,4 +496,41 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
copier.setLog(log);
|
||||
copier.copy(new File(targetDirectory, "src"));
|
||||
}
|
||||
|
||||
private List<ClassHolderTransformer> resolveTransformers(ClassLoader classLoader) {
|
||||
List<ClassHolderTransformer> transformerInstances = new ArrayList<>();
|
||||
if (transformers == null) {
|
||||
return transformerInstances;
|
||||
}
|
||||
for (String transformerName : transformers) {
|
||||
Class<?> transformerRawType;
|
||||
try {
|
||||
transformerRawType = Class.forName(transformerName, true, classLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error("Transformer not found: " + transformerName, e);
|
||||
continue;
|
||||
}
|
||||
if (!ClassHolderTransformer.class.isAssignableFrom(transformerRawType)) {
|
||||
log.error("Transformer " + transformerName + " is not subtype of "
|
||||
+ ClassHolderTransformer.class.getName());
|
||||
continue;
|
||||
}
|
||||
Class<? extends ClassHolderTransformer> transformerType = transformerRawType.asSubclass(
|
||||
ClassHolderTransformer.class);
|
||||
Constructor<? extends ClassHolderTransformer> ctor;
|
||||
try {
|
||||
ctor = transformerType.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
log.error("Transformer " + transformerName + " has no default constructor");
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
ClassHolderTransformer transformer = ctor.newInstance();
|
||||
transformerInstances.add(transformer);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
log.error("Error instantiating transformer " + transformerName, e);
|
||||
}
|
||||
}
|
||||
return transformerInstances;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2018 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.tooling.builder;
|
||||
|
||||
public class BuildException extends Exception {
|
||||
public BuildException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,19 +13,15 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps.model;
|
||||
package org.teavm.tooling.builder;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.teavm.callgraph.CallGraph;
|
||||
import org.teavm.diagnostics.ProblemProvider;
|
||||
|
||||
public interface TeaVMBuildResult {
|
||||
public interface BuildResult {
|
||||
CallGraph getCallGraph();
|
||||
|
||||
boolean isErrorOccurred();
|
||||
|
||||
String getStackTrace();
|
||||
|
||||
ProblemProvider getProblems();
|
||||
|
||||
Collection<String> getUsedResources();
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,16 +13,21 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps.model;
|
||||
package org.teavm.tooling.builder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||
import org.teavm.tooling.TeaVMTargetType;
|
||||
import org.teavm.tooling.TeaVMToolLog;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
|
||||
public interface TeaVMBuildStrategy {
|
||||
public interface BuildStrategy {
|
||||
void init();
|
||||
|
||||
void setLog(TeaVMToolLog log);
|
||||
|
||||
void addSourcesDirectory(String directory);
|
||||
|
||||
void addSourcesJar(String jarFile);
|
||||
|
@ -45,7 +50,21 @@ public interface TeaVMBuildStrategy {
|
|||
|
||||
void setIncremental(boolean incremental);
|
||||
|
||||
void setMinifying(boolean minifying);
|
||||
|
||||
void setProperties(Properties properties);
|
||||
|
||||
TeaVMBuildResult build();
|
||||
void setTransformers(String[] transformers);
|
||||
|
||||
void setOptimizationLevel(TeaVMOptimizationLevel level);
|
||||
|
||||
void setTargetFileName(String targetFileName);
|
||||
|
||||
void setClassesToPreserve(String[] classesToPreserve);
|
||||
|
||||
void setCacheDirectory(String cacheDirectory);
|
||||
|
||||
void setWasmVersion(WasmBinaryVersion wasmVersion);
|
||||
|
||||
BuildResult build() throws BuildException;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2018 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.tooling.builder;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public interface ClassLoaderFactory {
|
||||
ClassLoader create(URL[] urls, ClassLoader innerClassLoader);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,48 +13,56 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps;
|
||||
package org.teavm.tooling.builder;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||
import org.teavm.callgraph.CallGraph;
|
||||
import org.teavm.diagnostics.ProblemProvider;
|
||||
import org.teavm.idea.jps.model.TeaVMBuildResult;
|
||||
import org.teavm.idea.jps.model.TeaVMBuildStrategy;
|
||||
import org.teavm.idea.jps.util.ExceptionUtil;
|
||||
import org.teavm.tooling.EmptyTeaVMToolLog;
|
||||
import org.teavm.tooling.TeaVMTargetType;
|
||||
import org.teavm.tooling.TeaVMTool;
|
||||
import org.teavm.tooling.TeaVMToolException;
|
||||
import org.teavm.tooling.TeaVMToolLog;
|
||||
import org.teavm.tooling.sources.DirectorySourceFileProvider;
|
||||
import org.teavm.tooling.sources.JarSourceFileProvider;
|
||||
import org.teavm.tooling.sources.SourceFileProvider;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
|
||||
public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
||||
private final CompileContext context;
|
||||
public class InProcessBuildStrategy implements BuildStrategy {
|
||||
private final ClassLoaderFactory classLoaderFactory;
|
||||
private List<String> classPathEntries = new ArrayList<>();
|
||||
private TeaVMTargetType targetType;
|
||||
private String mainClass;
|
||||
private String targetDirectory;
|
||||
private String targetFileName = "";
|
||||
private boolean incremental;
|
||||
private String cacheDirectory;
|
||||
private TeaVMOptimizationLevel optimizationLevel = TeaVMOptimizationLevel.ADVANCED;
|
||||
private boolean minifying;
|
||||
private boolean sourceMapsFileGenerated;
|
||||
private boolean debugInformationGenerated;
|
||||
private boolean sourceFilesCopied;
|
||||
private String[] transformers = new String[0];
|
||||
private String[] classesToPreserve = new String[0];
|
||||
private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0x1;
|
||||
private final List<SourceFileProvider> sourceFileProviders = new ArrayList<>();
|
||||
private TeaVMProgressListener progressListener;
|
||||
private Properties properties = new Properties();
|
||||
private TeaVMToolLog log = new EmptyTeaVMToolLog();
|
||||
|
||||
public InProcessBuildStrategy(CompileContext context) {
|
||||
this.context = context;
|
||||
public InProcessBuildStrategy(ClassLoaderFactory classLoaderFactory) {
|
||||
this.classLoaderFactory = classLoaderFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,6 +123,7 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
|||
|
||||
@Override
|
||||
public void setIncremental(boolean incremental) {
|
||||
this.incremental = incremental;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,20 +133,67 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TeaVMBuildResult build() {
|
||||
public void setLog(TeaVMToolLog log) {
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinifying(boolean minifying) {
|
||||
this.minifying = minifying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransformers(String[] transformers) {
|
||||
this.transformers = transformers.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOptimizationLevel(TeaVMOptimizationLevel level) {
|
||||
this.optimizationLevel = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetFileName(String targetFileName) {
|
||||
this.targetFileName = targetFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassesToPreserve(String[] classesToPreserve) {
|
||||
this.classesToPreserve = classesToPreserve.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCacheDirectory(String cacheDirectory) {
|
||||
this.cacheDirectory = cacheDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWasmVersion(WasmBinaryVersion wasmVersion) {
|
||||
this.wasmVersion = wasmVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildResult build() throws BuildException {
|
||||
TeaVMTool tool = new TeaVMTool();
|
||||
tool.setProgressListener(progressListener);
|
||||
tool.setLog(new EmptyTeaVMToolLog());
|
||||
tool.setLog(log);
|
||||
tool.setTargetType(targetType);
|
||||
tool.setMainClass(mainClass);
|
||||
tool.setTargetDirectory(new File(targetDirectory));
|
||||
tool.setTargetFileName(targetFileName);
|
||||
tool.setClassLoader(buildClassLoader());
|
||||
tool.setOptimizationLevel(optimizationLevel);
|
||||
|
||||
tool.setSourceMapsFileGenerated(sourceMapsFileGenerated);
|
||||
tool.setDebugInformationGenerated(debugInformationGenerated);
|
||||
tool.setSourceFilesCopied(sourceFilesCopied);
|
||||
|
||||
tool.setMinifying(false);
|
||||
tool.setMinifying(minifying);
|
||||
tool.setIncremental(incremental);
|
||||
tool.getTransformers().addAll(Arrays.asList(transformers));
|
||||
tool.getClassesToPreserve().addAll(Arrays.asList(classesToPreserve));
|
||||
tool.setCacheDirectory(cacheDirectory != null ? new File(cacheDirectory) : null);
|
||||
tool.setWasmVersion(wasmVersion);
|
||||
|
||||
tool.getProperties().putAll(properties);
|
||||
|
||||
|
@ -145,22 +201,17 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
|||
tool.addSourceFileProvider(fileProvider);
|
||||
}
|
||||
|
||||
boolean errorOccurred = false;
|
||||
String stackTrace = null;
|
||||
try {
|
||||
tool.generate();
|
||||
} catch (TeaVMToolException | RuntimeException | Error e) {
|
||||
e.printStackTrace(System.err);
|
||||
stackTrace = ExceptionUtil.exceptionToString(e);
|
||||
context.processMessage(new CompilerMessage("TeaVM", e));
|
||||
errorOccurred = true;
|
||||
throw new BuildException(e);
|
||||
}
|
||||
|
||||
Set<String> generatedFiles = tool.getGeneratedFiles().stream()
|
||||
.map(File::getAbsolutePath)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return new InProcessBuildResult(tool.getDependencyInfo().getCallGraph(), errorOccurred, stackTrace,
|
||||
return new InProcessBuildResult(tool.getDependencyInfo().getCallGraph(),
|
||||
tool.getProblemProvider(), tool.getClasses(), tool.getUsedResources(), generatedFiles);
|
||||
}
|
||||
|
||||
|
@ -173,26 +224,19 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
|||
}
|
||||
}).toArray(URL[]::new);
|
||||
|
||||
RenamingClassLoader classLoader = new RenamingClassLoader(urls, TeaVMBuilder.class.getClassLoader());
|
||||
classLoader.rename("org/objectweb/asm/", "org/teavm/asm/");
|
||||
return classLoader;
|
||||
return classLoaderFactory.create(urls, InProcessBuildStrategy.class.getClassLoader());
|
||||
}
|
||||
|
||||
static class InProcessBuildResult implements TeaVMBuildResult {
|
||||
static class InProcessBuildResult implements BuildResult {
|
||||
private CallGraph callGraph;
|
||||
private boolean errorOccurred;
|
||||
private String stackTrace;
|
||||
private ProblemProvider problemProvider;
|
||||
private Collection<String> classes;
|
||||
private Collection<String> usedResources;
|
||||
private Collection<String> generatedFiles;
|
||||
|
||||
InProcessBuildResult(CallGraph callGraph, boolean errorOccurred, String stackTrace,
|
||||
ProblemProvider problemProvider, Collection<String> classes, Collection<String> usedResources,
|
||||
Collection<String> generatedFiles) {
|
||||
InProcessBuildResult(CallGraph callGraph, ProblemProvider problemProvider,
|
||||
Collection<String> classes, Collection<String> usedResources, Collection<String> generatedFiles) {
|
||||
this.callGraph = callGraph;
|
||||
this.errorOccurred = errorOccurred;
|
||||
this.stackTrace = stackTrace;
|
||||
this.problemProvider = problemProvider;
|
||||
this.classes = classes;
|
||||
this.usedResources = usedResources;
|
||||
|
@ -204,16 +248,6 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
|||
return callGraph;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorOccurred() {
|
||||
return errorOccurred;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackTrace() {
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemProvider getProblems() {
|
||||
return problemProvider;
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,39 +13,44 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps;
|
||||
package org.teavm.tooling.builder;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||
import org.teavm.callgraph.CallGraph;
|
||||
import org.teavm.diagnostics.Problem;
|
||||
import org.teavm.diagnostics.ProblemProvider;
|
||||
import org.teavm.idea.jps.model.TeaVMBuildResult;
|
||||
import org.teavm.idea.jps.model.TeaVMBuildStrategy;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildCallback;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildRequest;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildResponse;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
|
||||
import org.teavm.tooling.EmptyTeaVMToolLog;
|
||||
import org.teavm.tooling.TeaVMTargetType;
|
||||
import org.teavm.tooling.TeaVMToolLog;
|
||||
import org.teavm.tooling.daemon.RemoteBuildCallback;
|
||||
import org.teavm.tooling.daemon.RemoteBuildRequest;
|
||||
import org.teavm.tooling.daemon.RemoteBuildResponse;
|
||||
import org.teavm.tooling.daemon.RemoteBuildService;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
import org.teavm.vm.TeaVMPhase;
|
||||
import org.teavm.vm.TeaVMProgressFeedback;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
|
||||
public class RemoteBuildStrategy implements TeaVMBuildStrategy {
|
||||
private TeaVMRemoteBuildRequest request;
|
||||
private TeaVMRemoteBuildService buildService;
|
||||
public class RemoteBuildStrategy implements BuildStrategy {
|
||||
private RemoteBuildRequest request;
|
||||
private RemoteBuildService buildService;
|
||||
private TeaVMProgressListener progressListener;
|
||||
private TeaVMToolLog log = new EmptyTeaVMToolLog();
|
||||
|
||||
public RemoteBuildStrategy(TeaVMRemoteBuildService buildService) {
|
||||
public RemoteBuildStrategy(RemoteBuildService buildService) {
|
||||
this.buildService = buildService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
request = new TeaVMRemoteBuildRequest();
|
||||
request = new RemoteBuildRequest();
|
||||
request.optimizationLevel = TeaVMOptimizationLevel.ADVANCED;
|
||||
request.wasmVersion = WasmBinaryVersion.V_0x1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -110,14 +115,57 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TeaVMBuildResult build() {
|
||||
TeaVMRemoteBuildResponse response;
|
||||
try {
|
||||
response = buildService.build(request, new CallbackImpl(progressListener));
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
public void setLog(TeaVMToolLog log) {
|
||||
this.log = log;
|
||||
}
|
||||
return new TeaVMBuildResult() {
|
||||
|
||||
@Override
|
||||
public void setMinifying(boolean minifying) {
|
||||
request.minifying = minifying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransformers(String[] transformers) {
|
||||
request.transformers = transformers.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOptimizationLevel(TeaVMOptimizationLevel level) {
|
||||
request.optimizationLevel = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetFileName(String targetFileName) {
|
||||
request.tagetFileName = targetFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassesToPreserve(String[] classesToPreserve) {
|
||||
request.classesToPreserve = classesToPreserve.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCacheDirectory(String cacheDirectory) {
|
||||
request.cacheDirectory = cacheDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWasmVersion(WasmBinaryVersion wasmVersion) {
|
||||
request.wasmVersion = wasmVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildResult build() throws BuildException {
|
||||
RemoteBuildResponse response;
|
||||
try {
|
||||
response = buildService.build(request, new CallbackImpl(progressListener, log));
|
||||
} catch (Throwable e) {
|
||||
throw new BuildException(e);
|
||||
}
|
||||
if (response.exception != null) {
|
||||
throw new BuildException(response.exception);
|
||||
}
|
||||
return new BuildResult() {
|
||||
private ProblemProvider problems = new ProblemProvider() {
|
||||
@Override
|
||||
public List<Problem> getProblems() {
|
||||
|
@ -135,16 +183,6 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy {
|
|||
return response.callGraph;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorOccurred() {
|
||||
return response.errorOccurred;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackTrace() {
|
||||
return response.stackTrace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemProvider getProblems() {
|
||||
return problems;
|
||||
|
@ -167,22 +205,54 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy {
|
|||
};
|
||||
}
|
||||
|
||||
static class CallbackImpl extends UnicastRemoteObject implements TeaVMRemoteBuildCallback {
|
||||
static class CallbackImpl extends UnicastRemoteObject implements RemoteBuildCallback {
|
||||
private TeaVMProgressListener listener;
|
||||
private TeaVMToolLog log;
|
||||
|
||||
public CallbackImpl(TeaVMProgressListener listener) throws RemoteException {
|
||||
public CallbackImpl(TeaVMProgressListener listener, TeaVMToolLog log) throws RemoteException {
|
||||
super();
|
||||
this.listener = listener;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) throws RemoteException {
|
||||
return listener.phaseStarted(phase, count);
|
||||
public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
|
||||
return listener != null ? listener.phaseStarted(phase, count) : TeaVMProgressFeedback.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TeaVMProgressFeedback progressReached(int progress) throws RemoteException {
|
||||
return listener.progressReached(progress);
|
||||
public TeaVMProgressFeedback progressReached(int progress) {
|
||||
return listener != null ? listener.progressReached(progress) : TeaVMProgressFeedback.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorReported(String message, Throwable e) {
|
||||
log.error(message, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorReported(String message) {
|
||||
log.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warningReported(String message, Throwable e) {
|
||||
log.warning(message, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warningReported(String message) {
|
||||
log.warning(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void infoReported(String message, Throwable e) {
|
||||
log.info(message, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void infoReported(String message) {
|
||||
log.info(message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,11 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.daemon;
|
||||
package org.teavm.tooling.daemon;
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -34,22 +31,12 @@ import java.rmi.registry.Registry;
|
|||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildCallback;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildRequest;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildResponse;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
|
||||
import org.teavm.idea.jps.util.ExceptionUtil;
|
||||
import org.teavm.tooling.EmptyTeaVMToolLog;
|
||||
import org.teavm.tooling.TeaVMTool;
|
||||
import org.teavm.tooling.TeaVMToolException;
|
||||
import org.teavm.tooling.sources.DirectorySourceFileProvider;
|
||||
|
@ -58,15 +45,12 @@ import org.teavm.vm.TeaVMPhase;
|
|||
import org.teavm.vm.TeaVMProgressFeedback;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
|
||||
public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemoteBuildService {
|
||||
public class BuildDaemon extends UnicastRemoteObject implements RemoteBuildService {
|
||||
private static final int MIN_PORT = 10000;
|
||||
private static final int MAX_PORT = 1 << 16;
|
||||
private static final Set<String> KOTLIN_FILES = new HashSet<>(Arrays.asList("teavm-jps-common.jar",
|
||||
"teavm-plugin.jar", "teavm.jar"));
|
||||
private static final String DAEMON_CLASS = TeaVMBuildDaemon.class.getName().replace('.', '/') + ".class";
|
||||
private static final int DAEMON_CLASS_DEPTH;
|
||||
private static final String DAEMON_MESSAGE_PREFIX = "TeaVM daemon port: ";
|
||||
private static final String INCREMENTAL_PROPERTY = "teavm.daemon.incremental";
|
||||
private static final String DEBUG_PORT_PROPERTY = "teavm.daemon.debug.port";
|
||||
private boolean incremental;
|
||||
private int port;
|
||||
private Registry registry;
|
||||
|
@ -74,17 +58,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
private ClassLoader lastJarClassLoader;
|
||||
private List<String> lastJarClassPath;
|
||||
|
||||
static {
|
||||
int depth = 0;
|
||||
for (int i = 0; i < DAEMON_CLASS.length(); ++i) {
|
||||
if (DAEMON_CLASS.charAt(i) == '/') {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
DAEMON_CLASS_DEPTH = depth;
|
||||
}
|
||||
|
||||
TeaVMBuildDaemon(boolean incremental) throws RemoteException {
|
||||
BuildDaemon(boolean incremental) throws RemoteException {
|
||||
super();
|
||||
this.incremental = incremental;
|
||||
Random random = new Random();
|
||||
|
@ -96,7 +70,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
continue;
|
||||
}
|
||||
try {
|
||||
registry.bind(TeaVMRemoteBuildService.ID, this);
|
||||
registry.bind(RemoteBuildService.ID, this);
|
||||
} catch (RemoteException | AlreadyBoundException e) {
|
||||
throw new IllegalStateException("Could not bind remote build assistant service", e);
|
||||
}
|
||||
|
@ -139,7 +113,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
|
||||
public static void main(String[] args) throws RemoteException {
|
||||
boolean incremental = Boolean.parseBoolean(System.getProperty(INCREMENTAL_PROPERTY, "false"));
|
||||
TeaVMBuildDaemon daemon = new TeaVMBuildDaemon(incremental);
|
||||
BuildDaemon daemon = new BuildDaemon(incremental);
|
||||
System.out.println(DAEMON_MESSAGE_PREFIX + daemon.port);
|
||||
if (daemon.incrementalCache != null) {
|
||||
System.out.println("Incremental cache set up in " + daemon.incrementalCache);
|
||||
|
@ -147,8 +121,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
}
|
||||
|
||||
@Override
|
||||
public TeaVMRemoteBuildResponse build(TeaVMRemoteBuildRequest request, TeaVMRemoteBuildCallback callback)
|
||||
throws RemoteException {
|
||||
public RemoteBuildResponse build(RemoteBuildRequest request, RemoteBuildCallback callback) {
|
||||
System.out.println("Build started");
|
||||
|
||||
if (!request.incremental && incremental) {
|
||||
|
@ -163,21 +136,34 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
TeaVMTool tool = new TeaVMTool();
|
||||
tool.setIncremental(incremental && request.incremental);
|
||||
if (tool.isIncremental()) {
|
||||
tool.setCacheDirectory(incrementalCache);
|
||||
tool.setCacheDirectory(request.cacheDirectory != null
|
||||
? new File(request.cacheDirectory)
|
||||
: incrementalCache);
|
||||
}
|
||||
tool.setProgressListener(createProgressListener(callback));
|
||||
tool.setLog(new EmptyTeaVMToolLog());
|
||||
tool.setLog(new RemoteBuildLog(callback));
|
||||
if (request.transformers != null) {
|
||||
tool.getTransformers().addAll(Arrays.asList(request.transformers));
|
||||
}
|
||||
if (request.classesToPreserve != null) {
|
||||
tool.getClassesToPreserve().addAll(Arrays.asList(request.classesToPreserve));
|
||||
}
|
||||
tool.setTargetType(request.targetType);
|
||||
tool.setMainClass(request.mainClass);
|
||||
tool.setTargetDirectory(new File(request.targetDirectory));
|
||||
tool.setTargetFileName(request.tagetFileName);
|
||||
tool.setClassLoader(buildClassLoader(request.classPath, incremental && request.incremental));
|
||||
|
||||
tool.setSourceMapsFileGenerated(request.sourceMapsFileGenerated);
|
||||
tool.setDebugInformationGenerated(request.debugInformationGenerated);
|
||||
tool.setSourceFilesCopied(request.sourceFilesCopied);
|
||||
if (request.properties != null) {
|
||||
tool.getProperties().putAll(request.properties);
|
||||
}
|
||||
|
||||
tool.setMinifying(false);
|
||||
tool.setOptimizationLevel(request.optimizationLevel);
|
||||
tool.setMinifying(request.minifying);
|
||||
tool.setWasmVersion(request.wasmVersion);
|
||||
|
||||
for (String sourceDirectory : request.sourceDirectories) {
|
||||
tool.addSourceFileProvider(new DirectorySourceFileProvider(new File(sourceDirectory)));
|
||||
|
@ -186,19 +172,15 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
tool.addSourceFileProvider(new JarSourceFileProvider(new File(sourceJar)));
|
||||
}
|
||||
|
||||
boolean errorOccurred = false;
|
||||
String stackTrace = null;
|
||||
RemoteBuildResponse response = new RemoteBuildResponse();
|
||||
try {
|
||||
tool.generate();
|
||||
System.out.println("Build complete");
|
||||
} catch (TeaVMToolException | RuntimeException | Error e) {
|
||||
stackTrace = ExceptionUtil.exceptionToString(e);
|
||||
errorOccurred = true;
|
||||
response.exception = e;
|
||||
}
|
||||
|
||||
TeaVMRemoteBuildResponse response = new TeaVMRemoteBuildResponse();
|
||||
response.errorOccurred = errorOccurred;
|
||||
response.stackTrace = stackTrace;
|
||||
if (response.exception == null) {
|
||||
response.callGraph = tool.getDependencyInfo().getCallGraph();
|
||||
response.problems.addAll(tool.getProblemProvider().getProblems());
|
||||
response.severeProblems.addAll(tool.getProblemProvider().getSevereProblems());
|
||||
|
@ -207,6 +189,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
response.generatedFiles.addAll(tool.getGeneratedFiles().stream()
|
||||
.map(File::getAbsolutePath)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@ -254,7 +237,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
return new URLClassLoader(urls, jarClassLoader);
|
||||
}
|
||||
|
||||
private TeaVMProgressListener createProgressListener(TeaVMRemoteBuildCallback callback) {
|
||||
private TeaVMProgressListener createProgressListener(RemoteBuildCallback callback) {
|
||||
return new TeaVMProgressListener() {
|
||||
private long lastReportedTime;
|
||||
|
||||
|
@ -283,18 +266,26 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
};
|
||||
}
|
||||
|
||||
public static TeaVMDaemonInfo start(boolean incremental, int daemonMemory) throws IOException {
|
||||
public static DaemonInfo start(boolean incremental, int daemonMemory, DaemonLog log,
|
||||
String... classPathEntries) throws IOException {
|
||||
String javaHome = System.getProperty("java.home");
|
||||
String javaCommand = javaHome + "/bin/java";
|
||||
String classPath = String.join(File.pathSeparator, detectClassPath());
|
||||
ProcessBuilder builder = new ProcessBuilder(javaCommand, "-cp", classPath,
|
||||
String classPath = String.join(File.pathSeparator, classPathEntries);
|
||||
List<String> arguments = new ArrayList<>();
|
||||
|
||||
arguments.addAll(Arrays.asList(javaCommand, "-cp", classPath,
|
||||
"-D" + INCREMENTAL_PROPERTY + "=" + incremental,
|
||||
"-Xmx" + daemonMemory + "m",
|
||||
TeaVMBuildDaemon.class.getName());
|
||||
"-Xmx" + daemonMemory + "m"));
|
||||
|
||||
String debugPort = System.getProperty(DEBUG_PORT_PROPERTY);
|
||||
if (debugPort != null) {
|
||||
arguments.add("-agentlib:jdwp=transport=dt_socket,quiet=y,server=y,address=" + debugPort + ",suspend=y");
|
||||
}
|
||||
|
||||
arguments.add(BuildDaemon.class.getName());
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(arguments.toArray(new String[0]));
|
||||
Process process = builder.start();
|
||||
|
||||
Log log = LogFactory.getLog(TeaVMBuildDaemon.class);
|
||||
|
||||
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream(),
|
||||
StandardCharsets.UTF_8));
|
||||
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream(),
|
||||
|
@ -311,6 +302,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
}
|
||||
IOUtils.closeQuietly(stderrReader);
|
||||
IOUtils.closeQuietly(stdoutReader);
|
||||
process.destroy();
|
||||
throw new IllegalStateException("Could not start daemon. Stderr: " + sb);
|
||||
}
|
||||
int port = Integer.parseInt(line.substring(DAEMON_MESSAGE_PREFIX.length()));
|
||||
|
@ -318,7 +310,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
daemonThread(new DaemonProcessOutputWatcher(log, stdoutReader, "stdout", false)).start();
|
||||
daemonThread(new DaemonProcessOutputWatcher(log, stderrReader, "stderr", true)).start();
|
||||
|
||||
return new TeaVMDaemonInfo(port, process);
|
||||
return new DaemonInfo(port, process);
|
||||
}
|
||||
|
||||
private static Thread daemonThread(Runnable runnable) {
|
||||
|
@ -328,12 +320,12 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
}
|
||||
|
||||
static class DaemonProcessOutputWatcher implements Runnable {
|
||||
private Log log;
|
||||
private DaemonLog log;
|
||||
private BufferedReader reader;
|
||||
private String name;
|
||||
private boolean isError;
|
||||
|
||||
public DaemonProcessOutputWatcher(Log log, BufferedReader reader, String name, boolean isError) {
|
||||
DaemonProcessOutputWatcher(DaemonLog log, BufferedReader reader, String name, boolean isError) {
|
||||
this.log = log;
|
||||
this.reader = reader;
|
||||
this.name = name;
|
||||
|
@ -359,30 +351,4 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> detectClassPath() {
|
||||
IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId("org.teavm.idea"));
|
||||
Set<File> visited = new HashSet<>();
|
||||
List<String> classPath = new ArrayList<>();
|
||||
findInHierarchy(plugin.getPath(), classPath, visited);
|
||||
return classPath;
|
||||
}
|
||||
|
||||
private static void findInHierarchy(File file, List<String> targetFiles, Set<File> visited) {
|
||||
if (!visited.add(file)) {
|
||||
return;
|
||||
}
|
||||
if (file.isFile() && KOTLIN_FILES.contains(file.getName())) {
|
||||
targetFiles.add(file.getAbsolutePath());
|
||||
} else if (file.getPath().endsWith(DAEMON_CLASS)) {
|
||||
for (int i = 0; i <= DAEMON_CLASS_DEPTH; ++i) {
|
||||
file = file.getParentFile();
|
||||
}
|
||||
targetFiles.add(file.getAbsolutePath());
|
||||
} else if (file.isDirectory()) {
|
||||
for (File childFile : file.listFiles()) {
|
||||
findInHierarchy(childFile, targetFiles, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,13 +13,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.daemon;
|
||||
package org.teavm.tooling.daemon;
|
||||
|
||||
public class TeaVMDaemonInfo {
|
||||
public class DaemonInfo {
|
||||
private int port;
|
||||
private Process process;
|
||||
|
||||
TeaVMDaemonInfo(int port, Process process) {
|
||||
DaemonInfo(int port, Process process) {
|
||||
this.port = port;
|
||||
this.process = process;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2018 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.tooling.daemon;
|
||||
|
||||
public interface DaemonLog {
|
||||
void error(String message);
|
||||
|
||||
void error(String message, Throwable e);
|
||||
|
||||
void info(String message);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,15 +13,27 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps.remote;
|
||||
package org.teavm.tooling.daemon;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import org.teavm.vm.TeaVMPhase;
|
||||
import org.teavm.vm.TeaVMProgressFeedback;
|
||||
|
||||
public interface TeaVMRemoteBuildCallback extends Remote {
|
||||
public interface RemoteBuildCallback extends Remote {
|
||||
TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) throws RemoteException;
|
||||
|
||||
TeaVMProgressFeedback progressReached(int progress) throws RemoteException;
|
||||
|
||||
void errorReported(String message, Throwable e) throws RemoteException;
|
||||
|
||||
void errorReported(String message) throws RemoteException;
|
||||
|
||||
void warningReported(String message, Throwable e) throws RemoteException;
|
||||
|
||||
void warningReported(String message) throws RemoteException;
|
||||
|
||||
void infoReported(String message, Throwable e) throws RemoteException;
|
||||
|
||||
void infoReported(String message) throws RemoteException;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2018 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.tooling.daemon;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
import org.teavm.tooling.TeaVMToolLog;
|
||||
|
||||
class RemoteBuildLog implements TeaVMToolLog {
|
||||
private RemoteBuildCallback callback;
|
||||
|
||||
RemoteBuildLog(RemoteBuildCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String text) {
|
||||
try {
|
||||
callback.infoReported(text);
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String text) {
|
||||
try {
|
||||
callback.warningReported(text);
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String text) {
|
||||
try {
|
||||
callback.errorReported(text);
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String text, Throwable e) {
|
||||
try {
|
||||
callback.infoReported(text, e);
|
||||
} catch (RemoteException e2) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text, Throwable e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String text, Throwable e) {
|
||||
try {
|
||||
callback.warningReported(text, e);
|
||||
} catch (RemoteException e2) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String text, Throwable e) {
|
||||
try {
|
||||
callback.errorReported(text, e);
|
||||
} catch (RemoteException e2) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,24 +13,33 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps.remote;
|
||||
package org.teavm.tooling.daemon;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||
import org.teavm.tooling.TeaVMTargetType;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
|
||||
public class TeaVMRemoteBuildRequest implements Serializable {
|
||||
public class RemoteBuildRequest implements Serializable {
|
||||
public final List<String> sourceDirectories = new ArrayList<>();
|
||||
public final List<String> sourceJarFiles = new ArrayList<>();
|
||||
public final List<String> classPath = new ArrayList<>();
|
||||
public String[] transformers;
|
||||
public String[] classesToPreserve;
|
||||
public TeaVMTargetType targetType;
|
||||
public String mainClass;
|
||||
public String targetDirectory;
|
||||
public String tagetFileName = "";
|
||||
public boolean sourceMapsFileGenerated;
|
||||
public boolean debugInformationGenerated;
|
||||
public boolean sourceFilesCopied;
|
||||
public boolean incremental;
|
||||
public String cacheDirectory;
|
||||
public boolean minifying;
|
||||
public Properties properties;
|
||||
public TeaVMOptimizationLevel optimizationLevel;
|
||||
public WasmBinaryVersion wasmVersion;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps.remote;
|
||||
package org.teavm.tooling.daemon;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
@ -23,13 +23,12 @@ import java.util.Set;
|
|||
import org.teavm.callgraph.CallGraph;
|
||||
import org.teavm.diagnostics.Problem;
|
||||
|
||||
public class TeaVMRemoteBuildResponse implements Serializable {
|
||||
public class RemoteBuildResponse implements Serializable {
|
||||
public CallGraph callGraph;
|
||||
public boolean errorOccurred;
|
||||
public final List<Problem> problems = new ArrayList<>();
|
||||
public final List<Problem> severeProblems = new ArrayList<>();
|
||||
public final Set<String> usedResources = new HashSet<>();
|
||||
public final Set<String> classes = new HashSet<>();
|
||||
public final Set<String> generatedFiles = new HashSet<>();
|
||||
public String stackTrace;
|
||||
public Throwable exception;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,15 +13,14 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.idea.jps.remote;
|
||||
package org.teavm.tooling.daemon;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
public interface TeaVMRemoteBuildService extends Remote {
|
||||
public interface RemoteBuildService extends Remote {
|
||||
String REMOTE_PORT = "teavm.daemon.remote-port";
|
||||
String ID = "TeaVM-Daemon";
|
||||
|
||||
TeaVMRemoteBuildResponse build(TeaVMRemoteBuildRequest request, TeaVMRemoteBuildCallback callback)
|
||||
throws RemoteException;
|
||||
RemoteBuildResponse build(RemoteBuildRequest request, RemoteBuildCallback callback) throws RemoteException;
|
||||
}
|
|
@ -157,9 +157,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
String cacheDir = profile.getCacheDirectory();
|
||||
tool.setCacheDirectory(!cacheDir.isEmpty() ?
|
||||
new File(varManager.performStringSubstitution(cacheDir, false)) : null);
|
||||
for (ClassHolderTransformer transformer : instantiateTransformers(profile, classLoader)) {
|
||||
tool.getTransformers().add(transformer);
|
||||
}
|
||||
tool.getTransformers().addAll(Arrays.asList(profile.getTransformers()));
|
||||
tool.getClassesToPreserve().addAll(profile.getClassesToPreserve());
|
||||
for (SourceFileProvider provider : sourceProviders) {
|
||||
tool.addSourceFileProvider(provider);
|
||||
|
@ -540,42 +538,6 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
return projects;
|
||||
}
|
||||
|
||||
private List<ClassHolderTransformer> instantiateTransformers(TeaVMProfile profile, ClassLoader classLoader)
|
||||
throws CoreException{
|
||||
List<ClassHolderTransformer> transformerInstances = new ArrayList<>();
|
||||
for (String transformerName : profile.getTransformers()) {
|
||||
Class<?> transformerRawType;
|
||||
try {
|
||||
transformerRawType = Class.forName(transformerName, true, classLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
putConfigMarker("Transformer not found: " + transformerName);
|
||||
continue;
|
||||
}
|
||||
if (!ClassHolderTransformer.class.isAssignableFrom(transformerRawType)) {
|
||||
putConfigMarker("Transformer " + transformerName + " is not a subtype of " +
|
||||
ClassHolderTransformer.class.getName());
|
||||
continue;
|
||||
}
|
||||
Class<? extends ClassHolderTransformer> transformerType = transformerRawType.asSubclass(
|
||||
ClassHolderTransformer.class);
|
||||
Constructor<? extends ClassHolderTransformer> ctor;
|
||||
try {
|
||||
ctor = transformerType.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
putConfigMarker("Transformer " + transformerName + " has no default constructor");
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
ClassHolderTransformer transformer = ctor.newInstance();
|
||||
transformerInstances.add(transformer);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
putConfigMarker("Error instantiating transformer " + transformerName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return transformerInstances;
|
||||
}
|
||||
|
||||
private void putConfigMarker(String message) throws CoreException {
|
||||
IMarker marker = getProject().createMarker(TeaVMEclipsePlugin.CONFIG_MARKER_ID);
|
||||
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2018 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.idea.jps.util;
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.teavm.tooling.daemon.BuildDaemon;
|
||||
|
||||
public final class DaemonUtil {
|
||||
private static final Set<String> PLUGIN_FILES = new HashSet<>(Arrays.asList("teavm-jps-common.jar",
|
||||
"teavm-plugin.jar", "teavm.jar"));
|
||||
private static final String DAEMON_CLASS = BuildDaemon.class.getName().replace('.', '/') + ".class";
|
||||
private static final int DAEMON_CLASS_DEPTH;
|
||||
|
||||
static {
|
||||
int depth = 0;
|
||||
for (int i = 0; i < DAEMON_CLASS.length(); ++i) {
|
||||
if (DAEMON_CLASS.charAt(i) == '/') {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
DAEMON_CLASS_DEPTH = depth;
|
||||
}
|
||||
|
||||
private DaemonUtil() {
|
||||
}
|
||||
|
||||
public static List<String> detectClassPath() {
|
||||
IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId("org.teavm.idea"));
|
||||
Set<File> visited = new HashSet<>();
|
||||
List<String> classPath = new ArrayList<>();
|
||||
findInHierarchy(plugin.getPath(), classPath, visited);
|
||||
return classPath;
|
||||
}
|
||||
|
||||
private static void findInHierarchy(File file, List<String> targetFiles, Set<File> visited) {
|
||||
if (!visited.add(file)) {
|
||||
return;
|
||||
}
|
||||
if (file.isFile() && PLUGIN_FILES.contains(file.getName())) {
|
||||
targetFiles.add(file.getAbsolutePath());
|
||||
} else if (file.getPath().endsWith(DAEMON_CLASS)) {
|
||||
for (int i = 0; i <= DAEMON_CLASS_DEPTH; ++i) {
|
||||
file = file.getParentFile();
|
||||
}
|
||||
targetFiles.add(file.getAbsolutePath());
|
||||
} else if (file.isDirectory()) {
|
||||
for (File childFile : file.listFiles()) {
|
||||
findInHierarchy(childFile, targetFiles, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.FileInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -57,8 +58,6 @@ import org.teavm.common.IntegerArray;
|
|||
import org.teavm.diagnostics.DefaultProblemTextConsumer;
|
||||
import org.teavm.diagnostics.Problem;
|
||||
import org.teavm.diagnostics.ProblemProvider;
|
||||
import org.teavm.idea.jps.model.TeaVMBuildResult;
|
||||
import org.teavm.idea.jps.model.TeaVMBuildStrategy;
|
||||
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
|
||||
import org.teavm.idea.jps.model.TeaVMProperty;
|
||||
import org.teavm.idea.jps.remote.TeaVMBuilderAssistant;
|
||||
|
@ -67,6 +66,9 @@ import org.teavm.model.CallLocation;
|
|||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.tooling.builder.BuildException;
|
||||
import org.teavm.tooling.builder.BuildResult;
|
||||
import org.teavm.tooling.builder.BuildStrategy;
|
||||
import org.teavm.vm.TeaVMPhase;
|
||||
import org.teavm.vm.TeaVMProgressFeedback;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
|
@ -79,10 +81,10 @@ class TeaVMBuild {
|
|||
private final TeaVMBuilderAssistant assistant;
|
||||
private final Map<String, File> sourceFileCache = new HashMap<>();
|
||||
private final Map<File, int[]> fileLineCache = new HashMap<>();
|
||||
private TeaVMBuildStrategy buildStrategy;
|
||||
private BuildStrategy buildStrategy;
|
||||
private BuildOutputConsumer outputConsumer;
|
||||
|
||||
TeaVMBuild(CompileContext context, TeaVMBuilderAssistant assistant, TeaVMBuildStrategy buildStrategy,
|
||||
TeaVMBuild(CompileContext context, TeaVMBuilderAssistant assistant, BuildStrategy buildStrategy,
|
||||
BuildOutputConsumer outputConsumer) {
|
||||
this.context = context;
|
||||
this.assistant = assistant;
|
||||
|
@ -90,7 +92,7 @@ class TeaVMBuild {
|
|||
this.outputConsumer = outputConsumer;
|
||||
}
|
||||
|
||||
boolean perform(JpsModule module, TeaVMBuildTarget target) throws IOException {
|
||||
boolean perform(JpsModule module, TeaVMBuildTarget target) throws IOException, BuildException {
|
||||
TeaVMStorageProvider storageProvider = new TeaVMStorageProvider(
|
||||
target.getConfiguration().getTargetType().name());
|
||||
storage = context.getProjectDescriptor().dataManager.getStorage(target, storageProvider);
|
||||
|
@ -128,25 +130,17 @@ class TeaVMBuild {
|
|||
}
|
||||
buildStrategy.setProperties(properties);
|
||||
|
||||
TeaVMBuildResult buildResult = buildStrategy.build();
|
||||
BuildResult buildResult = buildStrategy.build();
|
||||
|
||||
if (!buildResult.isErrorOccurred() && buildResult.getProblems().getSevereProblems().isEmpty()) {
|
||||
if (!buildResult.getProblems().getSevereProblems().isEmpty()) {
|
||||
updateStorage(buildResult);
|
||||
}
|
||||
|
||||
reportProblems(buildResult.getProblems(), buildResult.getCallGraph());
|
||||
|
||||
if (!buildResult.isErrorOccurred()) {
|
||||
for (String fileName : buildResult.getGeneratedFiles()) {
|
||||
outputConsumer.registerOutputFile(new File(fileName), Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
if (buildResult.getStackTrace() != null) {
|
||||
context.processMessage(new CompilerMessage("TeaVM", BuildMessage.Kind.ERROR,
|
||||
"Compiler crashed:\n" + buildResult.getStackTrace(), "",
|
||||
-1, -1, -1, -1, -1));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -390,7 +384,7 @@ class TeaVMBuild {
|
|||
|
||||
private int[] getLineOffsetsCacheMiss(File file) {
|
||||
IntegerArray lines = new IntegerArray(50);
|
||||
try (Reader reader = new InputStreamReader(new FileInputStream(file), "UTF-8")) {
|
||||
try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
|
||||
int offset = 0;
|
||||
lines.add(0);
|
||||
|
||||
|
@ -450,10 +444,9 @@ class TeaVMBuild {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void updateStorage(TeaVMBuildResult buildResult) {
|
||||
private void updateStorage(BuildResult buildResult) {
|
||||
Set<String> resources = Stream.concat(buildResult.getClasses().stream()
|
||||
.map(cls -> cls.replace('.', '/') + ".class"), buildResult.getUsedResources().stream())
|
||||
.sorted()
|
||||
.collect(toSet());
|
||||
List<TeaVMStorage.Entry> participatingFiles = resources.stream()
|
||||
.map(path -> {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.teavm.idea.jps;
|
||||
|
||||
import static org.teavm.idea.jps.remote.TeaVMBuilderAssistant.REMOTE_PORT;
|
||||
import java.io.IOException;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
|
@ -27,17 +26,19 @@ import org.jetbrains.jps.builders.BuildOutputConsumer;
|
|||
import org.jetbrains.jps.builders.BuildRootDescriptor;
|
||||
import org.jetbrains.jps.builders.DirtyFilesHolder;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.ProjectBuildException;
|
||||
import org.jetbrains.jps.incremental.TargetBuilder;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.teavm.idea.jps.model.TeaVMBuildStrategy;
|
||||
import org.teavm.idea.jps.remote.TeaVMBuilderAssistant;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
|
||||
import org.teavm.tooling.builder.BuildException;
|
||||
import org.teavm.tooling.builder.BuildStrategy;
|
||||
import org.teavm.tooling.builder.InProcessBuildStrategy;
|
||||
import org.teavm.tooling.builder.RemoteBuildStrategy;
|
||||
import org.teavm.tooling.daemon.RemoteBuildService;
|
||||
|
||||
public class TeaVMBuilder extends TargetBuilder<BuildRootDescriptor, TeaVMBuildTarget> {
|
||||
private TeaVMBuilderAssistant assistant;
|
||||
private TeaVMRemoteBuildService buildService;
|
||||
private RemoteBuildService buildService;
|
||||
|
||||
public TeaVMBuilder() {
|
||||
super(Collections.singletonList(TeaVMBuildTargetType.INSTANCE));
|
||||
|
@ -52,11 +53,11 @@ public class TeaVMBuilder extends TargetBuilder<BuildRootDescriptor, TeaVMBuildT
|
|||
}
|
||||
}
|
||||
|
||||
String daemonPortString = System.getProperty(TeaVMRemoteBuildService.REMOTE_PORT);
|
||||
String daemonPortString = System.getProperty(RemoteBuildService.REMOTE_PORT);
|
||||
if (daemonPortString != null) {
|
||||
try {
|
||||
Registry registry = LocateRegistry.getRegistry(Integer.parseInt(daemonPortString));
|
||||
buildService = (TeaVMRemoteBuildService) registry.lookup(TeaVMRemoteBuildService.ID);
|
||||
buildService = (RemoteBuildService) registry.lookup(RemoteBuildService.ID);
|
||||
} catch (NumberFormatException | RemoteException | NotBoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -66,19 +67,32 @@ public class TeaVMBuilder extends TargetBuilder<BuildRootDescriptor, TeaVMBuildT
|
|||
@Override
|
||||
public void build(@NotNull TeaVMBuildTarget target,
|
||||
@NotNull DirtyFilesHolder<BuildRootDescriptor, TeaVMBuildTarget> holder,
|
||||
@NotNull BuildOutputConsumer outputConsumer, @NotNull CompileContext context) throws ProjectBuildException,
|
||||
IOException {
|
||||
@NotNull BuildOutputConsumer outputConsumer, @NotNull CompileContext context) {
|
||||
if (assistant == null) {
|
||||
context.processMessage(new CompilerMessage("TeaVM", BuildMessage.Kind.WARNING,
|
||||
"No TeaVM builder assistant available. Diagnostic messages will be less informative"));
|
||||
}
|
||||
|
||||
TeaVMBuildStrategy buildStrategy = buildService != null
|
||||
try {
|
||||
BuildStrategy buildStrategy = buildService != null
|
||||
? new RemoteBuildStrategy(buildService)
|
||||
: new InProcessBuildStrategy(context);
|
||||
: createInProcessBuilder();
|
||||
TeaVMBuild build = new TeaVMBuild(context, assistant, buildStrategy, outputConsumer);
|
||||
|
||||
build.perform(target.getModule(), target);
|
||||
} catch (BuildException e) {
|
||||
context.processMessage(CompilerMessage.createInternalBuilderError("TeaVM", e.getCause()));
|
||||
} catch (Exception e) {
|
||||
context.processMessage(CompilerMessage.createInternalBuilderError("TeaVM", e));
|
||||
}
|
||||
}
|
||||
|
||||
private BuildStrategy createInProcessBuilder() {
|
||||
return new InProcessBuildStrategy((urls, innerClassLoader) -> {
|
||||
RenamingClassLoader loader = new RenamingClassLoader(urls, innerClassLoader);
|
||||
loader.rename("org/objectweb/asm/", "org/teavm/asm/");
|
||||
return loader;
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.io.InputStreamReader;
|
|||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.jetbrains.jps.incremental.storage.StorageOwner;
|
||||
|
@ -39,7 +40,7 @@ public class TeaVMStorage implements StorageOwner {
|
|||
this.file = file;
|
||||
if (file.exists()) {
|
||||
participatingFiles = new ArrayList<>();
|
||||
try (Reader innerReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
|
||||
try (Reader innerReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
BufferedReader reader = new BufferedReader(innerReader)) {
|
||||
while (true) {
|
||||
String line = reader.readLine();
|
||||
|
@ -82,7 +83,7 @@ public class TeaVMStorage implements StorageOwner {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void clean() throws IOException {
|
||||
public void clean() {
|
||||
file.delete();
|
||||
participatingFiles = null;
|
||||
}
|
||||
|
@ -95,7 +96,7 @@ public class TeaVMStorage implements StorageOwner {
|
|||
file.delete();
|
||||
}
|
||||
} else {
|
||||
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
|
||||
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
|
||||
BufferedWriter writer = new BufferedWriter(innerWriter)) {
|
||||
for (Entry participatingFile : participatingFiles) {
|
||||
writer.append(participatingFile.path + ":" + participatingFile.timestamp);
|
||||
|
|
|
@ -18,13 +18,17 @@ package org.teavm.idea;
|
|||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import java.io.IOException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.teavm.idea.daemon.TeaVMBuildDaemon;
|
||||
import org.teavm.idea.daemon.TeaVMDaemonInfo;
|
||||
import org.teavm.idea.jps.model.TeaVMJpsWorkspaceConfiguration;
|
||||
import org.teavm.idea.jps.util.DaemonUtil;
|
||||
import org.teavm.tooling.daemon.BuildDaemon;
|
||||
import org.teavm.tooling.daemon.DaemonInfo;
|
||||
import org.teavm.tooling.daemon.DaemonLog;
|
||||
|
||||
public class TeaVMDaemonComponent implements ApplicationComponent {
|
||||
private TeaVMDaemonInfo daemonInfo;
|
||||
private DaemonInfo daemonInfo;
|
||||
private boolean incremental;
|
||||
private int daemonMemory;
|
||||
|
||||
|
@ -64,7 +68,9 @@ public class TeaVMDaemonComponent implements ApplicationComponent {
|
|||
public void startDaemon() {
|
||||
if (daemonInfo == null) {
|
||||
try {
|
||||
daemonInfo = TeaVMBuildDaemon.start(incremental, daemonMemory);
|
||||
Log log = LogFactory.getLog(TeaVMDaemonComponent.class);
|
||||
daemonInfo = BuildDaemon.start(incremental, daemonMemory, new LogWrapper(log),
|
||||
DaemonUtil.detectClassPath().toArray(new String[0]));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -116,4 +122,27 @@ public class TeaVMDaemonComponent implements ApplicationComponent {
|
|||
public String getComponentName() {
|
||||
return "TeaVM daemon";
|
||||
}
|
||||
|
||||
static class LogWrapper implements DaemonLog {
|
||||
private Log log;
|
||||
|
||||
public LogWrapper(Log log) {
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String s) {
|
||||
log.error(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String s, Throwable throwable) {
|
||||
log.error(s, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String s) {
|
||||
log.info(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import com.intellij.compiler.server.BuildProcessParametersProvider;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
|
||||
import org.teavm.tooling.daemon.RemoteBuildService;
|
||||
|
||||
public class TeaVMJPSConfigurator extends BuildProcessParametersProvider {
|
||||
private TeaVMJPSRemoteService remoteService;
|
||||
|
@ -37,7 +37,7 @@ public class TeaVMJPSConfigurator extends BuildProcessParametersProvider {
|
|||
List<String> result = new ArrayList<>();
|
||||
result.add("-D" + REMOTE_PORT + "=" + remoteService.getPort());
|
||||
if (daemonComponent.isDaemonRunning()) {
|
||||
result.add("-D" + TeaVMRemoteBuildService.REMOTE_PORT + "=" + daemonComponent.getDaemonPort());
|
||||
result.add("-D" + RemoteBuildService.REMOTE_PORT + "=" + daemonComponent.getDaemonPort());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,7 @@ public class TeaVMJPSRemoteService extends UnicastRemoteObject implements Applic
|
|||
}
|
||||
|
||||
@Override
|
||||
public TeaVMElementLocation getMethodLocation(String className, String methodName, String methodDesc)
|
||||
throws RemoteException {
|
||||
public TeaVMElementLocation getMethodLocation(String className, String methodName, String methodDesc) {
|
||||
TeaVMElementLocation[] resultHolder = new TeaVMElementLocation[1];
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(() -> {
|
||||
|
|
|
@ -1,217 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 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.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.artifact.repository.MavenArtifactRepository;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.logging.Log;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.repository.RepositorySystem;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.tooling.BaseTeaVMTool;
|
||||
import org.teavm.tooling.sources.SourceFileProvider;
|
||||
|
||||
public abstract class AbstractTeaVMMojo extends AbstractMojo {
|
||||
@Component
|
||||
protected MavenProject project;
|
||||
|
||||
@Component
|
||||
protected RepositorySystem repositorySystem;
|
||||
|
||||
@Parameter(required = true, readonly = true, defaultValue = "${localRepository}")
|
||||
protected MavenArtifactRepository localRepository;
|
||||
|
||||
@Parameter(required = true, readonly = true, defaultValue = "${project.remoteArtifactRepositories}")
|
||||
protected List<MavenArtifactRepository> remoteRepositories;
|
||||
|
||||
@Parameter(readonly = true, defaultValue = "${plugin.artifacts}")
|
||||
protected List<Artifact> pluginArtifacts;
|
||||
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}")
|
||||
protected File classFiles;
|
||||
|
||||
@Parameter
|
||||
protected List<String> compileScopes;
|
||||
|
||||
@Parameter
|
||||
protected boolean minifying = true;
|
||||
|
||||
@Parameter
|
||||
protected Properties properties;
|
||||
|
||||
@Parameter
|
||||
protected boolean debugInformationGenerated;
|
||||
|
||||
@Parameter
|
||||
protected boolean sourceMapsGenerated;
|
||||
|
||||
@Parameter
|
||||
protected boolean sourceFilesCopied;
|
||||
|
||||
@Parameter
|
||||
protected boolean incremental;
|
||||
|
||||
@Parameter
|
||||
protected String[] transformers;
|
||||
|
||||
protected ClassLoader classLoader;
|
||||
|
||||
protected abstract File getTargetDirectory();
|
||||
|
||||
protected final List<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
|
||||
throws MojoExecutionException {
|
||||
List<ClassHolderTransformer> transformerInstances = new ArrayList<>();
|
||||
if (transformers == null) {
|
||||
return transformerInstances;
|
||||
}
|
||||
for (String transformerName : transformers) {
|
||||
Class<?> transformerRawType;
|
||||
try {
|
||||
transformerRawType = Class.forName(transformerName, true, classLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new MojoExecutionException("Transformer not found: " + transformerName, e);
|
||||
}
|
||||
if (!ClassHolderTransformer.class.isAssignableFrom(transformerRawType)) {
|
||||
throw new MojoExecutionException("Transformer " + transformerName + " is not subtype of "
|
||||
+ ClassHolderTransformer.class.getName());
|
||||
}
|
||||
Class<? extends ClassHolderTransformer> transformerType = transformerRawType.asSubclass(
|
||||
ClassHolderTransformer.class);
|
||||
Constructor<? extends ClassHolderTransformer> ctor;
|
||||
try {
|
||||
ctor = transformerType.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new MojoExecutionException("Transformer " + transformerName + " has no default constructor");
|
||||
}
|
||||
try {
|
||||
ClassHolderTransformer transformer = ctor.newInstance();
|
||||
transformerInstances.add(transformer);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new MojoExecutionException("Error instantiating transformer " + transformerName, e);
|
||||
}
|
||||
}
|
||||
return transformerInstances;
|
||||
}
|
||||
|
||||
protected void setupTool(BaseTeaVMTool tool) throws MojoExecutionException {
|
||||
tool.setLog(new MavenTeaVMToolLog(getLog()));
|
||||
try {
|
||||
ClassLoader classLoader = prepareClassLoader();
|
||||
tool.setClassLoader(classLoader);
|
||||
tool.setMinifying(minifying);
|
||||
tool.setTargetDirectory(getTargetDirectory());
|
||||
tool.getTransformers().addAll(instantiateTransformers(classLoader));
|
||||
if (sourceFilesCopied) {
|
||||
for (SourceFileProvider provider : getSourceFileProviders()) {
|
||||
tool.addSourceFileProvider(provider);
|
||||
}
|
||||
}
|
||||
if (properties != null) {
|
||||
tool.getProperties().putAll(properties);
|
||||
}
|
||||
tool.setIncremental(incremental);
|
||||
tool.setDebugInformationGenerated(debugInformationGenerated);
|
||||
tool.setSourceMapsFileGenerated(sourceMapsGenerated);
|
||||
tool.setSourceFilesCopied(sourceFilesCopied);
|
||||
} catch (RuntimeException e) {
|
||||
throw new MojoExecutionException("Unexpected error occured", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected final ClassLoader prepareClassLoader() throws MojoExecutionException {
|
||||
try {
|
||||
Log log = getLog();
|
||||
log.info("Preparing classpath for JavaScript generation");
|
||||
List<URL> urls = new ArrayList<>();
|
||||
StringBuilder classpath = new StringBuilder();
|
||||
for (Artifact artifact : project.getArtifacts()) {
|
||||
if (!filterByScope(artifact)) {
|
||||
continue;
|
||||
}
|
||||
File file = artifact.getFile();
|
||||
if (classpath.length() > 0) {
|
||||
classpath.append(':');
|
||||
}
|
||||
classpath.append(file.getPath());
|
||||
urls.add(file.toURI().toURL());
|
||||
}
|
||||
if (classpath.length() > 0) {
|
||||
classpath.append(':');
|
||||
}
|
||||
classpath.append(classFiles.getPath());
|
||||
urls.add(classFiles.toURI().toURL());
|
||||
for (File additionalEntry : getAdditionalClassPath()) {
|
||||
classpath.append(':').append(additionalEntry.getPath());
|
||||
urls.add(additionalEntry.toURI().toURL());
|
||||
}
|
||||
log.info("Using the following classpath for JavaScript generation: " + classpath);
|
||||
classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]),
|
||||
AbstractTeaVMMojo.class.getClassLoader());
|
||||
return classLoader;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new MojoExecutionException("Error gathering classpath information", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected List<File> getAdditionalClassPath() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected boolean filterByScope(Artifact artifact) {
|
||||
return compileScopes == null ? isSupportedScope(artifact.getScope())
|
||||
: compileScopes.contains(artifact.getScope());
|
||||
}
|
||||
|
||||
protected boolean isSupportedScope(String scope) {
|
||||
switch (scope) {
|
||||
case Artifact.SCOPE_COMPILE:
|
||||
case Artifact.SCOPE_PROVIDED:
|
||||
case Artifact.SCOPE_SYSTEM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected final List<SourceFileProvider> getSourceFileProviders() {
|
||||
MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup();
|
||||
lookup.setMavenProject(project);
|
||||
lookup.setRepositorySystem(repositorySystem);
|
||||
lookup.setLocalRepository(localRepository);
|
||||
lookup.setRemoteRepositories(remoteRepositories);
|
||||
lookup.setPluginDependencies(pluginArtifacts);
|
||||
List<SourceFileProvider> providers = lookup.resolve();
|
||||
addSourceProviders(providers);
|
||||
return providers;
|
||||
}
|
||||
|
||||
protected void addSourceProviders(@SuppressWarnings("unused") List<SourceFileProvider> providers) {
|
||||
}
|
||||
}
|
|
@ -26,9 +26,7 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
|
|||
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.repository.RepositorySystem;
|
||||
import org.teavm.tooling.sources.DirectorySourceFileProvider;
|
||||
import org.teavm.tooling.sources.JarSourceFileProvider;
|
||||
import org.teavm.tooling.sources.SourceFileProvider;
|
||||
import org.teavm.tooling.builder.BuildStrategy;
|
||||
|
||||
public class MavenSourceFileProviderLookup {
|
||||
private MavenProject mavenProject;
|
||||
|
@ -57,7 +55,7 @@ public class MavenSourceFileProviderLookup {
|
|||
this.pluginDependencies = pluginDependencies;
|
||||
}
|
||||
|
||||
public List<SourceFileProvider> resolve() {
|
||||
public void resolve(BuildStrategy builder) {
|
||||
List<Artifact> initialArtifacts = new ArrayList<>();
|
||||
initialArtifacts.addAll(mavenProject.getArtifacts());
|
||||
if (pluginDependencies != null) {
|
||||
|
@ -74,7 +72,6 @@ public class MavenSourceFileProviderLookup {
|
|||
}
|
||||
|
||||
artifacts.addAll(initialArtifacts);
|
||||
List<SourceFileProvider> providers = new ArrayList<>();
|
||||
for (Artifact artifact : artifacts) {
|
||||
ArtifactResolutionRequest request = new ArtifactResolutionRequest()
|
||||
.setLocalRepository(localRepository)
|
||||
|
@ -85,16 +82,15 @@ public class MavenSourceFileProviderLookup {
|
|||
if (resolvedArtifact.getFile() != null) {
|
||||
File file = resolvedArtifact.getFile();
|
||||
if (!file.isDirectory()) {
|
||||
providers.add(new JarSourceFileProvider(file));
|
||||
builder.addSourcesJar(file.getAbsolutePath());
|
||||
} else {
|
||||
providers.add(new DirectorySourceFileProvider(file));
|
||||
builder.addSourcesDirectory(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String sourceRoot : mavenProject.getCompileSourceRoots()) {
|
||||
providers.add(new DirectorySourceFileProvider(new File(sourceRoot)));
|
||||
}
|
||||
return providers;
|
||||
builder.addSourcesDirectory(new File(sourceRoot).getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,26 +16,88 @@
|
|||
package org.teavm.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.net.URLClassLoader;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.artifact.repository.MavenArtifactRepository;
|
||||
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
|
||||
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.logging.Log;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.repository.RepositorySystem;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||
import org.teavm.tooling.TeaVMProblemRenderer;
|
||||
import org.teavm.tooling.TeaVMTargetType;
|
||||
import org.teavm.tooling.TeaVMTool;
|
||||
import org.teavm.tooling.TeaVMToolException;
|
||||
import org.teavm.tooling.sources.DirectorySourceFileProvider;
|
||||
import org.teavm.tooling.sources.SourceFileProvider;
|
||||
import org.teavm.tooling.builder.BuildException;
|
||||
import org.teavm.tooling.builder.BuildResult;
|
||||
import org.teavm.tooling.builder.BuildStrategy;
|
||||
import org.teavm.tooling.builder.InProcessBuildStrategy;
|
||||
import org.teavm.tooling.builder.RemoteBuildStrategy;
|
||||
import org.teavm.tooling.daemon.BuildDaemon;
|
||||
import org.teavm.tooling.daemon.DaemonInfo;
|
||||
import org.teavm.tooling.daemon.DaemonLog;
|
||||
import org.teavm.tooling.daemon.RemoteBuildService;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
|
||||
@Mojo(name = "compile", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||
requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||
defaultPhase = LifecyclePhase.PROCESS_CLASSES)
|
||||
public class TeaVMCompileMojo extends AbstractTeaVMMojo {
|
||||
public class TeaVMCompileMojo extends AbstractMojo {
|
||||
@Component
|
||||
private MavenProject project;
|
||||
|
||||
@Component
|
||||
private RepositorySystem repositorySystem;
|
||||
|
||||
@Parameter(required = true, readonly = true, defaultValue = "${localRepository}")
|
||||
private MavenArtifactRepository localRepository;
|
||||
|
||||
@Parameter(required = true, readonly = true, defaultValue = "${project.remoteArtifactRepositories}")
|
||||
private List<MavenArtifactRepository> remoteRepositories;
|
||||
|
||||
@Parameter(readonly = true, defaultValue = "${plugin.artifacts}")
|
||||
private List<Artifact> pluginArtifacts;
|
||||
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}")
|
||||
private File classFiles;
|
||||
|
||||
@Parameter
|
||||
private List<String> compileScopes;
|
||||
|
||||
@Parameter
|
||||
private boolean minifying = true;
|
||||
|
||||
@Parameter
|
||||
private Properties properties;
|
||||
|
||||
@Parameter
|
||||
private boolean debugInformationGenerated;
|
||||
|
||||
@Parameter
|
||||
private boolean sourceMapsGenerated;
|
||||
|
||||
@Parameter
|
||||
private boolean sourceFilesCopied;
|
||||
|
||||
@Parameter
|
||||
private boolean incremental;
|
||||
|
||||
@Parameter
|
||||
private String[] transformers;
|
||||
|
||||
@Parameter(defaultValue = "${project.build.directory}/javascript")
|
||||
private File targetDirectory;
|
||||
|
||||
|
@ -61,48 +123,197 @@ public class TeaVMCompileMojo extends AbstractTeaVMMojo {
|
|||
private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
|
||||
|
||||
@Parameter(defaultValue = "${project.build.directory}/teavm-cache")
|
||||
protected File cacheDirectory;
|
||||
|
||||
private TeaVMTool tool = new TeaVMTool();
|
||||
private File cacheDirectory;
|
||||
|
||||
@Parameter
|
||||
private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0x1;
|
||||
|
||||
@Override
|
||||
protected File getTargetDirectory() {
|
||||
return targetDirectory;
|
||||
@Parameter(property = "teavm.outOfProcess", defaultValue = "false")
|
||||
private boolean outOfProcess;
|
||||
|
||||
@Parameter(property = "teavm.processMemory", defaultValue = "512")
|
||||
private int processMemory;
|
||||
|
||||
private void setupBuilder(BuildStrategy builder) throws MojoExecutionException {
|
||||
builder.setLog(new MavenTeaVMToolLog(getLog()));
|
||||
try {
|
||||
builder.setClassPathEntries(prepareClassPath());
|
||||
builder.setMinifying(minifying);
|
||||
builder.setTargetDirectory(targetDirectory.getAbsolutePath());
|
||||
if (transformers != null) {
|
||||
builder.setTransformers(transformers);
|
||||
}
|
||||
if (sourceFilesCopied) {
|
||||
getSourceFileProviders(builder);
|
||||
builder.addSourcesDirectory(sourceDirectory.getAbsolutePath());
|
||||
}
|
||||
if (properties != null) {
|
||||
builder.setProperties(properties);
|
||||
}
|
||||
builder.setIncremental(incremental);
|
||||
builder.setDebugInformationGenerated(debugInformationGenerated);
|
||||
builder.setSourceMapsFileGenerated(sourceMapsGenerated);
|
||||
builder.setSourceFilesCopied(sourceFilesCopied);
|
||||
} catch (RuntimeException e) {
|
||||
throw new MojoExecutionException("Unexpected error occurred", e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> prepareClassPath() {
|
||||
Log log = getLog();
|
||||
log.info("Preparing classpath for JavaScript generation");
|
||||
List<String> paths = new ArrayList<>();
|
||||
StringBuilder classpath = new StringBuilder();
|
||||
for (Artifact artifact : project.getArtifacts()) {
|
||||
if (!filterByScope(artifact)) {
|
||||
continue;
|
||||
}
|
||||
File file = artifact.getFile();
|
||||
if (classpath.length() > 0) {
|
||||
classpath.append(':');
|
||||
}
|
||||
classpath.append(file.getPath());
|
||||
paths.add(file.getAbsolutePath());
|
||||
}
|
||||
if (classpath.length() > 0) {
|
||||
classpath.append(':');
|
||||
}
|
||||
classpath.append(classFiles.getPath());
|
||||
paths.add(classFiles.getAbsolutePath());
|
||||
log.info("Using the following classpath for JavaScript generation: " + classpath);
|
||||
return paths;
|
||||
}
|
||||
|
||||
private boolean filterByScope(Artifact artifact) {
|
||||
return compileScopes == null ? isSupportedScope(artifact.getScope())
|
||||
: compileScopes.contains(artifact.getScope());
|
||||
}
|
||||
|
||||
protected boolean isSupportedScope(String scope) {
|
||||
switch (scope) {
|
||||
case Artifact.SCOPE_COMPILE:
|
||||
case Artifact.SCOPE_PROVIDED:
|
||||
case Artifact.SCOPE_SYSTEM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void getSourceFileProviders(BuildStrategy builder) {
|
||||
MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup();
|
||||
lookup.setMavenProject(project);
|
||||
lookup.setRepositorySystem(repositorySystem);
|
||||
lookup.setLocalRepository(localRepository);
|
||||
lookup.setRemoteRepositories(remoteRepositories);
|
||||
lookup.setPluginDependencies(pluginArtifacts);
|
||||
lookup.resolve(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException {
|
||||
Log log = getLog();
|
||||
setupTool(tool);
|
||||
tool.setLog(new MavenTeaVMToolLog(log));
|
||||
try {
|
||||
tool.setMainClass(mainClass);
|
||||
if (!targetFileName.isEmpty()) {
|
||||
tool.setTargetFileName(targetFileName);
|
||||
}
|
||||
tool.setOptimizationLevel(optimizationLevel);
|
||||
if (classesToPreserve != null) {
|
||||
tool.getClassesToPreserve().addAll(Arrays.asList(classesToPreserve));
|
||||
}
|
||||
tool.setCacheDirectory(cacheDirectory);
|
||||
tool.setTargetType(targetType);
|
||||
tool.setWasmVersion(wasmVersion);
|
||||
tool.generate();
|
||||
if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) {
|
||||
throw new MojoExecutionException("Build error");
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw new MojoExecutionException("Unexpected error occured", e);
|
||||
} catch (TeaVMToolException e) {
|
||||
throw new MojoExecutionException("IO error occured", e);
|
||||
if (outOfProcess) {
|
||||
executeInSeparateProcess();
|
||||
} else {
|
||||
executeWithBuilder(new InProcessBuildStrategy(URLClassLoader::new));
|
||||
}
|
||||
}
|
||||
|
||||
private void executeInSeparateProcess() throws MojoExecutionException {
|
||||
DaemonInfo daemon;
|
||||
try {
|
||||
daemon = BuildDaemon.start(false, processMemory, new DaemonLogImpl(), createDaemonClassPath());
|
||||
} catch (Throwable e) {
|
||||
throw new MojoExecutionException("Error starting TeaVM process", e);
|
||||
}
|
||||
|
||||
try {
|
||||
RemoteBuildService buildService;
|
||||
try {
|
||||
Registry registry = LocateRegistry.getRegistry(daemon.getPort());
|
||||
buildService = (RemoteBuildService) registry.lookup(RemoteBuildService.ID);
|
||||
} catch (RemoteException | NotBoundException e) {
|
||||
throw new MojoExecutionException("Error connecting TeaVM process", e);
|
||||
}
|
||||
|
||||
RemoteBuildStrategy builder = new RemoteBuildStrategy(buildService);
|
||||
executeWithBuilder(builder);
|
||||
} finally {
|
||||
daemon.getProcess().destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void executeWithBuilder(BuildStrategy builder) throws MojoExecutionException {
|
||||
builder.init();
|
||||
Log log = getLog();
|
||||
setupBuilder(builder);
|
||||
MavenTeaVMToolLog toolLog = new MavenTeaVMToolLog(log);
|
||||
builder.setLog(toolLog);
|
||||
try {
|
||||
builder.setMainClass(mainClass);
|
||||
if (!targetFileName.isEmpty()) {
|
||||
builder.setTargetFileName(targetFileName);
|
||||
}
|
||||
builder.setOptimizationLevel(optimizationLevel);
|
||||
if (classesToPreserve != null) {
|
||||
builder.setClassesToPreserve(classesToPreserve);
|
||||
}
|
||||
builder.setCacheDirectory(cacheDirectory.getAbsolutePath());
|
||||
builder.setTargetType(targetType);
|
||||
builder.setWasmVersion(wasmVersion);
|
||||
BuildResult result;
|
||||
result = builder.build();
|
||||
TeaVMProblemRenderer.describeProblems(result.getCallGraph(), result.getProblems(), toolLog);
|
||||
if (stopOnErrors && !result.getProblems().getSevereProblems().isEmpty()) {
|
||||
throw new MojoExecutionException("Build error");
|
||||
}
|
||||
} catch (BuildException e) {
|
||||
throw new MojoExecutionException("Unexpected error occurred", e.getCause());
|
||||
} catch (Exception e) {
|
||||
throw new MojoExecutionException("Unexpected error occurred", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] createDaemonClassPath() {
|
||||
Artifact toolArtifact = pluginArtifacts.stream()
|
||||
.filter(artifact -> artifact.getGroupId().equals("org.teavm")
|
||||
&& artifact.getArtifactId().equals("teavm-tooling"))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (toolArtifact == null) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
ArtifactResolutionResult resolutionResult = repositorySystem.resolve(new ArtifactResolutionRequest()
|
||||
.setLocalRepository(localRepository)
|
||||
.setRemoteRepositories(new ArrayList<>(remoteRepositories))
|
||||
.setResolveTransitively(true)
|
||||
.setResolveRoot(true)
|
||||
.setArtifact(toolArtifact));
|
||||
|
||||
if (!resolutionResult.isSuccess()) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
return resolutionResult.getArtifacts().stream()
|
||||
.map(artifact -> artifact.getFile().getAbsolutePath())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
class DaemonLogImpl implements DaemonLog {
|
||||
@Override
|
||||
protected void addSourceProviders(List<SourceFileProvider> providers) {
|
||||
providers.add(new DirectorySourceFileProvider(sourceDirectory));
|
||||
public void error(String message) {
|
||||
getLog().error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Throwable e) {
|
||||
getLog().error(message, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message) {
|
||||
getLog().info(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user