使用Maven构建多平台可执行的SWT应用程序

6
我的问题是:如何使用Maven一次生成多个可执行Jar文件(包括依赖项),以根据目标操作系统/架构运行SWT应用程序?
我已经创建了一个SWT应用程序,需要在不同的操作系统和架构上运行。该项目是一个包含父POM的Maven多模块项目。 project-pom.xml(打包=pom,指定SWT依赖项) `- application-module(继承SWT依赖项) `- pom.xml(打包=jar) `- domain-specific-module `- pom.xml(打包=jar) `- utils-module(继承SWT依赖项) `- pom.xml(打包=jar)
在父POM(project-pom.xml)中,我已经使用maven配置文件包含了SWT依赖项,以根据我的操作系统和架构进行设置,这很好用:
<dependencies>
    <dependency>
        <groupId>org.eclipse.swt</groupId>
        <artifactId>${swt.artifactId}</artifactId>
        <version>4.3</version>
    </dependency>
</dependencies>

<repositories>
    <repository>
        <id>EclipseSwtRepository</id>
        <url>https://swt-repo.googlecode.com/svn/repo/</url>
    </repository>
</repositories>

<profiles>
    <profile>
        <id>unix-amd64</id>
        <activation>
            <os>
                <family>unix</family>
                <arch>amd64</arch>
            </os>
        </activation>
        <properties>
            <swt.artifactId>org.eclipse.swt.gtk.linux.x86_64</swt.artifactId>
        </properties>
    </profile>
    <profile>
        <id>windows-x86</id>
        <activation>
            <os>
                <family>windows</family>
                <arch>x86</arch>
            </os>
        </activation>
        <properties>
            <swt.artifactId>org.eclipse.swt.win32.win32.x86</swt.artifactId>
        </properties>
    </profile>
    <profile>
        <id>windows-x86_64</id>
        <activation>
            <os>
                <family>windows</family>
                <arch>x86_64</arch>
            </os>
        </activation>
        <properties>
            <swt.artifactId>org.eclipse.swt.win32.win32.x86_64</swt.artifactId>
        </properties>
    </profile>
</profiles>

现在Maven会选择正确的SWT依赖项,例如用于编译应用程序。我使用Maven命令mvn help:active-profiles检查了活动配置文件。
现在我想为目标平台linux_x86_64/amd64、windows_x86和windows_x86_64生成可执行Jars。首先,我使用maven-jar-plugin生成Jar和清单文件(application-module/pom.xml):
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>libs/</classpathPrefix>
                 <mainClass>qualified.path.to.MyApplication</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

这个很好用。Jar包已经生成,并且清单文件也在里面。正如您所看到的,我的意图是将所有依赖项放在名为lib/的目录中。但是,该Jar文件无法执行(缺少库文件)。

理论上,下一步是在package阶段查找依赖项并将其复制到lib/目录中。对于这一步骤,我(尝试)使用maven-dependency-plugin (application-module/pom.xml):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.8</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/libs</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>

如果我运行命令mvn package,没有任何反应(在target/或其他地方都没有创建目录)。为了检查插件是否正常工作,我使用了命令mvn dependency: copy-dependencies,它创建了一个名为dependency的目录(我假设这是此插件的默认值),并将所有依赖的Jar文件放在其中。
这是我遇到的第一个问题。下一个问题是,如何一次性创建多个(而不仅仅是单个)可执行的Jar文件,根据我的SWT应用程序的目标操作系统/体系结构(使用类似mvn package的单个命令)?生成的构建目录结构应类似于以下内容:
target/
`- linux_x86_64/
   `- application-version_linux_x86_64.jar
   `- libs/
      `- org.eclipse.swt.gtk.linux.x86_64-4.3.jar
      `- ...
`- windows_x86/
   `- application-version_windows_x86.jar
   `- libs/
      `- org.eclipse.swt.win32.win32.x86-4.3.jar
      `- ...
`- windows_x86_64/
   `- application-version_x86_64.jar
   `- libs/
      `- org.eclipse.swt.win32.win32.x86_64-4.3.jar
      `- ...
另一个解决方案是直接将依赖项放在Jar文件中,但目前我还不知道如何做到这一点。
我在这个上下文中了解了其他插件(maven-assembly-plugin,maven-shade-plugin),但目前这些插件对我来说都太多信息,无法确定是否会起作用。有没有人能告诉我哪个插件最适合我的目的?
最终完成后,我想使用launch4j-maven-plugin生成本地Windows可执行文件(最终用户不喜欢非本地可执行文件的感觉),并使用先前为Windows生成的可执行Jar文件。
希望这些信息足够了。

我没有完全阅读这两个问题,但是这个问题不是重复的吗?这个问题 - Baz
感谢您的回复。是的,这看起来很相似(我也阅读了它,以及许多其他文章),但那里的问题并没有真正解决。首先,maven-dependency-plugin对我不起作用,我不知道为什么。其次,我不想将所有配置文件名称作为命令行参数传递给Maven,以实现多个可执行文件的构建。我更喜欢内联POM解决方案。其他开发人员可能不知道应该传递这些参数。 - Marcel
嗯,好的。虽然我不使用Maven,但我无法帮助您。我可以为您提供一个简单的ant脚本,创建一个多平台的单一jar文件 :) 但我猜这对您没有帮助 ;) - Baz
没问题,谢谢你的提供 :) 如果我在使用Maven时感到绝望,我会联系你寻求Ant支持 ;) - Marcel
1个回答

4
我使用 Maven 学习了 JackRabbit 的设置来完成这个操作。JackRabbit以各种形式(独立、OSGi包、Web应用程序等)提供,并且所有内容都是从一个聚合POM文件中完成的。
第一步是将父 POM 文件与配置文件和公共依赖项分开,然后通过聚合 POM 文件定义项目的子模块(顺序)。聚合 POM 文件中的第一个子模块通常是父 POM 文件。聚合 POM 文件的优点是可以使用它来构建整个项目的所有内容。
接下来,我创建了一个“通用组装资源”项目,该项目生成一个包含所有资源(例如自述文件、手册、图片等)的 JAR 文件,这些资源在平台上的所有组装中都会使用。每个平台组装项目都会提取此 JAR 文件,然后将提取的文件复制到适当的位置。就我所看到的,JackRabbit并没有这样做,因此您可以跳过此步骤。

最后,为每个平台创建一个独立的平台组件子模块。在平台组件中,您可以设置要和不要的依赖关系。子模块可以包含特定于平台的文件(例如,Windows的批处理文件,Linux的.sh文件)。组件形式可以针对平台进行特定制作(例如,.zip适用于Windows,.tar.gz适用于Linux)。对于Windows,我还包括NSIS以创建setup.exe(您也可以在安装了NSIS软件包的Linux上构建它)。

在这个设置中,我经常使用maven-dependency-plugin来处理不同的阶段。我经常使用的一个是阶段process-resources,您可以尝试使用它代替阶段package


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接