Alternative to loading native libraries

Started by volks73, August 21, 2008, 20:35:20

Previous topic - Next topic

volks73

Hello,

I have been reading the Java Gaming Forum and the LWJGL forum for some time now to learn and acquire resources about game development in general and game development with Java specifically. Sorry, but before I get to my actual post I want to thank the JGF and this forum for all the great information, resources, and advice they provide. I have started work on my first game and I am learning a lot. Thank you.

My development system:

Eclipse IDE 3.3
Ant 1.7
Java 1.6
LWJGL 1.1.4
Windows Vista, XP, and Ubuntu 8.04

I have a private server hosting a subversion repository which allows me to actively develop across all three (or 2.5 if you don't count Vista as full operating system) operating systems. Hence, using Java. I want to play my game on both systems without managing multiple binaries. Allows, I have been writing Java for a while now.

Okay, finally, my question. I was packaging my game into a ZIP file to send to a friend for him to play and test. The folder structure of the ZIP:

+ install dir
| - game.jar
| + lib
| | + native
| | | - *.dll, *.so, etc.
| | - LWJGL.jar
| + config
| + bin
| + images
| + plugins
| + docs

Everything works fine when I run the game from within Eclipse. I have the native library for the LWJGL library set and everything. But when I package the game into a jar and ran it from outside Eclipse, nothing happened. I did some testing and basically it wasn't loading the native libraries. Now, I did some searching on this forum, google, and JGF. There were a couple of options:

1.) Write a script (.bat or .sh) file that would start the game with the VM option -Djava.library.path="path/to/native/libraries/" for each operating system.
2.) Place all the native libraries into the same folder as the game JAR. I currently have the LWJGL library and natives in a subfolder (lib and lib/native).
3.) Custom ClassLoader.

The problem with option 1, I would need the absolute path to the native library folder, but the user could install (basically unpack the archive) anywhere on the computer. This would require a more complex .bat or .sh file to run the game. Seemed a bit too complicated for the end user, or would require an installer and for a simple alpha-quality game would be overkill. Option 2 is the easiest. When I run Ant, just copy the native libraries from the lib folder to the root deployment folder. This worked just fine, but from an end user stand point, this could cause problems because the user would go to the folder where the executable jar is located and become unnerved by all the extra files. This isn't a big deal but it makes the installation messy, plus users have been trained to look for .exe not a .jar, unfortunately. I found examples on this forum of option 3, but I wonder if the following is easier:

public static void main(String[] args)
{	
	final String userDir = System.getProperty("user.dir");
	final String nativeLibDir = userDir + File.separator + "lib" + File.separator + "native" + File.separator;
	System.setProperty("org.lwjgl.librarypath", nativeLibDir);
        
        // Rest of startup game code
}


I went digging through the LWJGL source code to see if it was checking if the native libraries were loaded before starting up because when I used System.load(String) to explicitly load the native libraries, I got the "java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path" exception. I came across the property in the doLoadLibrary(String) method of the Sys class. This code works if all of the native libraries are placed in one folder, such as "lib/native", and it works on both Windows and Linux. Obviously it could be extended to first detect the operating system from the System.getProperty("os.name") property and then append the OS folder to the nativeLibDir thus eliminating the need for all the native libraries to be in one folder. Furthermore, I removed the native library link (Right-click project name->properties->Java Build Path->Libraries->Expand LWJGL->Native Library->Remove) for the LWJGL library in Eclipse and its works when I run the code from within Eclipse too.

So, after all that, my question is simple: Am I missing anything by doing this? Is this bad form or could lead to breakage in the future?

Sorry for the extremely long post.

Volks73
For every winner there are a dozen losers, odds are you are one of them.

Evil-Devil

You don't have to provide the absolute path to the native files. The relative path is enough. The user can export your zip to any location he wants as long the structure you provided with the zip file stays the same.

Grandmaster B

Option 1 should work. Place your game into a subfolder (e.g. /gamebin/) and place the .bat/.sh into the root of this folder. Then do something like:

cd gamebin
game.jar

Fool Running

I would think the way you are doing it is fine. As Evil-Devil said, you shouldn't need to use the absolute path (not sure why you think you need to).
Someone correct me if I'm wrong, but you should be able to just use a '/' or '\' character for the file separator. Java is pretty good at doing the proper translation for you. So the code should be able to be written shorter, like:
System.setProperty("org.lwjgl.librarypath", "lib/native/");
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

pandur

also, launch4j is great.
which is a java executable wrapper. so you can give out an exe to your users...

http://launch4j.sourceforge.net/