mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Add incremental build to JPS
This commit is contained in:
parent
87f7ee4b72
commit
36f2932caa
|
@ -251,6 +251,17 @@
|
|||
<artifactId>jps-builders</artifactId>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>log4j</id>
|
||||
<goals>
|
||||
<goal>install-file</goal>
|
||||
</goals>
|
||||
<phase>prepare-package</phase>
|
||||
<configuration>
|
||||
<file>dependencies/idea/lib/commons-logging-1.2.jar</file>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<localRepositoryPath>dependencies/maven</localRepositoryPath>
|
||||
|
|
|
@ -42,5 +42,7 @@ public interface TeaVMBuildStrategy {
|
|||
|
||||
void setProgressListener(TeaVMProgressListener progressListener);
|
||||
|
||||
void setIncremental(boolean incremental);
|
||||
|
||||
TeaVMBuildResult build();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.jetbrains.jps.model.ex.JpsElementBase;
|
|||
|
||||
public class TeaVMJpsWorkspaceConfiguration extends JpsElementBase<TeaVMJpsWorkspaceConfiguration> {
|
||||
private boolean daemonEnabled;
|
||||
private boolean incremental;
|
||||
|
||||
public boolean isDaemonEnabled() {
|
||||
return daemonEnabled;
|
||||
|
@ -29,6 +30,14 @@ public class TeaVMJpsWorkspaceConfiguration extends JpsElementBase<TeaVMJpsWorks
|
|||
this.daemonEnabled = daemonEnabled;
|
||||
}
|
||||
|
||||
public boolean isIncremental() {
|
||||
return incremental;
|
||||
}
|
||||
|
||||
public void setIncremental(boolean incremental) {
|
||||
this.incremental = incremental;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TeaVMJpsWorkspaceConfiguration createCopy() {
|
||||
|
@ -40,5 +49,6 @@ public class TeaVMJpsWorkspaceConfiguration extends JpsElementBase<TeaVMJpsWorks
|
|||
@Override
|
||||
public void applyChanges(@NotNull TeaVMJpsWorkspaceConfiguration configuration) {
|
||||
daemonEnabled = configuration.daemonEnabled;
|
||||
incremental = configuration.incremental;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,4 +30,5 @@ public class TeaVMRemoteBuildRequest implements Serializable {
|
|||
public boolean sourceMapsFileGenerated;
|
||||
public boolean debugInformationGenerated;
|
||||
public boolean sourceFilesCopied;
|
||||
public boolean incremental;
|
||||
}
|
||||
|
|
|
@ -110,6 +110,10 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
|
|||
this.progressListener = progressListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIncremental(boolean incremental) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TeaVMBuildResult build() {
|
||||
TeaVMTool tool = new TeaVMTool();
|
||||
|
|
|
@ -97,6 +97,11 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy {
|
|||
this.progressListener = progressListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIncremental(boolean incremental) {
|
||||
request.incremental = incremental;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TeaVMBuildResult build() {
|
||||
TeaVMRemoteBuildResponse response;
|
||||
|
|
|
@ -113,6 +113,7 @@ class TeaVMBuild {
|
|||
buildStrategy.setTargetType(config.getTargetType());
|
||||
buildStrategy.setTargetDirectory(config.getTargetDirectory());
|
||||
buildStrategy.setProgressListener(createProgressListener(context));
|
||||
buildStrategy.setIncremental(!isRebuild(target));
|
||||
TeaVMBuildResult buildResult = buildStrategy.build();
|
||||
|
||||
if (!buildResult.isErrorOccurred() && buildResult.getProblems().getSevereProblems().isEmpty()) {
|
||||
|
@ -399,9 +400,13 @@ class TeaVMBuild {
|
|||
return lines.getAll();
|
||||
}
|
||||
|
||||
private boolean isRebuild(TeaVMBuildTarget target) {
|
||||
return !context.getScope().isBuildIncrementally(target.getTargetType())
|
||||
|| context.getScope().isBuildForced(target);
|
||||
}
|
||||
|
||||
private boolean hasChanges(TeaVMBuildTarget target) {
|
||||
if (!context.getScope().isBuildIncrementally(target.getTargetType())
|
||||
|| context.getScope().isBuildForced(target)) {
|
||||
if (isRebuild(target)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,12 @@
|
|||
<version>${idea.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm.idea</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>${idea.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm.idea</groupId>
|
||||
<artifactId>teavm</artifactId>
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.teavm.idea.jps.model.TeaVMJpsWorkspaceConfiguration;
|
|||
|
||||
public class TeaVMDaemonComponent implements ApplicationComponent {
|
||||
private TeaVMDaemonInfo daemonInfo;
|
||||
private boolean incremental;
|
||||
|
||||
@Override
|
||||
public void initComponent() {
|
||||
|
@ -32,6 +33,7 @@ public class TeaVMDaemonComponent implements ApplicationComponent {
|
|||
TeaVMWorkspaceConfigurationStorage.class);
|
||||
if (configurationStorage != null) {
|
||||
TeaVMJpsWorkspaceConfiguration configuration = configurationStorage.getState();
|
||||
incremental = configuration.isIncremental();
|
||||
if (configuration.isDaemonEnabled()) {
|
||||
startDaemon();
|
||||
}
|
||||
|
@ -60,7 +62,7 @@ public class TeaVMDaemonComponent implements ApplicationComponent {
|
|||
public void startDaemon() {
|
||||
if (daemonInfo == null) {
|
||||
try {
|
||||
daemonInfo = TeaVMBuildDaemon.start();
|
||||
daemonInfo = TeaVMBuildDaemon.start(incremental);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -76,6 +78,21 @@ public class TeaVMDaemonComponent implements ApplicationComponent {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isIncremental() {
|
||||
return incremental;
|
||||
}
|
||||
|
||||
public void setIncremental(boolean incremental) {
|
||||
this.incremental = incremental;
|
||||
}
|
||||
|
||||
public void applyChanges() {
|
||||
TeaVMWorkspaceConfigurationStorage configurationStorage = getConfigurationStorage();
|
||||
TeaVMJpsWorkspaceConfiguration configuration = configurationStorage.getState();
|
||||
configuration.setIncremental(incremental);
|
||||
configurationStorage.loadState(configuration);
|
||||
}
|
||||
|
||||
private void updateConfiguration(boolean daemonEnabled) {
|
||||
TeaVMWorkspaceConfigurationStorage configurationStorage = getConfigurationStorage();
|
||||
TeaVMJpsWorkspaceConfiguration configuration = configurationStorage.getState();
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.io.InputStreamReader;
|
|||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.rmi.AlreadyBoundException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
|
@ -37,6 +38,9 @@ import java.util.List;
|
|||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
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;
|
||||
|
@ -58,8 +62,11 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
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 boolean incremental;
|
||||
private int port;
|
||||
private Registry registry;
|
||||
private File incrementalCache;
|
||||
|
||||
static {
|
||||
int depth = 0;
|
||||
|
@ -71,8 +78,9 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
DAEMON_CLASS_DEPTH = depth;
|
||||
}
|
||||
|
||||
TeaVMBuildDaemon() throws RemoteException {
|
||||
TeaVMBuildDaemon(boolean incremental) throws RemoteException {
|
||||
super();
|
||||
this.incremental = incremental;
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
port = random.nextInt(MAX_PORT - MIN_PORT) + MIN_PORT;
|
||||
|
@ -86,14 +94,36 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
} catch (RemoteException | AlreadyBoundException e) {
|
||||
throw new IllegalStateException("Could not bind remote build assistant service", e);
|
||||
}
|
||||
|
||||
setupIncrementalCache();
|
||||
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("Could not create RMI registry");
|
||||
}
|
||||
|
||||
private void setupIncrementalCache() {
|
||||
if (!incremental) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
incrementalCache = Files.createTempDirectory("teavm-cache").toFile();
|
||||
incrementalCache.deleteOnExit();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Could not setup incremental cache");
|
||||
e.printStackTrace(System.err);
|
||||
incremental = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws RemoteException {
|
||||
TeaVMBuildDaemon daemon = new TeaVMBuildDaemon();
|
||||
boolean incremental = Boolean.parseBoolean(System.getProperty(INCREMENTAL_PROPERTY, "false"));
|
||||
TeaVMBuildDaemon daemon = new TeaVMBuildDaemon(incremental);
|
||||
System.out.println(DAEMON_MESSAGE_PREFIX + daemon.port);
|
||||
if (daemon.incrementalCache != null) {
|
||||
System.out.println("Incremental cache set up in " + daemon.incrementalCache);
|
||||
}
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
|
@ -106,7 +136,22 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
@Override
|
||||
public TeaVMRemoteBuildResponse build(TeaVMRemoteBuildRequest request, TeaVMRemoteBuildCallback callback)
|
||||
throws RemoteException {
|
||||
System.out.println("Build started");
|
||||
|
||||
if (!request.incremental && incremental) {
|
||||
try {
|
||||
System.out.println("Dropping incremental cache");
|
||||
FileUtils.cleanDirectory(incrementalCache);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
TeaVMTool tool = new TeaVMTool();
|
||||
tool.setIncremental(incremental);
|
||||
if (tool.isIncremental()) {
|
||||
tool.setCacheDirectory(incrementalCache);
|
||||
}
|
||||
tool.setProgressListener(createProgressListener(callback));
|
||||
tool.setLog(new EmptyTeaVMToolLog());
|
||||
tool.setTargetType(request.targetType);
|
||||
|
@ -130,6 +175,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
boolean errorOccurred = false;
|
||||
try {
|
||||
tool.generate();
|
||||
System.out.println("Build complete");
|
||||
} catch (TeaVMToolException | RuntimeException | Error e) {
|
||||
e.printStackTrace(System.err);
|
||||
errorOccurred = true;
|
||||
|
@ -190,19 +236,24 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
};
|
||||
}
|
||||
|
||||
public static TeaVMDaemonInfo start() throws IOException {
|
||||
public static TeaVMDaemonInfo start(boolean incremental) throws IOException {
|
||||
String javaHome = System.getProperty("java.home");
|
||||
String javaCommand = javaHome + "/bin/java";
|
||||
String classPath = detectClassPath().stream().collect(Collectors.joining(File.pathSeparator));
|
||||
ProcessBuilder builder = new ProcessBuilder(javaCommand, "-cp", classPath, TeaVMBuildDaemon.class.getName());
|
||||
ProcessBuilder builder = new ProcessBuilder(javaCommand, "-cp", classPath,
|
||||
"-D" + INCREMENTAL_PROPERTY + "=" + incremental,
|
||||
TeaVMBuildDaemon.class.getName());
|
||||
Process process = builder.start();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
|
||||
String line = reader.readLine();
|
||||
|
||||
Log log = LogFactory.getLog(TeaVMBuildDaemon.class);
|
||||
|
||||
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
|
||||
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
|
||||
String line = stdoutReader.readLine();
|
||||
if (line == null || !line.startsWith(DAEMON_MESSAGE_PREFIX)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
|
||||
while (true) {
|
||||
line = reader.readLine();
|
||||
line = stderrReader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
|
@ -211,9 +262,41 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
|
|||
throw new IllegalStateException("Could not start daemon. Stderr: " + sb);
|
||||
}
|
||||
int port = Integer.parseInt(line.substring(DAEMON_MESSAGE_PREFIX.length()));
|
||||
|
||||
new Thread(new DaemonProcessOutputWatcher(log, stdoutReader, "stdout", false)).start();
|
||||
new Thread(new DaemonProcessOutputWatcher(log, stderrReader, "stderr", true)).start();
|
||||
|
||||
return new TeaVMDaemonInfo(port, process);
|
||||
}
|
||||
|
||||
static class DaemonProcessOutputWatcher implements Runnable {
|
||||
private Log log;
|
||||
private BufferedReader reader;
|
||||
private String name;
|
||||
private boolean isError;
|
||||
|
||||
public DaemonProcessOutputWatcher(Log log, BufferedReader reader, String name, boolean isError) {
|
||||
this.log = log;
|
||||
this.reader = reader;
|
||||
this.name = name;
|
||||
this.isError = isError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String line = reader.readLine();
|
||||
if (isError) {
|
||||
log.error("Build daemon [" + name + "]: " + line);
|
||||
} else {
|
||||
log.info("Build daemon [" + name + "]: " + line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading build daemon output", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> detectClassPath() {
|
||||
IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId("org.teavm.idea"));
|
||||
Set<File> visited = new HashSet<>();
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.teavm.idea.TeaVMDaemonComponent;
|
|||
public class TeaVMSettingsEditorTab implements SearchableConfigurable {
|
||||
private JPanel contentPane;
|
||||
private JCheckBox daemonCheckBox;
|
||||
private JCheckBox incrementalCheckBox;
|
||||
private TeaVMDaemonComponent daemonComponent;
|
||||
|
||||
public TeaVMSettingsEditorTab(TeaVMDaemonComponent daemonComponent) {
|
||||
|
@ -37,8 +38,11 @@ public class TeaVMSettingsEditorTab implements SearchableConfigurable {
|
|||
|
||||
contentPane = new JPanel();
|
||||
daemonCheckBox = new JCheckBox("use build daemon (can increase performance in most cases)");
|
||||
incrementalCheckBox = new JCheckBox("incremental build (only available with daemon)");
|
||||
contentPane.setLayout(new GridBagLayout());
|
||||
|
||||
daemonCheckBox.addActionListener(e -> incrementalCheckBox.setEnabled(daemonCheckBox.isSelected()));
|
||||
|
||||
GridBagConstraints labelConstraints = new GridBagConstraints();
|
||||
labelConstraints.gridwidth = GridBagConstraints.REMAINDER;
|
||||
labelConstraints.anchor = GridBagConstraints.BASELINE_LEADING;
|
||||
|
@ -48,6 +52,13 @@ public class TeaVMSettingsEditorTab implements SearchableConfigurable {
|
|||
labelConstraints.insets.right = 5;
|
||||
|
||||
contentPane.add(daemonCheckBox, labelConstraints);
|
||||
contentPane.add(incrementalCheckBox, labelConstraints);
|
||||
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.fill = GridBagConstraints.BOTH;
|
||||
constraints.weighty = 100;
|
||||
constraints.weightx = 1;
|
||||
contentPane.add(new JPanel(), constraints);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -76,20 +87,40 @@ public class TeaVMSettingsEditorTab implements SearchableConfigurable {
|
|||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return daemonCheckBox.isSelected() != daemonComponent.isDaemonRunning();
|
||||
return daemonCheckBox.isSelected() != daemonComponent.isDaemonRunning()
|
||||
|| incrementalCheckBox.isSelected() != daemonComponent.isIncremental();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
boolean shouldRestartDaemon = true;
|
||||
|
||||
if (incrementalCheckBox.isSelected() && !daemonComponent.isIncremental()) {
|
||||
shouldRestartDaemon = true;
|
||||
daemonComponent.setIncremental(incrementalCheckBox.isSelected());
|
||||
}
|
||||
|
||||
if (daemonCheckBox.isSelected()) {
|
||||
if (!daemonComponent.isDaemonRunning()) {
|
||||
daemonComponent.startDaemon();
|
||||
shouldRestartDaemon = false;
|
||||
}
|
||||
} else {
|
||||
daemonComponent.stopDaemon();
|
||||
shouldRestartDaemon = false;
|
||||
}
|
||||
|
||||
if (shouldRestartDaemon) {
|
||||
daemonComponent.stopDaemon();
|
||||
daemonComponent.startDaemon();
|
||||
}
|
||||
|
||||
daemonComponent.applyChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
daemonCheckBox.setSelected(daemonComponent.isDaemonRunning());
|
||||
incrementalCheckBox.setSelected(daemonComponent.isIncremental());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user