gpt4 book ai didi

java - 使用 Gradle 向运行时镜像添加依赖项

转载 作者:搜寻专家 更新时间:2023-10-31 19:51:49 26 4
gpt4 key购买 nike

我不知道如何添加依赖项。我的模块需要 Log4j。我向模块信息添加了要求。我还添加了 gradle 依赖项。我可以运行项目,但无法创建自定义运行时镜像。

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'
}

当我启动任务 jlink 时,我得到:

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



我检查了构建中的 libs 目录,没有 log4j jar。如何告诉 gradle 将依赖项添加到 jlink 任务?

最佳答案

问题

这就是您的 jlink 中的内容任务:

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

什么意味着您正在添加以下依赖项:
  • libs : 基本上是你模块的 jar helloFX .这是 jar 的结果任务,仅包括项目的类和资源,但不包括其依赖项。
  • fx_jmods : 那是 JavaFX jmods 的路径。

  • 但是当你运行时,你会得到这个错误:

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



    该错误意味着 module-path对于 jlink命令不完整,它无法解析所有必需的依赖项。如上所述,我们只包括 module.jar 和 JavaFX (jmods) jar,但不包括 log4j.jar .

    所以我们需要找到一种方法将该 jar 添加到模块路径中。

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

    解决方案一

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

    最直接的解决方案是在本地 .gradle 存储库中找到 gradle 存储 logj4 jar 的位置。
    '--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"

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

    解决方案二

    更好的解决方案是添加一个任务来复制运行时依赖项,这些依赖项直接由 gradle 解析到 libs文件夹如:
    task libs(type: Copy) {
    into 'build/libs/'
    from configurations.runtime
    }

    然后从 jlink 调用此任务任务:
    task jlink(type: Exec) {
    dependsOn 'clean'
    dependsOn 'jar'
    dependsOn 'libs'
    ...
    }

    如果你运行 ./gradlew jlink并检查 libs文件夹,您应该会找到如下内容:
    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是你的运行平台。

    注意 libs文件夹现在包含模块路径所需的所有依赖项,并且 JavaFX-*-$platform jar 包含 native 库,因此在 module-path 选项中不再需要 jmods。这就足够了:
    '--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现在任务成功。

    解决方案3

    正如@madhead 评论所建议的那样,您可以为 jlink 使用另一个插件。任务:所谓 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'
    }
    }

    另请注意,该插件具有为其他平台创建图像的选项(请参阅 targetPlatform )。

    编辑 log4j

    正如评论中提到的, log4j依赖还不能很好地与模块一起使用。有一个 open issue在 Apache 问题跟踪器上:

    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.



    我已将此添加到我的主要类(class)中:
    LogManager.getLogger(MainApp.class).info("hellofx!");

    我添加了 log4j2.xml文件到 src/main/resources .

    运行 ./gradlew run ,作品:
    > Task :run
    18:24:26.362 [JavaFX Application Thread] INFO eu.sample.app.Main - hellofx!

    但是,从解决方案 2 运行 jlink 会创建自定义图像,我可以验证是否包含 xml 文件,但是从图像运行时我得到:
    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...

    如前所述,使用解决方案 3 中的插件运行 jlink 在 createMergedModule 处失败。任务:
     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 版以来已修复]

    选择

    此时,可能的替代方案是使用 Slf4j。有一个 sample从成功使用它的插件文档中列出。

    总而言之,这是必需的:

    Gradle 文件:
    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来自 herelogback.xml来自 here ,与您的主要类(class)。

    两者都在运行 ./gradlew运行或 ./gradlew jlink , 和 build/image/bin/HelloFX工作,并将消息记录到控制台。

    编辑 (2)

    之后 reporting badass-jlink-plugin 的问题跟踪器的问题,这个问题已经解决,从 2.1.19 版开始,它应该可以正常创建自定义图像。

    由于 log4j是multi-release jar,需要做一件事:
    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
    }

    查看完整的工作示例 here .

    关于java - 使用 Gradle 向运行时镜像添加依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53762491/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com