Maven javafx:jlink。如何指定使用的模块路径?

Maven javafx:jlink. How to specifiy the module-path used?

我目前正在开发一个模块化的 JavaFX 应用程序,我正在使用 maven compile/deploy 它。

我的应用程序的一个依赖项是 JBibTex,它没有 module-info 文件,因此它被用作自动模块。为了让我的 javafx:jlink 工作(因为 javafx:jlink 不能在自动模块上工作),我必须将 JBibTex 转换为显式模块。为此,我使用了 Maven 的 ModiTect 插件。

我使用 ModiTect 为 JBibTex 库生成 module-info 文件,并将其添加到 JBibTex 的 jar 文件中(为此我使用了 moditect:add-module-infos)。

现在的问题是 javafx:jlink 使用位于我的“.m2”文件夹中的 JBibTex.jar 文件(maven 会自动下载所有项目的依赖项)。位于我的 .m2 文件夹中的 JBibTex.jar 文件不是我添加模块信息文件的文件。

所以我仍然得到错误:

Error: automatic module cannot be used with jlink: jbibtex

我通过使用 ModiTect 生成的显式 JBibtex 模块由我的 ModiTect 插件配置自动放入 target/modules

如何让 javafx:jlink 使用包含 module-info.class 文件的 target/modules/JBibTex.jar 文件而不是我的 .m2 文件夹的 JBibTex.jar?

这是我的 pom.xml 以防万一:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>xxx</groupId>
    <artifactId>BRM</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>BRM</name>
    <url>http://maven.apache.org</url>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>15</maven.compiler.source>
        <maven.compiler.target>15</maven.compiler.target>
        
        <mainClass>xxx.App</mainClass>
        <moduleName>xxx.brm</moduleName>
        
        <javafx.version>17.0.1</javafx.version>
        <javafx.maven.plugin.version>0.0.8</javafx.maven.plugin.version>
    </properties>
    

    <dependencies>
        <!-- javafx dependencies -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
          <version>${javafx.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
          <version>${javafx.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.jbibtex/jbibtex -->
        <dependency>
            <groupId>org.jbibtex</groupId>
            <artifactId>jbibtex</artifactId>
            <version>1.0.17</version>
        </dependency>
    </dependencies>

    <build>
         <resources>
            <resource>
                <directory>configs</directory>
            </resource>
        </resources>
        
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
            </plugin>
            
            <plugin>
                <groupId>org.moditect</groupId>
                <artifactId>moditect-maven-plugin</artifactId>
            </plugin>
        </plugins>
        
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>15</source>
                        <target>15</target>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.openjfx</groupId>
                    <artifactId>javafx-maven-plugin</artifactId>
                    <version>${javafx.maven.plugin.version}</version>
                    <configuration>
                            <mainClass>${mainClass}</mainClass>
                            <launcher>launcher</launcher>
                            <jlinkImageName>BRM</jlinkImageName>
                    </configuration>
                </plugin>
                
                <plugin>
                    <groupId>org.moditect</groupId>
                    <artifactId>moditect-maven-plugin</artifactId>
                    <version>1.0.0.RC2</version>
                    <executions>
                        <execution>
                            <id>add-module-infos</id>
                            <phase>generate-resources</phase>
                            <goals>
                                <goal>add-module-info</goal>
                            </goals>
                            <configuration>
                                <overwriteExistingFiles>true</overwriteExistingFiles>
                                <outputDirectory>${project.build.directory}/modules</outputDirectory>
                                <modules>
                                    <module>
                                        <artifact>
                                            <groupId>org.jbibtex</groupId>
                                            <artifactId>jbibtex</artifactId>
                                            <version>1.0.17</version>
                                        </artifact>
                                        <moduleInfoSource>
                                            module jbibtex 
                                            {
                                                exports org.jbibtex;
                                            }
                                        </moduleInfoSource>
                                    </module>
                                </modules>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

专门回答你的问题:

How to specify the module-path used?

您可以 运行jlink 从命令行而不是通过 Maven。

这样你就可以指定你想要的任何模块路径。

来自man page for jlink

jlink [options] --module-path modulepath --add-modules module [, module...]

modulepath

The path where the jlink tool discovers observable modules. These modules can be modular JAR files, JMOD files, or exploded modules.

module

The names of the modules to add to the runtime image. The jlink tool adds these modules and their transitive dependencies.

如果您希望继续使用 openjfx maven 插件 jlink 命令,您可以这样做。

配置maven插件传递给jlink的模块路径的代码是in git.

if (modulepathElements != null && !modulepathElements.isEmpty()) {
    commandArguments.add(" --module-path");
    String modulePath = StringUtils.join(modulepathElements.iterator(), File.pathSeparator);
    if (jmodsPath != null && ! jmodsPath.isEmpty()) {
        getLog().debug("Including jmods from local path: " + jmodsPath);
        modulePath = jmodsPath + File.pathSeparator + modulePath;
    }
    commandArguments.add(modulePath);

    commandArguments.add(" --add-modules");
    if (moduleDescriptor != null) {
        commandArguments.add(" " + moduleDescriptor.name());
    } else {
        throw new MojoExecutionException("jlink requires a module descriptor");
    }
}

这是基于javafx:jlink options:

jmodsPath: When using a local JavaFX SDK, sets the path to the local JavaFX jmods

因此,如果您将模块放在该选项指定的路径上,应该可以找到它。


这里有一些其他选项。

使用 jpackage

将您的应用打包为非模块化应用

我认为 mipa 关于使用 JPackageScriptFX 的建议可能是最好的方法:

  • github.com/dlemmermann/JPackageScriptFX

从二进制文件创建一个新的 jar

  1. 解压 JBibTex.jar。
  2. 将编译后的module-info添加到unjared目录中。
  3. 创建一个新的 jar,例如JBibTexModule.jar.
  4. 通过 mvn install 命令将其安装到您的 maven 存储库。
  5. 添加对 JBibTexModule 而不是 JBibTex 的 Maven 依赖。
  6. 将任何需要的语句添加到您的主应用程序模块信息文件以使用该库。

那么,我相信你已经完成了,它会构建,link,运行 ok。

从源创建一个新的 jar

jbibtex 库也在 github 中,因此您可以在项目上创建问题或拉取请求以要求对其进行模块化。

此外,您还可以:

  1. 克隆存储库。
  2. 添加模块-info.java.
  3. 构建 jar 文件。
  4. 在本地 Maven 存储库中本地安装它。
  5. 然后就看你创建的本地版本了