Building VTK on Linux with Java support
This document details my experiences, frustrations, and ultimate
success in building VTK 4.0 on RedHat Linux 8.0 with support for Sun's
Java Developement Kit 1.4.1_01. It was written Jan 21, 2003; things have
probably changed since I wrote it. I am not affiliated with Kitware or
the VTK project in any way, use this information at your own risk, there
is no guarantee or warranty, your mileage may vary, etc., etc.
Update! (20
Mar 2003)
Bas van der Linden figured out the mystery of the non-relocatable
libraries. I haven't yet recompiled VTK myself to verify his findings,
so I'll just include them here in original form:
I've used CMake myself for some C++ projects, and know it uses the
-rdynamic flag for linking. This is handy if you're developing shared
libraries, because you don't need to set LD_LIBRARY_PATHs all the time,
because the locations are encoded in the executable or library. This is
also what caused the problem: Java finds the libs in the
LD_LIBRARY_PATH, but those libs have the location of their dependencies
hardcoded inside them. So, it happens a library is loaded twice and all
problems start to happen.
The solution is simple. Using ccmake, toggle expert mode (by
pressing t) and switch the CMAKE_SKIP_RPATH to ON. Recompile. Wait.
Wait. Wait. (C++ takes way too long to compile...) Now, you're able to
move your libraries wherever you want.
I hope this can complete your VTK/Java/Linux HOWTO. Maybe, one more
tip. You don't have to switch BUILD_SHARED_LIBS to ON: if you leave it
off, the libvtk*Java.so libraries will be self contained. The
total size will be smaller (you might want to strip them anyway) than
having both the C++ lib and Java wrapper lib seperately. (I'm using
Debian unstable and VTK is in the distribution, except for the Java
wrappers, so I do not want an extra set of C++ libs, nor do I want to
recompile my Java wrapper libs when Debian moves to a newer version.)
Download and install CMake
Instructions are available on the VTK
website. Also, make sure it's on your path.
In bash: export PATH=/path/to/cmake/bin:$PATH
In csh: setenv PATH /path/to/cmake/bin:$PATH
Download and install Java
I used Sun's JDK 1.4.1_01, the newest release available at the time of
this writing. It was installed in /usr/local/j2sdk1.4.1_01,
with a symlink to /usr/local/java. However, CMake isn't
too smart, and in order for it to find your installation of Java, you
need to make a symlink from /usr/local/lib/java to your JDK
directory.
As root: ln -s /usr/local/j2sdk1.4.1_01 /usr/local/lib/java
Download and unpack the VTK source code
I'll assume you're doing all this from your home directory. It matters
which version of the code you use: I was unable to find success with the
standard, "stable" 4.0 release. Instead, I downloaded and compiled the
nightly release. If there's a newer stable release, you may be able to
use that; otherwise, I recommend the nightly releases. Check the quality
dashboard first, as the VTK site recommends.
Configure the VTK build
From ~/VTK, run ccmake. This will give you
a ncurses text GUI for configuring the build options. You'll need to
turn BUILD_SHARED_LIBS, VTK_USE_ANSI_STDLIB, and VTK_WRAP_JAVA to ON.
Adjust other options as needed; adjust advanced options at your own
risk. Press 'c' a few times until it offers you the option to press 'g'
for generate and exit. You might toggle display of the advanced options
on to make sure CMake found the correct paths to the headers and shared
libraries that are part of your Java install (if you made the symlink to /usr/local/lib/java,
it should have). Press 'g' and then you're ready to build. (See the update for better suggestions on the
configuration options to choose.)
Build VTK
Just type make from ~/VTK. This takes ~ 2
hours on my PIII laptop. If you're lucky, it will build the Java JAR
file for you, too. If you're unlucky, it won't.
You don't need to do a make install; you'll use the
libraries directly from the bin directory. Something bad happens to the
libraries when you do a make install, and they no longer work. (See the update for a solution to this problem.)
Build the JAR
If you're lucky, this has already been done for you by make,
and there's a file called vtk.jar in ~/VTK/bin.
If not, do the following from ~/VTK:
cd java/
mkdir classes/
javac -d classes/ vtk/*.java
cd classes/
jar cvf vtk.jar vtk/
jar i vtk.jar
cp vtk.jar ../../bin/
Prepare your environment
You need to make sure that your newly built VTK libraries (libvtk___.so)
can be found by the dynamic linker, so you have to put their location
on your LD_LIBRARY_PATH.
In bash: export LD_LIBRARY_PATH=~/VTK/bin:$LD_LIBRARY_PATH
In csh: setenv LD_LIBRARY_PATH
~/VTK/bin:$LD_LIBRARY_PATH
You may want to add this to one of your shell startup scripts so that
you don't have to do this every time you log in.
I thought I was able to successfully relocate these libraries using cp
-a ~/VTK/bin ~/devel/vtklibs, but I have been unable to make it
work again. Trying to relocate the libraries, either with make
install or by hand, results in this
error at runtime. This also means they cannot be installed in a
typical location, like /usr/lib or /usr/local/lib.
(It's possible to get around this; see the update.)
You also have to make sure that Java can find vtk.jar.
You can do this by putting it on your CLASSPATH, by using the -cp
or -classpath switches on the command line, or by putting
it in your installed extensions directory (something like /usr/local/java/jre/lib/ext).
It's your choice; I use the command line switches in my Makefiles (for
both javac and java).
Run a test program
I'd recommend using the first part of the tutorial. Do this:
cd Examples/Tutorial/Step1/Java/
javac -classpath ../../../../bin/vtk.jar Cone.java
java -classpath ../../../../bin/vtk.jar:.
Cone
Errors and troubleshooting
An unexpected exception has been detected in native code
outside the VM.
Unexpected Signal : 11 occurred at PC=0x4CA7D87C
Function=_ZN12vtkHashTable12AddHashEntryEPvS0_+0x52
Library=/home/ian/devel/vtklib/libvtkCommonJava.so
Current Java thread:
at
vtk.vtkPolyData.VTKCastInit(Native Method)
at
vtk.vtkPolyDataSource.GetOutput_2(Native Method)
at
vtk.vtkPolyDataSource.GetOutput(vtkPolyDataSource.java:20)
at
vtkprogs.SphereTest.Main(SphereTest.java:78)
at
vtkprogs.SphereTest.main(SphereTest.java:162)
Dynamic libraries:
...
4c9d2000-4ca88000 r-xp 00000000 03:07
786156 /home/ian/devel/vtklib/libvtkCommonJava.so
4ca88000-4cab1000 rw-p 000b6000 03:07
786156 /home/ian/devel/vtklib/libvtkCommonJava.so
...
4cdb8000-4ce6e000 r-xp 00000000 03:07
262765 /home/ian/tmp/VTK/bin/libvtkCommonJava.so
4ce6e000-4ce97000 rw-p 000b6000 03:07
262765 /home/ian/tmp/VTK/bin/libvtkCommonJava.so
...
This sort of error appears to be caused by relocating the libraries;
the linker appears to try to load them both from where they were built
and from where they were copied to. See the update for a possible solution to this
problem. Otherwise, make sure you're using the libraries in-place,
where they were compiled and built by make.
Cone.java:9: package vtk does not exist
import vtk.*;
^
Cone.java:33: cannot resolve symbol
symbol : class vtkConeSource
location: class Cone
vtkConeSource cone = new vtkConeSource();
^
You've left vtk.jar off of your classpath during
compilation.
Exception in thread "main"
java.lang.NoClassDefFoundError: Cone
You've left the current direcory off of your classpath during
execution. This is the reason for the extra colon and dot in the command line above.
Exception in thread "main"
java.lang.NoClassDefFoundError: vtk/vtkMapper
You've left vtk.jar off of your classpath during execution.