使用Gradle的多个启动脚本

时间:2014-01-20 18:46:36

标签: maven gradle

我有一个正在运行的Maven构建(如下所示),它准备了几个可执行文件作为两个独立的进程启动。

虽然这很好用,但如何使用Gradle完成?我看到Gradle提供了一个名为application的插件,但我很难找到一个很好的例子来说明如何告诉它在键入:gradle stage时,它应该创建2个可执行文件。

现在,当我调用stage时,它只在我的gradle脚本中定义的“root”主类上提供了一个可执行文件:

apply plugin: 'java'
apply plugin: 'application'

mainClassName = 'SpringLauncher'
applicationName = 'foo'
compileJava.options.encoding = 'UTF-8'
targetCompatibility = '1.7'
sourceCompatibility = '1.7'

task stage(dependsOn: ['clean', 'installApp', 'hello'])

Maven构建:

<build>
<plugins>
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
      <artifactId>appassembler-maven-plugin</artifactId>
      <version>1.1.1</version>
      <configuration> 
        <assembleDirectory>target</assembleDirectory> 
        <programs>
            <program>
                <mainClass>foo.bar.scheduler.SchedulerMain</mainClass>
                <name>scheduler</name>
            </program>
            <program>
                <mainClass>SpringLauncher</mainClass>
                <name>web</name>
            </program>
        </programs>
      </configuration>
      <executions>
          <execution>
              <phase>package</phase><goals><goal>assemble</goal></goals>
          </execution>            
      </executions>
  </plugin>
</plugins>

4 个答案:

答案 0 :(得分:11)

不幸的是,gradle应用程序插件不提供对多个可执行脚本的一流支持。

幸运的是,因为gradle脚本是常规的,所以你可以很容易地改变应用程序插件的功能。

documentation for the Application plugin显示startScripts任务的类型为CreateStartScripts,因此请尝试创建自己的同类型的第二个任务

task schedulerScripts(type: CreateStartScripts) {
    mainClassName = "foo.bar.scheduler.SchedulerMain"
    applicationName = "scheduler" 
    outputDir = new File(project.buildDir, 'scripts')
    classpath = jar.outputs.files + project.configurations.runtime
}

然后在您的发行版中包含该任务的输出

applicationDistribution.into("bin") {
            from(schedulerScripts)
            fileMode = 0755
}

答案 1 :(得分:2)

使用JavaExec

可能更好
task scheduler(type: JavaExec) {
   main = "foo.bar.scheduler.SchedulerMain"
   classpath = sourceSets.main.runtimeClasspath
}

task web(type: JavaExec) {
   main = "SpringLauncher"
   classpath = sourceSets.main.runtimeClasspath
}

然后您可以运行gradle scheduler web

答案 2 :(得分:1)

科特林 DSL

可重用功能

使用 Gradle Kotlin DSL 的 accepted answer 等价物,另外将创建多个脚本的通用逻辑抽象为一个可重用的函数:

fun createAdditionalScript(name: String, configureStartScripts: CreateStartScripts.() -> Unit) =
  tasks.register<CreateStartScripts>("startScripts$name") {
    configureStartScripts()
    applicationName = name
    outputDir = File(project.buildDir, "scripts")
    classpath = tasks.getByName("jar").outputs.files + configurations.runtimeClasspath.get()
  }.also {
    application.applicationDistribution.into("bin") {
      from(it)
      fileMode = 0b000_111_101_101
      duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    }
  }

现在你可以像这样使用它:

createAdditionalScript("foo") {
  mainClassName = "path.to.FooKt"
}

createAdditionalScript("bar") {
  mainClassName = "path.to.BarKt"
}

可重用性通过 buildSrc

函数 createAdditionalScript 最好放在 buildSrc 或插件中以保持主脚本干净,为此,它看起来像这样:

import org.gradle.api.Project
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.plugins.JavaApplication
import org.gradle.api.tasks.application.CreateStartScripts
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.register
import java.io.File

fun Project.additionalScript(name: String, configureStartScripts: CreateStartScripts.() -> Unit) =
  tasks.register<CreateStartScripts>("startScripts$name") {
    configureStartScripts()
    applicationName = name
    outputDir = File(buildDir, "scripts")
    classpath = tasks.getByName("jar").outputs.files + configurations.getByName("runtimeClasspath")
  }.also {
    configure<JavaApplication> {
      applicationDistribution.into("bin") {
        from(it)
        fileMode = 0b000_111_101_101
        duplicatesStrategy = DuplicatesStrategy.EXCLUDE
      }
    }
  }

请注意,fileMode 使用二进制权限表示来为用户、组和其他设置 r、w 和 x 位。 Kotlin DSL 不会像 Groovy 那样将 0755 之类的值解释为八进制。

答案 3 :(得分:0)

我发现的简单方法是添加一个新的CreateStartScripts任务并使它成为schedulerScripts的依赖项:

task schedulerScripts(type: CreateStartScripts) {
    mainClassName = 'foo.bar.scheduler.SchedulerMain'
    applicationName = 'scheduler'
    classpath = startScripts.classpath
    outputDir = startScripts.outputDir
}
startScripts.dependsOn schedulerScripts