使用Gradle向运行时映像添加依赖项 [英] Add dependecies to runtime image with Gradle

查看:118
本文介绍了使用Gradle向运行时映像添加依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如何添加依赖项.我的模块需要Log4j.我在模块信息中添加了要求.我还添加了gradle依赖项.我可以运行项目,但不能创建自定义运行时映像.

I don't know how to add dependency. My module needs Log4j. I added requirement to module info. I added also to gradle dependencies. I can run project, but I can't create custom runtime image.

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
}

group 'eu.sample'
version '2.0'


repositories {
    mavenCentral()
}

javafx {
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

mainClassName = "$moduleName/eu.sample.app.Main"

def lin_java_home = hasProperty('org.gradle.java.home') ? getProperty('org.gradle.java.home') : System.getenv('JAVA_HOME')
def lin_fx_jmods = hasProperty('linux.fx.mods') ? getProperty('linux.fx.mods') : System.getenv('PATH_TO_FX_MODS_LIN')

def win_java_home = hasProperty('windows.java.home') ? getProperty('windows.java.home') : System.getenv('JAVA_HOME_WIN')
def win_fx_jmods = hasProperty('windows.fx.mods') ? getProperty('windows.fx.mods') : System.getenv('PATH_TO_FX_MODS_WIN')

dependencies {
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.1'
}

task jlink(type: Exec) {
    dependsOn 'clean'
    dependsOn 'jar'

    workingDir 'build'

    if (lin_java_home == null) {
        throw new RuntimeException("java_home is not defined.")
    }
    if (lin_fx_jmods == null) {
        throw new RuntimeException("fx_jmods is not defined.")
    }
    commandLine "${lin_java_home}/bin/jlink", '--module-path', "libs${File.pathSeparatorChar}${lin_fx_jmods}",
            '--add-modules', "${moduleName}", '--output', "${moduleName}", '--strip-debug',
            '--compress', '2', '--no-header-files', '--no-man-pages'
}

task jlinkWin(type: Exec) {
    dependsOn 'clean'
    dependsOn 'jar'


    workingDir 'build'

    if (win_java_home == null) {
        throw new RuntimeException("java_home is not defined.")
    }
    if (win_fx_jmods == null) {
        throw new RuntimeException("fx_jmods is not defined.")
    }
    commandLine "${lin_java_home}/bin/jlink", '--module-path', 
            "${win_java_home}/jmods${File.pathSeparatorChar}libs${File.pathSeparatorChar}${win_fx_jmods}",
            '--add-modules', "${moduleName}", '--output', "${moduleName}", '--strip-debug',
            '--compress', '2', '--no-header-files', '--no-man-pages'
}

当我执行任务链接时,我得到:

When I fire task jlink I get:

错误:未找到模块org.apache.logging.log4j,由 应用

Error: Module org.apache.logging.log4j not found, required by app

我检查了build中的libs目录,但没有log4j jar.如何告诉gradle为jlink任务添加依赖项?

I checked libs directory in build and there is not log4j jar. How to tell gradle to add dependencies to jlink task?

推荐答案

问题

这是您在jlink任务中所拥有的:

This is what you have in your jlink task:

'--module-path', "libs${File.pathSeparatorChar}${fx_jmods}"

这意味着您要添加以下项的依赖关系:

Whats means that you are adding the dependencies from:

  • libs:基本上是模块helloFX的jar.这是jar任务的结果,该任务仅包括项目的类和资源,但不包括其依赖项.

  • libs: basically the jar of your module helloFX. This is a result of the jar task, that only includes the classes and resources of your project, but not its dependencies.

fx_jmods:这是JavaFX jmods的路径.

fx_jmods: That is the path to the JavaFX jmods.

但是当您运行时,会出现此错误:

But when you run, you get this error:

错误:应用程序未找到模块org.apache.logging.log4j

Error: Module org.apache.logging.log4j not found, required by app

该错误表示jlink命令的module-path未完成,并且无法解析所有必需的依赖项.如上所述,我们仅包含module.jar和JavaFX(jmods)jar,但不包括log4j.jar.

The error means that the module-path for the jlink command is not complete, and it can't resolve all the required dependencies. As mentioned above, we are only including the module.jar and the JavaFX (jmods) jars, but not the log4j.jar.

因此,我们需要找到一种方法来将该jar添加到模块路径中.

So we need to find a way to add that jar to the module-path.

有几种可能的解决方案,可以在您的自定义映像中包含第三方依赖项.

There are a few possible solutions to include third party dependencies in your custom image.

解决方案1 ​​

我们必须修改jlink任务,以在我们的运行时配置中包括现有的依赖项.

We have to modify the jlink task, to include the existing dependencies in our runtime configuration.

最直接的解决方案是在本地.gradle存储库中找到gradle将logj4 jar存储在何处.

The most immediate solution is finding where the logj4 jars are stored by gradle, in the local .gradle repository.

'--module-path', "libs${File.pathSeparatorChar}${fx_jmods}: \
   /Users/<user>/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.11.1/268..a10/log4j-api-2.11.1.jar: \
   /Users/<user>/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-core/2.11.1/59..e4/log4j-core-2.11.1.jar"

虽然此解决方案有效,但它并不是最方便的,因为它取决于来自用户的本地路径.

While this solution works, it is not the most convenient, of course, as it depends on local paths from the user.

解决方案2

可以添加一个任务,将通过gradle直接解决的运行时依赖项复制到libs文件夹中,这是一个更好的解决方案,例如:

A better solution, can be done adding a task to copy the runtime dependencies, that are resolved directly by gradle, into the libs folder like:

task libs(type: Copy) {
    into 'build/libs/'
    from configurations.runtime
}

,然后从jlink任务调用此任务:

and then calling this task from the jlink task:

task jlink(type: Exec) {
    dependsOn 'clean'
    dependsOn 'jar'
    dependsOn 'libs'
    ...
}

如果运行./gradlew jlink并检查libs文件夹,则应该找到类似以下内容的文件:

If you run ./gradlew jlink and check the libs folder you should find something like this:

build/libs/hellofx.jar
build/libs/javafx-base-11.0.1.jar
build/libs/javafx-base-11.0.1-$platform.jar
build/libs/javafx-graphics-11.0.1.jar
build/libs/javafx-graphics-11.0.1-$platform.jar
build/libs/javafx-controls-11.0.1.jar
build/libs/javafx-controls-11.0.1-$platform.jar
build/libs/javafx-fxml-11.0.1.jar
build/libs/javafx-fxml-11.0.1-$platform.jar
build/libs/log4j-api-2.11.1.jar
build/libs/log4j-core-2.11.1.jar

其中$platform是您正在运行的平台.

where $platform is your running platform.

请注意,libs文件夹现在包含模块路径所需的 all 依赖项,并且JavaFX-*-$ platform jars 包含因此,在本机库中,不再需要在module-path选项中使用jmods.这样就足够了:

Notice that the libs folder now contains all the dependencies that are required for the module path, and also that the JavaFX-*-$platform jars contain the native libraries, therefore, the jmods are not needed anymore in the module-path option. This will be enough:

'--module-path', "libs"

因此您的命令行将是:

commandLine "${java_home}/bin/jlink", '--module-path', "libs",
        '--add-modules', "${moduleName}", '--output', "${moduleName}", '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'

您现在可以成功运行jlink任务.

You can run your jlink task now successfully.

解决方案3

如@madhead注释所建议,您可以将另一个插件用于jlink任务:所谓的

As suggested by @madhead comment, you can use another plugin for the jlink task: the so called badass-jlink-plugin.

将您的构建修改为:

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
    id 'org.beryx.jlink' version '2.1.8'
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.1'
}

javafx {
    modules = ['javafx.controls', 'javafx.fxml']
}

mainClassName = "${moduleName}/eu.sample.app.Main"

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'helloFX'
    }
}

还请注意,该插件具有为其他平台创建映像的选项(请参见

Note also that the plugin has an option to create image for other platforms (see targetPlatform).

编辑log4j

如注释中所述,log4j依赖项还不适用于模块.在Apache上有一个公开问题问题追踪器:

As mentioned in the comments, the log4j dependency doesn't play well with modules yet. There is an open issue at the Apache Issue tracker:

当前基于给定的自动模块,您不能在要使用jlink生成运行时映像的项目中使用log4j-core.

Currently based on the given automatic modules you can't use log4j-core in a project where you like to use jlink to produce a runtime image.

我已将其添加到我的主班:

I've added this to my main class:

LogManager.getLogger(MainApp.class).info("hellofx!");

,并且我已将log4j2.xml文件添加到src/main/resources.

and I've added the log4j2.xml file to src/main/resources.

运行./gradlew run,有效:

> Task :run
18:24:26.362 [JavaFX Application Thread] INFO  eu.sample.app.Main - hellofx!

但是,从解决方案2运行jlink会创建自定义图像,我可以验证是否包含了xml文件,但是从该图像运行时,我得到了:

But, running jlink from Solution 2, creates the custom image, I can verify that the xml file is included, but when running from the image I get:

build/hellofx/bin/java -m hellofx/eu.sample.app.Main
ERROR StatusLogger Log4j2 could not find a logging implementation. \
    Please add log4j-core to the classpath. Using SimpleLogger to log to the console...

并且如上所述,在createMergedModule任务中,使用解决方案3的插件运行jlink失败:

And as mentioned, running jlink with the plugin from Solution 3 fails at the createMergedModule task:

 error: package org.apache.logging.log4j.spi is not visible
   provides org.apache.logging.log4j.spi.Provider with org.apache.logging.log4j.core.impl.Log4jProvider;

[请参阅EDIT(2),此问题自版本2.1.9起已得到修复]

[See EDIT(2), this has been fixed since version 2.1.9]

替代

在这一点上,可能的替代方法是改用Slf4j.成功使用插件的文档中列出了一个示例.

At this point, a possible alternative could be use Slf4j instead. There is a sample listed from the plugin documentation that uses it successfully.

总之,这是必需的:

成绩文件:

dependencies {
    compile 'org.slf4j:slf4j-api:1.8.0-beta2'
    compile('ch.qos.logback:logback-classic:1.3.0-alpha4') {
        exclude module: "activation"
    }
}

模块信息:

requires org.slf4j;
requires ch.qos.logback.classic;
requires java.naming;

主类:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private static final Logger logger = LoggerFactory.getLogger(MainApp.class);

...
logger.info("hellofx!");

来自logging.properties"rel =" nofollow noreferrer">这里和logback.xml来自这里,与您的主要班级一起.

logging.properties from here and logback.xml from here, with your main class.

同时运行./gradlew run或./gradlew jlink,并且build/image/bin/HelloFX正常运行,并且消息记录到控制台.

Both running ./gradlew run or ./gradlew jlink, and build/image/bin/HelloFX work, and the message is logged to the console.

编辑(2)

报告问题后,将问题提交给badass-jlink-plugin问题追踪器,此问题已解决,并且从2.1.19版本开始,它应该可以很好地创建自定义图像.

After reporting the issue to the badass-jlink-plugin's issue tracker, this was solved, and since version 2.1.19 it should work fine creating a custom image.

由于log4j是多版本jar,因此需要做一件事:

Since log4j is multi-release jar, there is one thing required:

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
    id 'org.beryx.jlink' version '2.1.9'
}

...

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
       name = 'helloFX'
    }
    forceMerge('log4j-api')     // <---- this is required for Log4j
}

此处中查看完整的工作示例..

See a full working sample here.

这篇关于使用Gradle向运行时映像添加依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆