Packaging GDAL with Java

2020-06-27 08:06发布

I have a Java project that uses GDAL bindings on Win7. The problem is that due to the nature of the bindings, it requires setting environment variables to work, specially PATH, GDAL_DATA, GDAL_DRIVER_PATH, and PROJ_LIB. I mean they're easy enough for me to create and point to the GDAL directory. However if I ever want to distribute this, this is going to be an unwieldy step for the average user.

I need some way to configure the GDAL bindings in a way that the user can copy the program wherever they like, which has the jar and GDAL libraries, and the bootstrap code will automatically set GDAL to find those variables relative to it's current location.

Now I tried the following (which uses part of a solution posed in a very similar question: package GDAL JAVA Binding and native library in a SWT plugin):

// define `root` before to grab the path of the where the JAR is located
// bit of a hack-y way to set the classpath
System.setProperty("java.library.path", root+"gdal");
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
// set these gdal config variables programatically
gdal.SetConfigOption("GDAL", root + "gdal");
gdal.SetConfigOption("GDAL_DATA", root + "gdal\\gdal_data");
gdal.SetConfigOption("GDAL_DRIVER_PATH", root + "gdal\\gdalplugins");
gdal.SetConfigOption("PROJ_LIB", root + "gdal\\proj_lib");

But it fails in the first SetConfigOption() with the following error:

Native library load failed.
java.lang.UnsatisfiedLinkError: C:\...\gdal\gdaljni.dll: Can't find dependent libraries

Which means at least the first part is working because it properly locates gdaljni.dll, but seems like before the SetConfigOption() can do its thing, it's already trying to look into these paths just to initialize and failing.

Now if I set the environmental variables manually, obviously, it runs fine.

GDAL bindings from: http://www.gisinternals.com/

1条回答
我欲成王,谁敢阻挡
2楼-- · 2020-06-27 08:55

I apologize for not providing a Windows-specific answer, however the concepts between Unix-like and Windows systems here are fundamentally the same. The error you are having is due to the library path (in Windows, still the binary dll) not being part of the required paths. The GDAL config settings don't manage the route to the DLL, but rather locations to internal data.

This may not be the best solution, however this has worked very well for me in the past. The key is to create a script which updates the path required to start the application.

Inside the script, you need to ...

  1. Get the directory of the script itself so you can start the application from anywhere on the system.
  2. Add the path to your library inside the proper environment variable. Use the SCRIPT_PATH as the base of the path.
  3. Update DYLD_LIBRARY_PATH (Mac), LD_LIBRARY_PATH (Linux), and if I remember, PATH (Windows).
  4. Start the application like you exported the library path using the SCRIPT_PATH variable as the base.

Here is an example where I did not set the rpath in clang on my Mac.

  • package

    • bin/foo
    • lib/libtest.dylib
    • run.sh

Run script

#!/bin/sh

#  Get the directory of this script being run
SCRIPT_PATH="`dirname ${BASH_SOURCE[0]}`"

# Export the Path
export DYLD_LIBRARY_PATH=$SCRIPT_PATH/lib:$DYLD_LIBRARY_PATH

#  Run the executable
$SCRIPT_PATH/bin/foo
查看更多
登录 后发表回答