将编译器args设置为新语言插件中的字符串列表

时间:2018-03-13 09:47:42

标签: gradle groovy gradle-plugin

我正在为一种新语言开发一个插件,我试图在编译器中添加对编译选项的支持。我已经使用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是一个具有SvCompileOptions类型的options属性的任务。)

我收到以下错误:

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 个答案:

答案 0 :(得分:1)

这应该有效

D4B6 .START (2018-03-15 11:57:13) phpCAS-1.3.5+ ****************** [CAS.php:468]
D4B6 .=> phpCAS::client('2.0', 'XX.com', 8443, '/cas') [portal.php:10]
D4B6 .|    => CAS_Client::__construct('2.0', false, 'XX.com', 8443, '/cas', true) [CAS.php:360]
D4B6 .|    |    Starting a new session okutpm09o0akdi2bisd1q9ivg5 [Client.php:932]
D4B6 .|    |    Session is not authenticated [Client.php:938]
D4B6 .|    <= ''
D4B6 .<= ''
D4B6 .=> phpCAS::setNoCasServerValidation() [portal.php:13]
D4B6 .|    You have configured no validation of the legitimacy of the cas server. This is not recommended for production use. [CAS.php:1644]
D4B6 .<= ''
D4B6 .=> phpCAS::forceAuthentication() [portal.php:16]
D4B6 .|    => CAS_Client::forceAuthentication() [CAS.php:1098]
D4B6 .|    |    => CAS_Client::isAuthenticated() [Client.php:1280]
D4B6 .|    |    |    => CAS_Client::_wasPreviouslyAuthenticated() [Client.php:1393]
D4B6 .|    |    |    |    no user found [Client.php:1635]
D4B6 .|    |    |    <= false
D4B6 .|    |    |    no ticket found [Client.php:1494]
D4B6 .|    |    <= false
D4B6 .|    |    => CAS_Client::redirectToCas(false) [Client.php:1289]
D4B6 .|    |    |    => CAS_Client::getServerLoginURL(false, false) [Client.php:1656]
D4B6 .|    |    |    |    => CAS_Client::getURL() [Client.php:342]
D4B6 .|    |    |    |    |    Final URI: https://www.XX.com/newlogin/v1/portal.php [Client.php:3549]
D4B6 .|    |    |    |    <= 'https://www.XX.com/newlogin/v1/portal.php'
D4B6 .|    |    |    <= 'https://XX.com:8443/cas/login?service=https%3A%2F%2Fwww.XX.com%2Fnewlogin%2Fv1%2Fportal.php'
D4B6 .|    |    |    Redirect to : https://XX.com:8443/cas/login?service=https%3A%2F%2Fwww.XX.com%2Fnewlogin%2Fv1%2Fportal.php [Client.php:1663]
D4B6 .|    |    |    exit()
D4B6 .|    |    |    -
D4B6 .|    |    -
D4B6 .|    -
B117 .START (2018-03-15 11:57:15) phpCAS-1.3.5+ ****************** [CAS.php:468]
B117 .=> phpCAS::client('2.0', 'XX.com', 8443, '/cas') [portal.php:10]
B117 .|    => CAS_Client::__construct('2.0', false, 'XX.com', 8443, '/cas', true) [CAS.php:360]
B117 .|    |    Starting a new session okutpm09o0akdi2bisd1q9ivg5 [Client.php:932]
B117 .|    |    Session is not authenticated [Client.php:938]
B117 .|    |    Ticket 'ST-43-bcpN1lrL0uxok07f9Xf4-cas' found [Client.php:1020]
B117 .|    <= ''
B117 .<= ''
B117 .=> phpCAS::setNoCasServerValidation() [portal.php:13]
B117 .|    You have configured no validation of the legitimacy of the cas server. This is not recommended for production use. [CAS.php:1644]
B117 .<= ''
B117 .=> phpCAS::forceAuthentication() [portal.php:16]
B117 .|    => CAS_Client::forceAuthentication() [CAS.php:1098]
B117 .|    |    => CAS_Client::isAuthenticated() [Client.php:1280]
B117 .|    |    |    => CAS_Client::_wasPreviouslyAuthenticated() [Client.php:1393]
B117 .|    |    |    |    no user found [Client.php:1635]
B117 .|    |    |    <= false
B117 .|    |    |    CAS 2.0 ticket `ST-43-bcpN1lrL0uxok07f9Xf4-cas' is present [Client.php:1447]
B117 .|    |    |    => CAS_Client::validateCAS20('', NULL, NULL, false) [Client.php:1450]
B117 .|    |    |    |     [Client.php:3170]
B117 .|    |    |    |    => CAS_Client::getServerServiceValidateURL() [Client.php:3177]
B117 .|    |    |    |    |    => CAS_Client::getURL() [Client.php:453]
B117 .|    |    |    |    |    |    Final URI: https://www.XX.com/newlogin/v1/portal.php [Client.php:3549]
B117 .|    |    |    |    |    <= 'https://www.XX.com/newlogin/v1/portal.php'
B117 .|    |    |    |    <= 'https://XX.com:8443/cas/serviceValidate?service=https%3A%2F%2Fwww.XX.com%2Fnewlogin%2Fv1%2Fportal.php'
B117 .|    |    |    |    => CAS_Client::_readURL('https://XX.com:8443/cas/serviceValidate?service=https%3A%2F%2Fwww.XX.com%2Fnewlogin%2Fv1%2Fportal.php&ticket=ST-43-bcpN1lrL0uxok07f9Xf4-cas', NULL, NULL, NULL) [Client.php:3192]
B117 .|    |    |    |    |    => CAS_Request_CurlRequest::sendRequest() [AbstractRequest.php:242]
B117 .|    |    |    |    |    |    curl_exec() failed [CurlRequest.php:77]
B117 .|    |    |    |    |    <= false
B117 .|    |    |    |    <= false
B117 .|    |    |    |    could not open URL 'https://XX.com:8443/cas/serviceValidate?service=https%3A%2F%2Fwww.XX.com%2Fnewlogin%2Fv1%2Fportal.php&ticket=ST-43-bcpN1lrL0uxok07f9Xf4-cas' to validate (CURL error #7: Failed to connect to XX.com port 8443: Connection refused) [Client.php:3195]
B117 .|    |    |    |    => CAS_AuthenticationException::__construct(CAS_Client, 'Ticket not validated', 'https://XX.com:8443/cas/serviceValidate?service=https%3A%2F%2Fwww.XX.com%2Fnewlogin%2Fv1%2Fportal.php&ticket=ST-43-bcpN1lrL0uxok07f9Xf4-cas', true) [Client.php:3199]
B117 .|    |    |    |    |    => CAS_Client::getURL() [AuthenticationException.php:77]
B117 .|    |    |    |    |    <= 'https://www.XX.com/newlogin/v1/portal.php'
B117 .|    |    |    |    |    CAS URL: https://XX.com:8443/cas/serviceValidate?service=https%3A%2F%2Fwww.XX.com%2Fnewlogin%2Fv1%2Fportal.php&ticket=ST-43-bcpN1lrL0uxok07f9Xf4-cas [AuthenticationException.php:80]
B117 .|    |    |    |    |    Authentication failure: Ticket not validated [AuthenticationException.php:81]
B117 .|    |    |    |    |    Reason: no response from the CAS server [AuthenticationException.php:83]
B117 .|    |    |    |    |    exit()
B117 .|    |    |    |    |    -
B117 .|    |    |    |    -
B117 .|    |    |    -
B117 .|    |    -
B117 .|    -

如果您想要添加多个值(您可能会在某些时候执行),这样做的惯用方法是将您的类更改为:

options.compilerArgs << "-foo"

然后,你可以这样做:

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

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

答案 1 :(得分:1)

在@Opal的宝贵见解之后,从AbstractOptions扩展是问题的根源并在与removing the AbstractOptions class altogether相关的Gradle Github页面上发现问题,我认为最好的办法是根本就不要使用基类。

在整合@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']
}