Установка аргументов компилятора в виде списка строк в новом языковом плагине

Я разрабатываю плагин для нового языка, и я пытался добавить поддержку компиляции в компилятор. Я использовал org.gradle.api.tasks.compile.CompileOptions класс в качестве отправной точки и реализовал свой собственный класс следующим образом:

class SvCompileOptions extends AbstractOptions {
    private List<String> compilerArgs = Lists.newArrayList();

    @Input
    public List<String> getCompilerArgs() {
        return compilerArgs;
    }

    public void setCompilerArgs(List<String> compilerArgs) {
        this.compilerArgs = compilerArgs;
    }
}

В моем файле build.gradle я попытался сделать следующее:

compileSv {
    options.compilerArgs += [ "-foo" ]
}

(compileSv - это задача со свойством options типа SvCompileOptions.)

Я получаю следующую ошибку:

A problem occurred evaluating project ':uvc2'.
> java.lang.AbstractMethodError (no error message)

Если я заменю строку на:

compileSv {
    options.compilerArgs.add("-foo")
}

тогда все работает нормально, но это не очень градлеско.

Может кто-нибудь указать, что я делаю не так?


Согласно предложению @tim_yates, я добавил функцию для добавления к compilerArgs:

class SvCompileOptions extends AbstractOptions {

    void compilerArgs(String... args) {
        this.compilerArgs.addAll(args as List)
    }
}

Согласно предложению @Opal, я создал простой пример:

// File 'build.gradle'

buildscript {
    dependencies {
        classpath 'com.google.guava:guava:16+'
    }
    repositories {
        mavenCentral()
    }
}

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;


class SvCompileOptions extends AbstractOptions {

    private List<String> compilerArgs = Lists.newArrayList();

    @Input
    public List<String> getCompilerArgs() {
        return compilerArgs;
    }

    public void setCompilerArgs(List<String> compilerArgs) {
        this.compilerArgs = compilerArgs;
    }

    void compilerArgs(String... args) {
        this.compilerArgs.addAll(args as List)
    }

}


class SvCompile extends DefaultTask {

    @TaskAction
    protected void compile() {
        println options.compilerArgs
    }

    @Nested
    SvCompileOptions options = new SvCompileOptions()

}


task compileSv(type: SvCompile)


compileSv {
    options.compilerArgs 'foo', 'bar'
}

Код добавляет аргументы в пустой список и печатает [foo, bar] как и ожидалось. Если мы попытаемся перезаписать аргументы, используя следующее:

compileSv {
    options.compilerArgs = ['one', 'two']
}

выводится сообщение об ошибке:

* What went wrong:
A problem occurred evaluating root project 'so_compile_options2'.
> SvCompileOptions.setProperty(Ljava/lang/String;Ljava/lang/Object;)V

Я не уверен, почему сообщение об ошибке отличается, когда классы встроены в build.gradle, но я бы предположил, что это то, что приводит к AbstractMethodError Я видел.

Как отметил @Opal, эта проблема вызвана тем, что внутри AbstractOptions учебный класс. Я попытался добавить следующие методы в класс параметров компиляции, но сообщение об ошибке все еще там:

class SvCompileOptions extends AbstractOptions {

    private static final ImmutableSet<String> EXCLUDE_FROM_ANT_PROPERTIES =
            ImmutableSet.of("compilerArgs");

    @Override
    protected boolean excludeFromAntProperties(String fieldName) {
        return EXCLUDE_FROM_ANT_PROPERTIES.contains(fieldName);
    }

    // ...
}

Кажется, что функция exclude вообще не вызывается, как будто я добавляю в нее фиктивный отпечаток, который никогда не будет выдан.

2 ответа

Решение

После ценной информации от @Opal, которая простирается от AbstractOptions является источником проблемы и найти проблему на странице Gradle Github, связанную с удалением AbstractOptions В целом, я думаю, что лучше всего просто не использовать базовый класс.

После интеграции предложения @tim_yates для метода 'append' я перейду к следующей реализации:

class SvCompileOptions {

    private List<String> compilerArgs = Lists.newArrayList();

    @Input
    public List<String> getCompilerArgs() {
        return compilerArgs;
    }

    // Overwrites
    public void setCompilerArgs(List<String> compilerArgs) {
        this.compilerArgs = compilerArgs;
    }

    // Appends
    void compilerArgs(String... args) {
        this.compilerArgs.addAll(args as List)
    }

}

Это позволяет пользователю добавлять аргументы:

compileSv {
    options.compilerArgs 'foo', 'bar'
}

и перезаписать их

compileSv {
    options.compilerArgs = ['one', 'two']
}

Это должно работать

options.compilerArgs << "-foo"

Идиоматический способ сделать это, если вы хотите добавить несколько значений (что вы, вероятно, будете делать в какой-то момент), это изменить свой класс на:

class SvCompileOptions extends AbstractOptions {
    @Input
    List<String> compilerArgs = Lists.newArrayList();

    def args(String... args) {
        this.compilerArgs += args.toList()
    }
}

Затем вы можете сделать:

compileSv {
    options.args "-foo", "-bar"
}
Другие вопросы по тегам