All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.vyarus.gradle.plugin.teavm.task.TeavmCompileTask Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
package ru.vyarus.gradle.plugin.teavm.task;

import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.Directory;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Console;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.workers.WorkQueue;
import org.gradle.workers.WorkerExecutor;
import org.teavm.backend.wasm.render.WasmBinaryVersion;
import org.teavm.tooling.TeaVMTargetType;
import org.teavm.vm.TeaVMOptimizationLevel;

import javax.inject.Inject;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * TeaVM compile task.
 *
 * @author Vyacheslav Rusakov
 * @since 06.01.2023
 */
@SuppressWarnings({"PMD.ExcessiveImports", "checkstyle:ClassFanOutComplexity"})
public abstract class TeavmCompileTask extends DefaultTask {

    @Inject
    protected abstract WorkerExecutor getWorkerExecutor();

    /**
     * @return true to show teavm compilation debug information
     */
    @Console
    public abstract Property getDebug();

    /**
     * @return directories with compiled classes and jar files (dependencies)
     */
    @InputFiles
    public abstract SetProperty getClassPath();

    /**
     * @return collection of dependent jar files
     */
    @Classpath
    public abstract ConfigurableFileCollection getDependencies();

    /**
     * @return directories with sources and source jar files
     */
    @InputFiles
    @Optional
    public abstract SetProperty getSources();

    /**
     * @return collection of source jars
     */
    @InputFiles
    @Optional
    public abstract ConfigurableFileCollection getSourceDependencies();

    /**
     * @return target compilation directory
     */
    @OutputDirectory
    public abstract DirectoryProperty getTargetDir();

    /**
     * @return teavm cache directory
     */
    @Internal
    public abstract DirectoryProperty getCacheDir();

    /**
     * @return main class name (entry point)
     */
    @Input
    public abstract Property getMainClass();

    /**
     * @return entry static method name (main by default)
     */
    @Input
    @Optional
    public abstract Property getEntryPointName();

    /**
     * @return target file name (by default classes.js or classes.wasm)
     */
    @Input
    @Optional
    public abstract Property getTargetFileName();

    /**
     * @return compilation target
     */
    @Input
    public abstract Property getTargetType();

    /**
     * @return wasm version (if wasm target used)
     */
    @Input
    public abstract Property getWasmVersion();

    /**
     * @return true to stop build on compilation errors
     */
    @Input
    public abstract Property getStopOnErrors();

    /**
     * @return true to minimize js output
     */
    @Input
    public abstract Property getObfuscated();

    /**
     * @return true for strict compilation
     */
    @Input
    public abstract Property getStrict();

    /**
     * @return true to copy source files into target directory (for source maps)
     */
    @Input
    public abstract Property getSourceFilesCopied();

    /**
     * @return true to enable incremental compilation
     */
    @Input
    public abstract Property getIncremental();

    /**
     * @return true to create debug info file (required for debug server)
     */
    @Input
    public abstract Property getDebugInformationGenerated();

    /**
     * @return true to generate source maps (for js)
     */
    @Input
    public abstract Property getSourceMapsGenerated();

    /**
     * @return true for short file name (C only)
     */
    @Input
    public abstract Property getShortFileNames();

    /**
     * @return true for long jmp (C only)
     */
    @Input
    public abstract Property getLongjmpSupported();

    /**
     * @return true for heap dump (C only)
     */
    @Input
    public abstract Property getHeapDump();

    /**
     * ONLY for development because it affects optimization level (set to SIMPLE).
     *
     * @return true for fast dependency analysis
     */
    @Input
    public abstract Property getFastDependencyAnalysis();

    /**
     * @return true to remove assertions during compilation
     */
    @Input
    public abstract Property getAssertionsRemoved();

    /**
     * @return max top level names (JS target only)
     */
    @Input
    public abstract Property getMaxTopLevelNames();

    /**
     * @return min heap size (WASM and C targets)
     */
    @Input
    public abstract Property getMinHeapSize();

    /**
     * @return max heap size (WASM and C targets)
     */
    @Input
    public abstract Property getMaxHeapSize();

    /**
     * @return optimization level (SIMPLE - minimal, ADVANCED - prod. FULL - for WASM)
     */
    @Input
    public abstract Property getOptimizationLevel();

    /**
     * @return list of transformer classes (transforming ClassHolders)
     */
    @Input
    @Optional
    public abstract ListProperty getTransformers();

    /**
     * @return properties for teavm plugins
     */
    @Input
    @Optional
    public abstract MapProperty getProperties();

    /**
     * @return classes to preserve
     */
    @Input
    @Optional
    public abstract ListProperty getClassesToPreserve();

    @TaskAction
    public void compile() {
        // teavm configuration used for worker classpath
        final WorkQueue workQueue = getWorkerExecutor().classLoaderIsolation(workerSpec -> {
            final Configuration teavmConf = getProject().getConfigurations().getByName("teavm");
            workerSpec.getClasspath().from(teavmConf);
        });

        // file indicating compilation error
        final File resultFile = getProject().getLayout()
                .getBuildDirectory().file(getName() + ".error").get().getAsFile();
        if (resultFile.exists()) {
            FileUtils.deleteQuietly(resultFile);
        }

        runCompilation(workQueue, resultFile);

        if (getStopOnErrors().get() && resultFile.exists()) {
            String errors = null;
            try {
                errors = Files.readString(resultFile.toPath());
                // shift
                errors = Arrays.stream(errors.split("\n")).map(s -> "\t" + s).collect(Collectors.joining("\n"));
            } catch (IOException ignored) {
                // ignore
            }
            FileUtils.deleteQuietly(resultFile);
            throw new GradleException("Teavm compilation failed" + (errors == null ? "" : (":\n\n" + errors + "\n")));
        } else if (resultFile.exists()) {
            // stop on error disabled
            FileUtils.deleteQuietly(resultFile);
        }
    }

    @SuppressWarnings("checkstyle:ExecutableStatementCount")
    private void runCompilation(final WorkQueue workQueue, final File resultFile) {
        workQueue.submit(CompileWorker.class, parameters -> {
            parameters.getDebug().set(getDebug());

            final List classpath = new ArrayList<>();
            classpath.addAll(getClassPath().get().stream()
                    .map(s -> s.getAsFile().getAbsolutePath()).collect(Collectors.toList()));
            classpath.addAll(getDependencies().getFiles().stream()
                    .map(File::getAbsolutePath).collect(Collectors.toList()));

            parameters.getClassPathEntries().set(classpath);
            parameters.getSourceDirectories().set(getSources());
            parameters.getSourceJars().set(getSourceDependencies().getFiles());
            parameters.getTargetDirectory().set(getTargetDir());
            parameters.getCacheDirectory().set(getCacheDir());

            parameters.getMainClass().set(getMainClass());
            parameters.getEntryPointName().set(getEntryPointName());
            parameters.getTargetFileName().set(getTargetFileName());
            parameters.getTargetType().set(getTargetType());
            parameters.getWasmVersion().set(getWasmVersion());

            parameters.getObfuscated().set(getObfuscated());
            parameters.getStrict().set(getStrict());
            parameters.getSourceFilesCopied().set(getSourceFilesCopied());
            parameters.getIncremental().set(getIncremental());
            parameters.getDebugInformationGenerated().set(getDebugInformationGenerated());
            parameters.getSourceMapsFileGenerated().set(getSourceMapsGenerated());
            parameters.getShortFileNames().set(getShortFileNames());
            parameters.getLongjmpSupported().set(getLongjmpSupported());
            parameters.getHeapDump().set(getHeapDump());
            parameters.getFastDependencyAnalysis().set(getFastDependencyAnalysis());
            parameters.getAssertionsRemoved().set(getAssertionsRemoved());

            parameters.getMaxTopLevelNames().set(getMaxTopLevelNames());
            parameters.getMinHeapSize().set(getMinHeapSize());
            parameters.getMaxHeapSize().set(getMaxHeapSize());
            parameters.getOptimizationLevel().set(getOptimizationLevel());
            parameters.getTransformers().set(getTransformers());
            parameters.getProperties().set(getProperties());
            parameters.getClassesToPreserve().set(getClassesToPreserve());

            parameters.getErrorFile().set(resultFile);
        });

        // waiting for compilation finish to fail task if errors occur
        workQueue.await();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy