在gradle的应用程序插件生成的启动脚本中,如何将程序名称传递给应用程序?

时间:2018-01-17 17:44:03

标签: java gradle

执行gradle应用程序插件的installDist任务会创建一个包含包装脚本 build/install/my-application-name/bin my-application-name的目录my-application-name.bat。运行这些脚本中的任何一个都会运行应用程序,并且传递给这些脚本的参数将传递给底层应用程序。

在UNIX shell脚本中,您可以访问用于执行程序的名称$0。事实上,gradle生成的启动脚本的UNIX版本多次使用$0

如何配置gradle应用程序插件,以便这些脚本将$0(以及Windows上的Windows等效项)的值传递给底层应用程序,可能作为Java系统属性?

3 个答案:

答案 0 :(得分:5)

由于获取正在运行的脚本名称的参数在Linux(%0)和Windows(startScripts { unixStartScriptGenerator.template = resources.text.fromFile('unixStartScript.txt') windowsStartScriptGenerator.template = resources.text.fromFile('windowsStartScript.txt') } )中的引用方式不同,因此生成自定义脚本的最直接方法是单独使用相应start script generators的自定义模板:

unixStartScriptGenerator.template.asString()

默认模板很容易获得调用,例如# Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg,sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers+1 # Now, mark the region of unknown with zero markers[unknown==255] = 0 markers = cv2.watershed(im,markers) """Assign the markers a hue between 0 and 179""" hue_markers = np.uint8(179*np.float32(markers)/np.max(markers)) blank_channel = 255*np.ones((h, w), dtype=np.uint8) marker_img = cv2.merge([hue_markers, blank_channel, blank_channel]) marker_img = cv2.cvtColor(marker_img, cv2.COLOR_HSV2BGR) """create image black background, white boundaries for contour detections""" boundaries = np.zeros((h, w), dtype=np.uint8) boundaries[markers == -1] = 255

可以找到有关自定义启动脚本的文档here

答案 1 :(得分:1)

这是我最终做的,基于jihor的回答。我在这里发帖只是为了让其他任何感兴趣的人都能找到合适的答案:

startScripts {
    def gen = unixStartScriptGenerator
    gen.template = resources.text.fromString(
        gen.template.asString().replaceFirst('(?=\nDEFAULT_JVM_OPTS=.*?\n)') {
            '\nJAVA_OPTS="\\$JAVA_OPTS "\'"-Dprogname=\\$0"\''
        })

    // TODO: do something similar for windowsStartScriptGenerator
}

这使用replaceFirst代替replace,因此我们可以匹配模式。这有点不那么脆弱,也让我们使用前瞻,所以我们不必实际取代我们正在寻找的东西。 (顺便说一句,这是replaceFirst的常见变体,它采用了闭包。在这种情况下,这比需要替换字符串的版本要少得多。)

此外,而不是:

JAVA_OPTS="$JAVA_OPTS -Dprogname=$0"

我们实际上需要这样的东西:

JAVA_OPTS="$JAVA_OPTS "'"-Dprogname=$0"'

这是因为$0可能包含特殊字符(如空格),启动脚本会使用$JAVA_OPTS删除eval set --值中的一个引用级别。

(如果有人知道如何在Windows上进行此项工作,请随时更新此答案。)

答案 2 :(得分:1)

我采取了另一种方法。根据文档,可以追溯到Gradle 2.4一直到Gradle 4.8,我们应该能够在startScripts任务中设置以下属性:

  • applicationName
  • optsEnvironmentVar
  • exitEnvironmentVar
  • mainClassName
  • executableDir
  • defaultJvmOpts
  • appNameSystemProperty
  • appHomeRelativePath
  • classpath

不幸的是,对于以下属性(似乎从未公开过),情况并非如此:

  • appNameSystemProperty
  • appHomeRelativePath

如果appNameSystemProperty如文档所述被公开,那么我们应该能够简单地执行以下操作:

startScripts {
    applicationName = 'foo'
    appNameSystemProperty = 'appName'
}

这将导致在两个启动脚本中构造的Java命令中添加-DappName=foo

由于不是这种情况,所以我采用了以下方法,该方法比以前对该问题的解决方案更为冗长,但可能不那么灵活,因为它不依赖于调整现成的模板。而是导致记录的行为。

startScripts {
    mainClassName = '...'
    applicationName = 'foo'
    unixStartScriptGenerator =
        new CustomStartScriptGenerator(generator: unixStartScriptGenerator)
    windowsStartScriptGenerator =
        new CustomStartScriptGenerator(generator: windowsStartScriptGenerator)
}

class CustomStartScriptGenerator implements ScriptGenerator {
    @Delegate
    ScriptGenerator generator

    void generateScript(JavaAppStartScriptGenerationDetails details,
                        Writer destination) {
        details = new CustomDetails(details: details)
        this.generator.generateScript(details, destination)
    }

    static class CustomDetails implements JavaAppStartScriptGenerationDetails {
        @Delegate
        JavaAppStartScriptGenerationDetails details

        @Override
        String getAppNameSystemProperty() { 'appName' }
    }
}