Search code examples
javagradlesqlite4java

How can I set up a simple gradle project that uses sqlite4java?


I'm starting a simple java test project using sqlite4java and building using java.

I can get the core sqlite4java library downloaded easily, but I'm not sure what the best (any!) way to get gradle to download the native libraries and put them in the right place.

This is my build.gradle file:

apply plugin: 'java'

/* We use Java 1.7 */
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '1.0'

repositories {
    mavenCentral()
}

sourceSets {
    main {
        java.srcDir 'src'
        output.classesDir = 'build/main'
    }
    test {
        java.srcDir 'test'
        output.classesDir = 'build/test'
    }
}


dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    compile "com.almworks.sqlite4java:sqlite4java:1.0.392"
    compile "com.almworks.sqlite4java:libsqlite4java-osx:1.0.392"
}

But when I run a simple test I get:

TestTest > testSqlite4Basic FAILED
    com.almworks.sqlite4java.SQLiteException at TestTest.java:15
        Caused by: java.lang.UnsatisfiedLinkError at TestTest.java:15

(I'm building from within IntelliJ, but am using the gradle build options - so I don't think it's ItelliJ stuffing up the class path when running the tests...)

I'm pretty sure the first time I tried to build I got some message about being unable to unpack the libsqlite4java-osx ZIP file, (not surprisingly as maven central says its a dylib file).

What do I need to do to make gradle do the right thing?

ASIDE: I'm able to get the code to run by manually copying the downloaded .dylib from the maven cache into somewhere listed in my java.library.path (Think I used $HOME/Library/Java/Extensions on my mac). But this seems contrary to the whole point of packaging all setup and dependencies in the .gradle file, and wont let me distribute anything easily later.


Solution

  • Here's a complete answer based on Stanislav's comments.

    apply plugin: 'java'
    
    /* We use Java 1.8 */
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    version = '1.0'
    
    repositories { mavenCentral() }
    
    dependencies {
        testCompile group: 'junit', name: 'junit', version: '4.11'
        compile "com.almworks.sqlite4java:sqlite4java:1.0.392"
        compile "com.almworks.sqlite4java:libsqlite4java-osx:1.0.392"
    }
    
    sourceSets {
        main {
            java.srcDir 'src'
            output.classesDir = 'build/main'
        }
        test {
            java.srcDir 'test'
            output.classesDir = 'build/test'
        }
    }
    
    /* Copy the native files */
    task copyNativeDeps(type: Copy) {
        from (configurations.compile+configurations.testCompile) {
            include "*.dylib"
        }
        into 'build/libs'
    }
    
    /* Make sure we setup the tests to actually copy 
     * the native files and set the paths correctly. */
    test {
        dependsOn copyNativeDeps
        systemProperty "java.library.path", 'build/libs'
    }
    

    And example test source to run for it:

    import com.almworks.sqlite4java.SQLiteConnection;
    import com.almworks.sqlite4java.SQLiteStatement;
    import org.junit.Test;
    
    import java.io.File;
    
    public class SqliteTest {
    
        @Test public void aTest() throws Exception {
            SQLiteConnection db = new SQLiteConnection(new File("/tmp/database"));
            db.open(true);  
    
            SQLiteStatement st = db.prepare("SELECT name FROM dummy");
            try {
                while(st.step()) {
                    System.err.printf("name = %s\n", st.columnString(1));
                }
            } finally {
                st.dispose();
            }
        }
    }