Build multi-platform executable for a SWT application (Eclipse)

孤街醉人 提交于 2019-12-08 07:26:00

问题


I have an Eclipse-based SWT application, not using Maven.

My application targets multiple operating systems (CentOS, Windows, and Mac).

The only jar file that is not OS agnostic is the SWT library, which is specific to each OS type, not to mention processor type (x86 and/or x64).

I saw this other issue, but that targets Maven and I am not using Maven.

I have "org.eclipse.swt" added to my project by following an outlined procedure and including the entire SWT downloaded ZIP file. That specifies a second project in Package Explorer.

Earlier when I was just including swt.jar, it was a bit easier, as I just had to delete the jar, include the new one, and rebuild, but that was a a pain. Now that I use the entire SWT ZIP, the process is a bit tedious and not professional.

What are the steps, so that when I specify "right click > Java > Runnable JAR file" to create a single executable jar that I get 3 (or however many) different jar files, one per operating system? Visual Studio does that nicely, just I do not know how to do that here in Eclipse.

UPDATE: To answer a comment, I wanted to add JFace support, as I want to use the TableViewer feature, which requires JFace. Eclipse has this page outlining in the first part how to add in SWT. The steps work except for adding the source code at the end, but that is off-topic.

I followed the steps for 64-bit Windows, however I have to support CENTOS and Mac would be a "would be nice" at the moment.

Independent of swt.jar verses org.eclipse.swt, I would like a clean way (think Visual Studio with .Net) to build a single runnable/executable jar file for my application, one per supported OS type. My thought is that I specify build (whatever menu key sequence after I set things up) and I get one single executable jar file per target OS.


回答1:


Right, despite me saying that you can create a single .jar file for all platforms, I wasn't able to get it working properly.

However, I managed to get an example project up and running that will create a separate .jar file for each platform for you by simply using Ant.

You can download the whole project here.

The build script looks like this:

<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" />

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

    <!-- Define the class path -->
    <path id="classpath">
        <fileset dir="${lib.dir}" includes="**/*.jar" />
        <fileset dir="${lib.deploy.dir}" includes="**/swt_linux_gtk_x86.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>

    <!-- Define classpath and create the jar folder -->
    <target name="pre_jar" depends="compile">
        <pathconvert property="manifest.classpath" pathsep=" ">
            <path refid="classpath" />
            <mapper>
                <chainedmapper>
                    <flattenmapper />
                    <globmapper from="*.jar" to="*.jar" />
                </chainedmapper>
            </mapper>
        </pathconvert>

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

    <!-- Create the jar files -->
    <target name="jar" depends="pre_jar">
        <!-- Linux 32bit -->
        <jar destfile="${jar.dir}/${ant.project.name}_linux_gtk_x86.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="./ ${manifest.classpath}" />
            </manifest>

            <zipgroupfileset dir="${lib.dir}" includes="**/jar-in-jar-loader.jar" />
            <zipfileset dir="${lib.deploy.dir}" includes="**/swt_linux_gtk_x86.jar" />
            <zipfileset dir="${lib.dir}" includes="**/*.jar" excludes="**/jar-in-jar-loader.jar" />
        </jar>
        <!-- Linux 64bit -->
        <jar destfile="${jar.dir}/${ant.project.name}_linux_gtk_x64.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="./ ${manifest.classpath}" />
            </manifest>

            <zipgroupfileset dir="${lib.dir}" includes="**/jar-in-jar-loader.jar" />
            <zipfileset dir="${lib.deploy.dir}" includes="**/swt_linux_gtk_x64.jar" />
            <zipfileset dir="${lib.dir}" includes="**/*.jar" excludes="**/jar-in-jar-loader.jar" />
        </jar>
        <!-- Windows 32bit -->
        <jar destfile="${jar.dir}/${ant.project.name}_win32_x86.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="./ ${manifest.classpath}" />
            </manifest>

            <zipgroupfileset dir="${lib.dir}" includes="**/jar-in-jar-loader.jar" />
            <zipfileset dir="${lib.deploy.dir}" includes="**/swt_win32_x86.jar" />
            <zipfileset dir="${lib.dir}" includes="**/*.jar" excludes="**/jar-in-jar-loader.jar" />
        </jar>
        <!-- Windows 64bit -->
        <jar destfile="${jar.dir}/${ant.project.name}_win32_x64.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="./ ${manifest.classpath}" />
            </manifest>

            <zipgroupfileset dir="${lib.dir}" includes="**/jar-in-jar-loader.jar" />
            <zipfileset dir="${lib.deploy.dir}" includes="**/swt_win32_x64.jar" />
            <zipfileset dir="${lib.dir}" includes="**/*.jar" excludes="**/jar-in-jar-loader.jar" />
        </jar>
        <!-- MacOS 32bit -->
        <jar destfile="${jar.dir}/${ant.project.name}_macos_x86.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="./ ${manifest.classpath}" />
            </manifest>

            <zipgroupfileset dir="${lib.dir}" includes="**/jar-in-jar-loader.jar" />
            <zipfileset dir="${lib.deploy.dir}" includes="**/swt_macosx_x86.jar" />
            <zipfileset dir="${lib.dir}" includes="**/*.jar" excludes="**/jar-in-jar-loader.jar" />
        </jar>
        <!-- MacOS 64bit -->
        <jar destfile="${jar.dir}/${ant.project.name}_macos_x64.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="./ ${manifest.classpath}" />
            </manifest>

            <zipgroupfileset dir="${lib.dir}" includes="**/jar-in-jar-loader.jar" />
            <zipfileset dir="${lib.deploy.dir}" includes="**/swt_macosx_x64.jar" />
            <zipfileset dir="${lib.dir}" includes="**/*.jar" excludes="**/jar-in-jar-loader.jar" />
        </jar>
    </target>

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

</project>

The project itself is nothing fancy, just a JFace Dialog to show that JFace works as well.


NOTE:

To make this compile on a Windows machine, you will have to change one line:

<fileset dir="${lib.deploy.dir}" includes="**/swt_linux_gtk_x86.jar" />

change it to:

<fileset dir="${lib.deploy.dir}" includes="**/swt_win32_x64.jar" />

or

<fileset dir="${lib.deploy.dir}" includes="**/swt_win32_x86.jar" />

Basically, this line has to represent YOUR system, i.e., the system you're compiling on.



来源:https://stackoverflow.com/questions/22303755/build-multi-platform-executable-for-a-swt-application-eclipse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!