为多平台SWT应用程序构建每个平台一个jar包

5
这个主题已经有几个问题了,但似乎没有一个正常工作的。
以下是它们的列表:
- 使用Ant构建多平台SWT应用程序 - 为SWT应用程序(Eclipse)构建多平台可执行文件 - 使用maven为SWT应用程序构建多平台可执行文件 - 适用于不同平台的SWT jar - 创建跨平台Java SWT应用程序 我的要求是构建一个ant脚本,创建每个平台的一个jar,即Windows x86、Windows x64、Linux x86/x64等。
有人有更深入的见解吗?
使用上述方法,我无法生成可行的解决方案。它要么以SWT jar文件未自动加载而结束,要么未包含在类路径中。
如果有人能提供一个可行的示例(最好包括完整的源代码),那就太好了!

3
嘿,很高兴看到有人试图将所有这些信息集合在一个地方。干得好! - Nobody
1个回答

6

好的,我最终想出了一个解决方案,并在三个平台上成功测试过。

这两个神奇的组件是jar-in-jar-loader和适当的构建脚本。

带有注释的构建脚本可以在此处找到:

<project name="RandomApp" basedir="." default="clean-build">

    <property name="src.dir" value="src" />

    <!-- Define the necessary paths -->
    <property name="build.dir" value="bin_temp" />
    <property name="lib.dir" value="lib" />
    <property name="lib.deploy.dir" value="lib_swt" />
    <property name="classes.dir" value="${build.dir}/classes" />
    <property name="jar.dir" value="${build.dir}/jar" />
    <property name="img.dir" value="img" />
    <property name="res.dir" value="res" />

    <!-- Define the main class -->
    <property name="main-class" value="org.baz.desktop.randomapp.gui.RandomApp" />

    <path id="base-classpath">
        <fileset dir="${lib.dir}" includes="**/*.jar" />
    </path>

    <!-- Define the class path -->
    <path id="classpath">
        <fileset dir="${lib.dir}" includes="**/*.jar" />
        <fileset dir="${lib.deploy.dir}" includes="**/swt_win32_x64.jar" />
    </path>

    <!-- Clean previously built files -->
    <target name="clean">
        <delete dir="${build.dir}" />
    </target>

    <!-- Compile the project -->
    <target name="compile">
        <mkdir dir="${classes.dir}" />
        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" includeantruntime="false" />
    </target>

    <macrodef name="createclasspath">
        <attribute name="name" />
        <attribute name="swtlib" />
        <sequential>
            <pathconvert property="@{name}.classpath" pathsep=" ">
                <path refid="base-classpath" />
                <fileset dir="${lib.deploy.dir}" includes="**/swt_@{swtlib}.jar" />
                <mapper>
                    <chainedmapper>
                        <flattenmapper />
                        <globmapper from="*.jar" to="*.jar" />
                    </chainedmapper>
                </mapper>
            </pathconvert>
        </sequential>
    </macrodef>

    <!-- Define classpath and create the jar folder -->
    <target name="pre_jar" depends="compile">
        <!-- Linux 32bit -->
        <createclasspath name="win86" swtlib="win32_x86" />
        <!-- Linux 64bit -->
        <createclasspath name="win64" swtlib="win32_x64" />
        <!-- Windows 32bit -->
        <createclasspath name="linux86" swtlib="linux_gtk_x86" />
        <!-- Windows 64bit -->
        <createclasspath name="linux64" swtlib="linux_gtk_x64" />
        <!-- MacOS 32bit -->
        <createclasspath name="macos86" swtlib="macos_x86" />
        <!-- MacOS 64bit -->
        <createclasspath name="macos64" swtlib="macos_x64" />

        <mkdir dir="${jar.dir}" />
    </target>

    <macrodef name="createjar">
        <attribute name="swtlib" />
        <attribute name="swtclasspath" />
        <sequential>
            <jar destfile="${jar.dir}/${ant.project.name}_@{swtlib}.jar" basedir="${classes.dir}">
                <manifest>
                    <attribute name="Main-Class" value="org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader" />
                    <attribute name="Rsrc-Main-Class" value="${main-class}" />
                    <attribute name="Class-Path" value="." />
                    <attribute name="Rsrc-Class-Path" value="./ @{swtclasspath}" />
                </manifest>

                <zipgroupfileset dir="${lib.dir}" includes="**/jar-in-jar-loader.jar" />
                <zipfileset dir="${lib.deploy.dir}" includes="**/swt_@{swtlib}.jar" />
                <zipfileset dir="${lib.dir}" includes="**/*.jar" excludes="**/jar-in-jar-loader.jar" />
            </jar>
        </sequential>
    </macrodef>

    <!-- Create the jar files -->
    <target name="jar" depends="pre_jar">
        <!-- Linux 32bit -->
        <createjar swtlib="linux_gtk_x86" swtclasspath="${linux86.classpath}" />
        <!-- Linux 64bit -->
        <createjar swtlib="linux_gtk_x64" swtclasspath="${linux64.classpath}" />
        <!-- Windows 32bit -->
        <createjar swtlib="win32_x86" swtclasspath="${win86.classpath}" />
        <!-- Windows 64bit -->
        <createjar swtlib="win32_x64" swtclasspath="${win64.classpath}" />
        <!-- MacOS 32bit -->
        <createjar swtlib="macos_x86" swtclasspath="${macos86.classpath}" />
        <!-- MacOS 64bit -->
        <createjar swtlib="macos_x64" swtclasspath="${macos64.classpath}" />
    </target>

    <target name="clean-build" depends="clean,jar" />

</project>

它的基本作用是定义一个没有任何SWT库的基础类路径。然后使用基础路径创建特定于平台的类路径,并添加适当的平台SWT库。
然后,jar任务使用这些类路径和jar-in-jar-loader为每个平台创建单独的jar包。
这就是全部,一种完全自动化生成每个(受支持的)平台的jar包的方式。
我已经创建了一个示例项目,供人们下载和测试。这是一个多平台应用程序的简单起点。

https://www.dropbox.com/s/ianrbl4bn0fmsdi/SWTApplication.7z


更新:

我通过正确使用macrodef成功地大幅缩短了蚂蚁脚本 :)


你尝试过使用SWT创建exe文件和.dmg文件,而不使用RCP或第三方付费工具吗? - App Work
@AppWork 不是,我使用Install4J来创建这些。不过你可以从他们那里获得开源许可证。那个是免费的。 - Baz
@AppWork 如果你的应用程序是非盈利开源项目,并在你的工具网站上添加一个指向他们网站的链接,那么你可以免费使用Install4J。更多信息请参见:https://www.ej-technologies.com/buy/install4j/openSource - Baz
价格对于商业用途来说太高了。还有其他可供选择的替代品吗?Nullsoft Scriptable Install System (NSIS) 怎么样?你试过了吗? - App Work
launch4j和JSmooth都可以免费用于Windows系统。两者均有GNU通用公共许可证。https://dev59.com/U0rSa4cB1Zd3GeqPZtvv#5349215 - App Work
@AppWork 我只使用过Install4j,因为我所有的工具都是开源的。 - Baz

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