Build one jar per platform for multi-platform SWT application

后端 未结 1 1239
清酒与你
清酒与你 2020-12-03 16:39

There are a couple of questions to this topic already, but none of them seem to work properly.

Here is a list of them:

  • Bulding an multi-platform SWT ap
相关标签:
1条回答
  • 2020-12-03 17:05

    Right, so I finally came up with a solution that I successfully tested on three platforms.

    The two magic components are the jar-in-jar-loader and a proper build script.

    The build script with comments can be found here:

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

    What it basically does is define a base classpath without any SWT library. Then it creates platform specific classpaths using the base one and adding the appropriate platform SWT library.

    The jar task then creates a separate jar for each platform using these classpaths and the jar-in-jar-loader.

    And that's it, a fully automated way of generating jars for each (supported) platform.


    I've created an example project that people can download and test out. It's an easy starting point for a multi-platform application.

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


    Update:

    I've managed to significantly shorten the ant script by making proper use of macrodef :)

    0 讨论(0)
提交回复
热议问题