Puuba.Com

The MetronomiconThe WeaponographistConcursionMediaPress


Deploying a Java App As a .EXE or .APP – Free!

The Why:

So, as is probably pretty clear, I’ve been in development on a video game, for PC and Mac, called Concursion.
I know, I know… people say that Java isn’t suited for games, but I’m stubborn, and like Java best, and you’re wrong, and so there.

Thing is, as I’m sure many people have probably encountered, until recently, there didn’t seem to be any Free way to make a Windows .EXE file, or an OSX .app file out of my Java… without paying a software company hundreds (or more) of my moneys. The moneys I’m already investing, as best I can, in a game.

And no one wants to distribute an executable .JAR, or, worse still… some batch file with additional program arguments, bundled with a … something.
Not pro.

So, this might be pretty nerdy, but I thought that I might help.

The What:

Thus, we need a way, for free, to create an EXE and an APP, bundled with:

The How:

It’s not extremely well documented all in one place, but the addition of JavaFX into the main Java deployment package actually provides a native solution. For free! And you already have the tools! Installed!
Hooraaaaaaayyyyyyy!

From this point on, I’m going to walk through the deployment process, in the guise of my Ant build file, from start to end, using a build file I’ve created, which, ideally, you should just be able to pop some key commands into and win. For freedom!
At the end, you can find the file in it’s entirety, for perusal, use, and modification.

Note: Because I’m breaking this down into pieces to explain, I WILL be missing some semantic necessities, in headers or includes. Please see the WHOLE file posted for download to make sure you have all of that. It’s thoroughly documented, and also includes some cleanup etc.
Eventually, these all get strung into one deployment target for quick use.

If you already have a JAR you’re ready to use, you can skip to the deployment step for the guts of this thing.

The Steps:

Step 1 – Compile:

This should be pretty straightforward, but is the first step to creating something you can easily distro. Standard tools here.

<target name=”compile”> 
     <mkdir dir=”${build}”/>
     <javac srcdir=”${src}” destdir=”${build}”
          classpath=”${library1};${library2};${library3}”/>
</target>

If you’re compiling against any frameworks which you then plan to unzip and include in the same single JAR, this is the time to unzip those JARs, and dump them into the same “build” folder.
You can totally keep these separate too, though.

Optional:
<target name=”unzipFrameworks”>
     <unzip src=”${library3}” dest=”${build}”/>
</target>

Step 2 – Create a JAR

Note that we are using the STANDARD and NOT the JavaFX Jar target (javafx:jar). Which makes this, again, pretty trivially standard.
This difference from Oracle’s docs is Key however, and allows us to:

If, on the other hand, you genuinely want/need the JavaFX launcher — use that tag instead. It’s documented elsewhere to keep this shorter…ish. Just note that you’ll have to pass it some extra nested elements (application, info, resources).
If using LWJGL, I recommend the below. Mostly for the DPI stuff.

<target name=”createJar”>
    <delete dir=”${jars}”/>
    <jar destfile=”${jars}/${jarName}.jar”>
        <fileset dir=”${build}”/>
        <manifest>
            <attribute name=”App-Title” value=”${jarName}”/>
            <attribute name=”App-Vendor” value=”${appVendor}”/>
            <attribute name=”Main-Class” value=”${initialClass}”/>
            <attribute name=”Class-Path” value=”${library1} ${library2}”/>
            <attribute name=”Permissions” value=”all-permissions”/>
       </manifest>
     </jar>
</target>

Step 3 – Obfuscate – Protect Your Code (Optional)

I use Proguard (due to habit) to obfuscate my code. Basically, this step goes through all of your methods, fields, classes, etc, and changes all their names to gibberish, making your code way harder to understand for a human. And, therefore, significantly harder to steal/take/crib/jack/…yoink.
It’s not a hardfast firm prevention to code piracy, but it’s a pretty strong deterrent, and makes reading your code pretty angry.

If you’re going open source, or just happy to share… there’s probably no need for this step. I know, I’m a jerk.

Note: If you’re using any sort of reflection, you probably need to exempt some classes or fields from obfuscation. This is fairly easily possible, but outside the scope of this… blog?
This sample preserves only your initial class path (required) and enum support, for convenience.

<target name=”obfuscate”>
    <taskdef resource=”proguard/ant/task.properties”  classpath=”lib/proguard.jar”/>
    <move file=”${jars}/${jarName}.jar” tofile=”${jars}/${jarName}_raw.jar”/>
    <proguard optimize=”false”>
        -libraryjars    “${java.home}/lib/rt.jar”${cpSeperator}${library1}${cpSeperator}${library2}
        -injars         ${jars}/${jarName}_raw.jar
        -outjars        ${jars}/${jarName}.jar
        -keep public class ${initialClass} {
        public static void main(java.lang.String[]);
        }
        -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
        }
     </proguard>
</target>

Step 4 – Generate Your Native Bundles – Deploy!!!!!

Finally, the step you’re waiting for. This step will take your processed JAR, and turn it into something magical.

For a Windows PC, it’ll create a file bundle containing, at it’s top level, an EXE file. This should be all you have to double-click to launch. The backing files will be in nearby subfolders.
For a Mac OSX, it’ll create a single .app file, containing all your works and widgets. It’s like f’ing magic.

Note that paths (set elsewhere in the build file) specify and include:

If all goes well, at the end of this, you’re virtually good to go. You’ve got something deploy-worthy.

<fx:deploy width=”1920″ height=”1080″ nativebundles=”image”
            outdir=”${deploy}${deployFolderExtension}”
            outfile=”${jarName}”>
    <fx:application refid=”gameName”/>
    <fx:info title=”${jarName}” vendor=”${appVendor}”
            copyright=”${copyrightInfo}” description=”${description}”>
        <fx:icon href=”${iconName}”/>   <!–Defined above. A .ico for Windows, or an .icns for OSX.”–>
    </fx:info>
    <fx:preferences shortcut=”true” menu=”true” install=”true”/>
    <fx:permissions elevated=”true”/>
    <fx:resources>
        <fx:fileset dir=”${jars}” includes=”${jarName}.jar” type=”jar”/>
        <fx:fileset dir=”.” includes=”${resources}/,${library1},${library2}”/>
        <fx:fileset dir=”${natives}” type=”data”>
            <include name=”*.${nativeExtension}”/>
        </fx:fileset>
    </fx:resources>
<fx:platform>
<fx:jvmarg value=”jvmArg1″/> <!–Whatever JVM arguments are set above.–>
        <fx:jvmarg value=”jvmArg2″/>
</fx:platform>

</fx:deploy>

Step 5 – Sign the .APP Bundle – Mac OSX Only

At the end of all this, it’ll SEEM like your .APP file is golden. You’ll run it, it’ll launch, and no security errors will report.
DO NOT TRUST THIS.

OSX tracks the origin of files, and knows which ones you’ve downloaded vs created locally. As such, it’s not checking the security measures in the same way as would someone else’s computer, who downloads your app.
Their computer, right now, will be a jerk, suggest that your app is insecure, and recommend deletion. Yep, the OS itself will recommend deletion. 🙂
At the very least, it’ll pose a question, implying you aren’t to be trusted.

And so far… you aren’t.

Note: For any of the below to work, you’ll need to have met some requirements:

Then:

  1. Copy the following file:
         ./Library/Java/JavaVirtualMachines/jdk1.7###.jdk/Info.plist
    Into:
         deployMac/bundles/GameName.app/Contents/PlugIns/jdk1.7###/
  2. Take note of the ID of that cert (found in the Keychain Access app).
    It will look something like: “Developer ID Application: Company Name (ABCD1234EF)“.
  3. Open up the terminal (command line) and type the following commands:
  4. codesign –force –sign “Developer ID Application: Company Name (ABCD1234EF)” /PathToYourDeployment/deployMac/bundles/GameName.app/Contents/PlugIns/jdk1.7.0_51.jdk/Contents
    This signs the JDK itself, which is required in the very latest versions of OSX.
    The easiest way to do this is to drag the Contents/PlugIns/jdk### folder into the command prompt after typing the first part.
  5. codesign –force –sign “Developer ID Application: Company Name (ABCD1234EF)” /PathToYourDeployment/deployMac/bundles/GameName.app
    Now, you’re signing the app itself.

 

Tada!

Shazam. You’re done.
You have an EXE or an APP (or both), and you’re ready to put that stuff on the interwebs.
Enjoy!

Download the file here!

buildDemo.xml

Note: You can only create an APP on a Mac, and can only create an EXE on a PC. So, you’ll need whichever computer handy, to do the respective build.
The build file supports both just for convenience so you can share a project.

-Danny Garfield
Danny@puuba.com

Categories

Concursion Updates
Danger Elaborates
Danny Plays
Danny Says
Let's All Sounds!
Puuba Shorts
The Metronomicon
The Weaponographist
Uncategorized
W8wut?

Recent Posts

The Release Trailer is Here!
Hero Spotlights Go!
Live Action Trailer - Behind The Scenes
Slay The Dance Floor - Live Action Trailer!
Chiptune Challenge Pack Two Released!
Indie Game Challenge Pack One Released!

Archives

  • August 2017
  • July 2017
  • October 2016
  • September 2016
  • August 2016
  • July 2016