IDEA: fix building multi-platform projects (JS, WebAssembly)

This commit is contained in:
Alexey Andreev 2016-11-15 23:07:25 +03:00
parent df95588d51
commit 8e2814f984
8 changed files with 114 additions and 47 deletions

View File

@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA JPS Debug" type="Remote" factoryName="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" value="javadebug" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="5005" />
<option name="LOCAL" value="false" />
</RunnerSettings>
<method />
</configuration>
</component>

View File

@ -0,0 +1,26 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="JPS repack" type="MavenRunConfiguration" factoryName="Maven">
<MavenSettings>
<option name="myGeneralSettings" />
<option name="myRunnerSettings" />
<option name="myRunnerParameters">
<MavenRunnerParameters>
<option name="profiles">
<set />
</option>
<option name="goals">
<list>
<option value="package" />
</list>
</option>
<option name="profilesMap">
<map />
</option>
<option name="resolveToWorkspace" value="false" />
<option name="workingDirPath" value="$PROJECT_DIR$/tools/idea/jps-common" />
</MavenRunnerParameters>
</option>
</MavenSettings>
<method />
</configuration>
</component>

View File

@ -16,6 +16,9 @@
package org.teavm.idea.jps.model; package org.teavm.idea.jps.model;
import com.intellij.util.xmlb.annotations.Transient; import com.intellij.util.xmlb.annotations.Transient;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.JpsElementChildRole; import org.jetbrains.jps.model.JpsElementChildRole;
import org.jetbrains.jps.model.ex.JpsElementBase; import org.jetbrains.jps.model.ex.JpsElementBase;
@ -24,8 +27,11 @@ import org.jetbrains.jps.model.module.JpsModule;
import org.teavm.tooling.TeaVMTargetType; import org.teavm.tooling.TeaVMTargetType;
public class TeaVMJpsConfiguration extends JpsElementBase<TeaVMJpsConfiguration> { public class TeaVMJpsConfiguration extends JpsElementBase<TeaVMJpsConfiguration> {
static final JpsElementChildRole<TeaVMJpsConfiguration> ROLE = JpsElementChildRoleBase.create( static final JpsElementChildRole<TeaVMJpsConfiguration> JS_ROLE = JpsElementChildRoleBase.create(
"TeaVM configuration"); "TeaVM configuration (JS)");
static final JpsElementChildRole<TeaVMJpsConfiguration> WEBASSEMBLY_ROLE = JpsElementChildRoleBase.create(
"TeaVM configuration (WebAssembly)");
@Transient @Transient
private TeaVMTargetType targetType; private TeaVMTargetType targetType;
@ -84,12 +90,15 @@ public class TeaVMJpsConfiguration extends JpsElementBase<TeaVMJpsConfiguration>
this.sourceFilesCopied = sourceFilesCopied; this.sourceFilesCopied = sourceFilesCopied;
} }
public static TeaVMJpsConfiguration get(JpsModule module) { public static List<TeaVMJpsConfiguration> getAll(JpsModule module) {
return module.getContainer().getChild(ROLE); List<TeaVMJpsConfiguration> configurations = new ArrayList<>();
} for (JpsElementChildRole<TeaVMJpsConfiguration> role : Arrays.asList(JS_ROLE, WEBASSEMBLY_ROLE)) {
TeaVMJpsConfiguration configuration = module.getContainer().getChild(role);
public void setTo(JpsModule module) { if (configuration != null) {
module.getContainer().setChild(ROLE, this); configurations.add(configuration);
}
}
return configurations;
} }
@NotNull @NotNull

View File

@ -20,7 +20,9 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import org.jdom.Element; import org.jdom.Element;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsElement; import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.JpsElementChildRole;
import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension; import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
import org.jetbrains.jps.model.serialization.facet.JpsFacetConfigurationSerializer; import org.jetbrains.jps.model.serialization.facet.JpsFacetConfigurationSerializer;
@ -33,35 +35,32 @@ public class TeaVMModelSerializerService extends JpsModelSerializerExtension {
return Arrays.asList(jsSerializer, wasmSerializer); return Arrays.asList(jsSerializer, wasmSerializer);
} }
JpsFacetConfigurationSerializer<TeaVMJpsConfiguration> jsSerializer = private TeaVMFacetSerializer jsSerializer = new TeaVMFacetSerializer(TeaVMJpsConfiguration.JS_ROLE,
new JpsFacetConfigurationSerializer<TeaVMJpsConfiguration>(TeaVMJpsConfiguration.ROLE, "teavm-js", "TeaVM (JS)", TeaVMTargetType.JAVASCRIPT);
"teavm-js", "TeaVM (JS)") {
private TeaVMFacetSerializer wasmSerializer = new TeaVMFacetSerializer(TeaVMJpsConfiguration.WEBASSEMBLY_ROLE,
"teavm-wasm", "TeaVM (WebAssembly)", TeaVMTargetType.WEBASSEMBLY);
private class TeaVMFacetSerializer
extends JpsFacetConfigurationSerializer<TeaVMJpsConfiguration> {
private TeaVMTargetType targetType;
public TeaVMFacetSerializer(JpsElementChildRole<TeaVMJpsConfiguration> role, String facetTypeId,
@Nullable String facetName, TeaVMTargetType targetType) {
super(role, facetTypeId, facetName);
this.targetType = targetType;
}
@Override @Override
protected TeaVMJpsConfiguration loadExtension(@NotNull Element element, String s, JpsElement jpsElement, protected TeaVMJpsConfiguration loadExtension(@NotNull Element element, String s, JpsElement jpsElement,
JpsModule jpsModule) { JpsModule jpsModule) {
TeaVMJpsConfiguration configuration = XmlSerializer.deserialize(element, TeaVMJpsConfiguration.class); TeaVMJpsConfiguration configuration = XmlSerializer.deserialize(element, TeaVMJpsConfiguration.class);
configuration.setTargetType(TeaVMTargetType.JAVASCRIPT); configuration.setTargetType(targetType);
return configuration; return configuration;
} }
@Override @Override
protected void saveExtension(TeaVMJpsConfiguration configuration, Element element, JpsModule jpsModule) { protected void saveExtension(TeaVMJpsConfiguration configuration, Element element, JpsModule jpsModule) {
} }
}; }
JpsFacetConfigurationSerializer<TeaVMJpsConfiguration> wasmSerializer =
new JpsFacetConfigurationSerializer<TeaVMJpsConfiguration>(TeaVMJpsConfiguration.ROLE,
"teavm-wasm", "TeaVM (WebAssembly)") {
@Override
protected TeaVMJpsConfiguration loadExtension(@NotNull Element element, String s, JpsElement jpsElement,
JpsModule jpsModule) {
TeaVMJpsConfiguration configuration = XmlSerializer.deserialize(element, TeaVMJpsConfiguration.class);
configuration.setTargetType(TeaVMTargetType.WEBASSEMBLY);
return configuration;
}
@Override
protected void saveExtension(TeaVMJpsConfiguration configuration, Element element, JpsModule jpsModule) {
}
};
} }

View File

@ -68,6 +68,7 @@ import org.teavm.model.MethodReference;
import org.teavm.model.TextLocation; import org.teavm.model.TextLocation;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.tooling.EmptyTeaVMToolLog; import org.teavm.tooling.EmptyTeaVMToolLog;
import org.teavm.tooling.TeaVMTargetType;
import org.teavm.tooling.TeaVMTool; import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException; import org.teavm.tooling.TeaVMToolException;
import org.teavm.tooling.sources.DirectorySourceFileProvider; import org.teavm.tooling.sources.DirectorySourceFileProvider;
@ -79,10 +80,11 @@ import org.teavm.vm.TeaVMProgressListener;
class TeaVMBuild { class TeaVMBuild {
private final CompileContext context; private final CompileContext context;
private final TeaVMStorageProvider storageProvider = new TeaVMStorageProvider(); private final TeaVMStorageProvider jsStorageProvider = new TeaVMStorageProvider("js");
private final TeaVMStorageProvider wasmStorageProvider = new TeaVMStorageProvider("wasm");
private final List<String> classPathEntries = new ArrayList<>(); private final List<String> classPathEntries = new ArrayList<>();
private List<String> directoryClassPathEntries; private List<String> directoryClassPathEntries;
private TeaVMStorage storage; private Map<TeaVMTargetType, TeaVMStorage> storages = new HashMap<>();
private final TeaVMBuilderAssistant assistant; private final TeaVMBuilderAssistant assistant;
private final Map<String, File> sourceFileCache = new HashMap<>(); private final Map<String, File> sourceFileCache = new HashMap<>();
private final Map<File, int[]> fileLineCache = new HashMap<>(); private final Map<File, int[]> fileLineCache = new HashMap<>();
@ -94,9 +96,23 @@ class TeaVMBuild {
} }
boolean perform(JpsModule module, ModuleBuildTarget target) throws IOException { boolean perform(JpsModule module, ModuleBuildTarget target) throws IOException {
storage = context.getProjectDescriptor().dataManager.getStorage(target, storageProvider); storages.put(TeaVMTargetType.JAVASCRIPT, context.getProjectDescriptor().dataManager.getStorage(
target, jsStorageProvider));
storages.put(TeaVMTargetType.WEBASSEMBLY, context.getProjectDescriptor().dataManager.getStorage(
target, wasmStorageProvider));
TeaVMJpsConfiguration config = TeaVMJpsConfiguration.get(module); boolean doneSomething = false;
for (TeaVMJpsConfiguration config : TeaVMJpsConfiguration.getAll(module)) {
if (performForSubsystem(module, target, config)) {
doneSomething = true;
}
}
return doneSomething;
}
private boolean performForSubsystem(JpsModule module, ModuleBuildTarget target, TeaVMJpsConfiguration config)
throws IOException {
if (config == null) { if (config == null) {
return false; return false;
} }
@ -106,7 +122,7 @@ class TeaVMBuild {
directoryClassPathEntries = classPathEntries.stream().filter(name -> new File(name).isDirectory()) directoryClassPathEntries = classPathEntries.stream().filter(name -> new File(name).isDirectory())
.collect(toList()); .collect(toList());
if (!hasChanges(target)) { if (!hasChanges(target, config.getTargetType())) {
return false; return false;
} }
@ -137,7 +153,7 @@ class TeaVMBuild {
} }
if (!errorOccurred && tool.getProblemProvider().getSevereProblems().isEmpty()) { if (!errorOccurred && tool.getProblemProvider().getSevereProblems().isEmpty()) {
updateStorage(tool); updateStorage(tool, config.getTargetType());
} }
CallGraph callGraph = tool.getDependencyInfo().getCallGraph(); CallGraph callGraph = tool.getDependencyInfo().getCallGraph();
@ -377,12 +393,13 @@ class TeaVMBuild {
return lines.getAll(); return lines.getAll();
} }
private boolean hasChanges(ModuleBuildTarget target) { private boolean hasChanges(ModuleBuildTarget target, TeaVMTargetType targetType) {
if (!context.getScope().isBuildIncrementally(target.getTargetType()) if (!context.getScope().isBuildIncrementally(target.getTargetType())
|| context.getScope().isBuildForced(target)) { || context.getScope().isBuildForced(target)) {
return true; return true;
} }
List<TeaVMStorage.Entry> filesToWatch = storage.getParticipatingFiles();
List<TeaVMStorage.Entry> filesToWatch = storages.get(targetType).getParticipatingFiles();
if (filesToWatch == null) { if (filesToWatch == null) {
return true; return true;
} }
@ -396,7 +413,7 @@ class TeaVMBuild {
return false; return false;
} }
private void updateStorage(TeaVMTool tool) { private void updateStorage(TeaVMTool tool, TeaVMTargetType targetType) {
Set<String> resources = Stream.concat(tool.getClasses().stream().map(cls -> cls.replace('.', '/') + ".class"), Set<String> resources = Stream.concat(tool.getClasses().stream().map(cls -> cls.replace('.', '/') + ".class"),
tool.getUsedResources().stream()) tool.getUsedResources().stream())
.sorted() .sorted()
@ -408,7 +425,8 @@ class TeaVMBuild {
}) })
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(toList()); .collect(toList());
storage.setParticipatingFiles(participatingFiles);
storages.get(targetType).setParticipatingFiles(participatingFiles);
} }
private Long getTimestamp(String path) { private Long getTimestamp(String path) {

View File

@ -74,7 +74,6 @@ public class TeaVMBuilder extends ModuleLevelBuilder {
return doneSomething ? ExitCode.OK : ExitCode.NOTHING_DONE; return doneSomething ? ExitCode.OK : ExitCode.NOTHING_DONE;
} }
@NotNull @NotNull
@Override @Override
public String getPresentableName() { public String getPresentableName() {

View File

@ -34,8 +34,8 @@ public class TeaVMStorage implements StorageOwner {
private List<Entry> participatingFiles; private List<Entry> participatingFiles;
private boolean dirty; private boolean dirty;
TeaVMStorage(File file) throws IOException { TeaVMStorage(File file, String suffix) throws IOException {
file = new File(file, "teavm.storage"); file = new File(file, "teavm-" + suffix + ".storage");
this.file = file; this.file = file;
if (file.exists()) { if (file.exists()) {
participatingFiles = new ArrayList<>(); participatingFiles = new ArrayList<>();
@ -106,10 +106,6 @@ public class TeaVMStorage implements StorageOwner {
} }
} }
public boolean causesBuild(String file) {
return participatingFiles == null || participatingFiles.contains(file);
}
public static class Entry { public static class Entry {
public final String path; public final String path;
public final long timestamp; public final long timestamp;

View File

@ -21,9 +21,15 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.storage.StorageProvider; import org.jetbrains.jps.builders.storage.StorageProvider;
public class TeaVMStorageProvider extends StorageProvider<TeaVMStorage> { public class TeaVMStorageProvider extends StorageProvider<TeaVMStorage> {
private String suffix;
public TeaVMStorageProvider(String suffix) {
this.suffix = suffix;
}
@NotNull @NotNull
@Override @Override
public TeaVMStorage createStorage(File file) throws IOException { public TeaVMStorage createStorage(File file) throws IOException {
return new TeaVMStorage(file); return new TeaVMStorage(file, suffix);
} }
} }