wasm gc: add Gradle properties to copy runtime and write disassembly

This commit is contained in:
Alexey Andreev 2024-09-19 19:48:37 +02:00
parent 9fa88a15da
commit 64d6b1e570
6 changed files with 143 additions and 2 deletions

View File

@ -108,7 +108,9 @@ class TeaVMExtensionImpl extends TeaVMBaseExtensionImpl implements TeaVMExtensio
wasmGC.getAddedToWebApp().convention(property("wasm-gc.addedToWebApp") wasmGC.getAddedToWebApp().convention(property("wasm-gc.addedToWebApp")
.map(Boolean::parseBoolean).orElse(false)); .map(Boolean::parseBoolean).orElse(false));
wasmGC.getStrict().convention(property("wasm-gc.strict").map(Boolean::parseBoolean).orElse(true)); wasmGC.getStrict().convention(property("wasm-gc.strict").map(Boolean::parseBoolean).orElse(true));
wasmGC.getCopyRuntime().convention(property("wasm-gc.copyRuntime").map(Boolean::parseBoolean).orElse(true));
wasmGC.getObfuscated().convention(property("wasm-gc.obfuscated").map(Boolean::parseBoolean).orElse(true)); wasmGC.getObfuscated().convention(property("wasm-gc.obfuscated").map(Boolean::parseBoolean).orElse(true));
wasmGC.getDisassembly().convention(property("wasm-gc.disassembly").map(Boolean::parseBoolean).orElse(false));
} }
private void setupWasiDefaults() { private void setupWasiDefaults() {

View File

@ -37,6 +37,8 @@ import org.gradle.api.tasks.bundling.War;
import org.teavm.gradle.api.TeaVMConfiguration; import org.teavm.gradle.api.TeaVMConfiguration;
import org.teavm.gradle.api.TeaVMExtension; import org.teavm.gradle.api.TeaVMExtension;
import org.teavm.gradle.config.ArtifactCoordinates; import org.teavm.gradle.config.ArtifactCoordinates;
import org.teavm.gradle.tasks.CopyWasmGCRuntimeTask;
import org.teavm.gradle.tasks.DisasmWebAssemblyTask;
import org.teavm.gradle.tasks.GenerateCTask; import org.teavm.gradle.tasks.GenerateCTask;
import org.teavm.gradle.tasks.GenerateJavaScriptTask; import org.teavm.gradle.tasks.GenerateJavaScriptTask;
import org.teavm.gradle.tasks.GenerateWasiTask; import org.teavm.gradle.tasks.GenerateWasiTask;
@ -55,6 +57,8 @@ public class TeaVMPlugin implements Plugin<Project> {
public static final String WASM_TASK_NAME = "generateWasm"; public static final String WASM_TASK_NAME = "generateWasm";
public static final String WASI_TASK_NAME = "generateWasi"; public static final String WASI_TASK_NAME = "generateWasi";
public static final String WASM_GC_TASK_NAME = "generateWasmGC"; public static final String WASM_GC_TASK_NAME = "generateWasmGC";
public static final String WASM_GC_COPY_RUNTIME_TASK_NAME = "copyWasmGCRuntime";
public static final String WASM_GC_DISASSEMBLY_TASK_NAME = "disasmWasmGC";
public static final String C_TASK_NAME = "generateC"; public static final String C_TASK_NAME = "generateC";
public static final String CONFIGURATION_NAME = "teavm"; public static final String CONFIGURATION_NAME = "teavm";
public static final String CLASSPATH_CONFIGURATION_NAME = "teavmClasspath"; public static final String CLASSPATH_CONFIGURATION_NAME = "teavmClasspath";
@ -222,6 +226,31 @@ public class TeaVMPlugin implements Plugin<Project> {
task.getObfuscated().convention(wasmGC.getObfuscated()); task.getObfuscated().convention(wasmGC.getObfuscated());
task.getStrict().convention(wasmGC.getStrict()); task.getStrict().convention(wasmGC.getStrict());
}); });
project.getTasks().create(WASM_GC_COPY_RUNTIME_TASK_NAME, CopyWasmGCRuntimeTask.class, task -> {
task.setGroup(TASK_GROUP);
task.onlyIf(t -> extension.getWasmGC().getCopyRuntime().getOrElse(false));
var fileName = extension.getWasmGC().getTargetFileName().map(x -> x + "-runtime.js");
task.getOutputFile().convention(extension.getWasmGC().getOutputDir()
.flatMap(d -> d.dir(extension.getWasmGC().getRelativePathInOutputDir()))
.flatMap(d -> d.file(fileName)));
});
project.getTasks().create(WASM_GC_DISASSEMBLY_TASK_NAME, DisasmWebAssemblyTask.class, task -> {
task.setGroup(TASK_GROUP);
var genTask = (GenerateWasmGCTask) project.getTasks().getByName(WASM_GC_TASK_NAME);
task.dependsOn(genTask);
task.onlyIf(t -> extension.getWasmGC().getDisassembly().getOrElse(false));
task.getHtml().set(true);
task.getInputFile().convention(project.getLayout().dir(genTask.getOutputDir())
.flatMap(x -> x.file(genTask.getTargetFileName())));
var fileName = extension.getWasmGC().getTargetFileName().map(x -> {
if (x.endsWith(".wasm")) {
x = x.substring(0, x.length() - 5);
}
return x + ".wast.html";
});
task.getOutputFile().convention(project.getLayout().dir(genTask.getOutputDir())
.flatMap(d -> d.file(fileName)));
});
} }
private void registerCTask(Project project, Configuration configuration) { private void registerCTask(Project project, Configuration configuration) {
@ -272,6 +301,8 @@ public class TeaVMPlugin implements Plugin<Project> {
} }
if (wasmGCAddedToWebApp) { if (wasmGCAddedToWebApp) {
task.dependsOn(project.getTasks().named(WASM_GC_TASK_NAME)); task.dependsOn(project.getTasks().named(WASM_GC_TASK_NAME));
task.dependsOn(project.getTasks().named(WASM_GC_COPY_RUNTIME_TASK_NAME));
task.dependsOn(project.getTasks().named(WASM_GC_DISASSEMBLY_TASK_NAME));
var outDir = extension.getWasmGC().getOutputDir(); var outDir = extension.getWasmGC().getOutputDir();
var relPath = extension.getWasmGC().getRelativePathInOutputDir(); var relPath = extension.getWasmGC().getRelativePathInOutputDir();
task.with(project.copySpec(spec -> { task.with(project.copySpec(spec -> {

View File

@ -22,5 +22,9 @@ public interface TeaVMWasmGCConfiguration extends TeaVMCommonConfiguration, TeaV
Property<Boolean> getStrict(); Property<Boolean> getStrict();
Property<Boolean> getCopyRuntime();
Property<Boolean> getDisassembly();
Property<String> getTargetFileName(); Property<String> getTargetFileName();
} }

View File

@ -0,0 +1,39 @@
/*
* Copyright 2024 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.gradle.tasks;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
public abstract class CopyWasmGCRuntimeTask extends DefaultTask {
@OutputFile
public abstract RegularFileProperty getOutputFile();
@TaskAction
public void copyRuntime() throws IOException {
var resourceName = "org/teavm/backend/wasm/wasm-gc-runtime.js";
var classLoader = CopyWasmGCRuntimeTask.class.getClassLoader();
var output = getOutputFile().get().getAsFile();
try (var input = classLoader.getResourceAsStream(resourceName)) {
Files.copy(input, output.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2024 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.gradle.tasks;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.teavm.backend.wasm.disasm.Disassembler;
import org.teavm.backend.wasm.disasm.DisassemblyHTMLWriter;
import org.teavm.backend.wasm.disasm.DisassemblyTextWriter;
public abstract class DisasmWebAssemblyTask extends DefaultTask {
public DisasmWebAssemblyTask() {
getHtml().convention(false);
}
@InputFile
public abstract RegularFileProperty getInputFile();
@OutputFile
public abstract RegularFileProperty getOutputFile();
@Input
public abstract Property<Boolean> getHtml();
@TaskAction
public void disassemble() throws IOException {
var file = getInputFile().get().getAsFile();
var bytes = Files.readAllBytes(file.toPath());
var output = new FileOutputStream(getOutputFile().get().getAsFile());
var writer = new PrintWriter(output);
var html = getHtml().get();
var disassemblyWriter = html
? new DisassemblyHTMLWriter(writer)
: new DisassemblyTextWriter(writer);
disassemblyWriter.setWithAddress(true);
if (html) {
disassemblyWriter.write("<html><body><pre>").eol();
}
var disassembler = new Disassembler(disassemblyWriter);
disassembler.disassemble(bytes);
if (html) {
disassemblyWriter.write("</pre></body></html>").eol();
}
}
}

View File

@ -21,8 +21,6 @@ import org.teavm.tooling.TeaVMTargetType;
import org.teavm.tooling.builder.BuildStrategy; import org.teavm.tooling.builder.BuildStrategy;
public abstract class GenerateWasmGCTask extends TeaVMTask { public abstract class GenerateWasmGCTask extends TeaVMTask {
private static final int MB = 1024 * 1024;
public GenerateWasmGCTask() { public GenerateWasmGCTask() {
getStrict().convention(true); getStrict().convention(true);
getObfuscated().convention(true); getObfuscated().convention(true);