How To Use LWJGL From Clojure
February 16, 2013 — 3 minutes long
I recently decided to try my hand at 3D programming in Clojure, and I
settled on trying out LWGJL. Unfortunately, accessing its API takes a
bit more than adding dependencies to
project.clj, and after an hour of
fiddling and searching I wanted to share my solution so that others
- Download the stable release of LWJGL and copy the files from
native/within your project.
native/to the JVM’s library path.
First, The LWJGL Library
The first step, actually, is to update
Central. First we need to put
[org.lwjgl.lwjgl/lwjgl "2.8.5"] inside
:dependencies. If you’re starting a new Leiningen project,
project.clj might look something like this:
(defproject my-project "0.1.0-SNAPSHOT" ; ... :dependencies [[org.clojure/clojure "1.4.0"] [org.lwjgl.lwjgl/lwjgl "2.8.5"]])
You’ll probably want to find out what the current stable version is, and
"2.8.5" with that.
Adding this satisfies the library portion of LWJGL, but if we were to
stop here, we would probably end up with an error like
UnsatisfiedLinkError no lwjgl in java.library.path when trying to
import LWJGL classes from Clojure.
Second, Native Extensions
LWJGL comes with several native extensions for Mac, Linux, and Windows, and it needs those available when running on the respective OS. For some reason, those files do not come with the download from Central and need to be “installed” by hand.
First we’ll create a directory at the top level of our project to hold
the extensions. We can name it
native/, or whatever. The only
important thing is that we remember that name so we can tell
about it in a moment.
Go to the LWJGL downloads page and download the latest stable zip
file. Extract the contents and copy every file within the
native/<my-OS> directory into our project’s
native/ directory. It’s
important that the files are directly under
native/ and not in
java won’t look inside those.
Third, Changing The JVM’s Library Path
project.clj file allows for a
:jvm-opts key-pair that
that is used to set
java’s command-line flags. Here we need to tell
the JVM to look inside the directory where our native extensions are
located. In my case, I used
native/, so you can see that I told it
about that. I also used Clojure’s
str to concatenate my custom library
path to the beginning of the existing path. The new
something like this:
(defproject my-project "0.1.0-SNAPSHOT" ; ... :dependencies [[org.clojure/clojure "1.4.0"] [org.lwjgl.lwjgl/lwjgl "2.8.5"]]) :jvm-opts [~(str "-Djava.library.path=native/:" (System/getProperty "java.library.path"))])
Once this is completed, you should be able to
import away without