[][src]Crate jerk

jerk: Java Embedding Rust Kit

Crates.io Docs GitHub unsafe: yes rust: 1.36.0+ License

Libraries to compile/embed/test Java alongside a Rust library/application. Similar to cc, but for Java. This is not an official project of Google, Oracle, Sun Microsystems, or anyone else.

BranchBadgesNotes
publishOpen issuesStable/published version
masterBuild Status"Completed" stuff that hasn't been published.
wip/*"Work In Progress" - incomplete, use at your own risk.
dead/*Abandoned threads of work

Goals

  • Minimal dependencies
  • Compile small amounts of Java before/alongside your Rust code via javac, jar, etc.
  • TODO?: Compile small amounts of Kotlin before/alongside your Rust code via kotlinc etc.
  • TODO?: Compile small amounts of whatever JVM language before/alongside your Rust code via Ant, Groovy, etc.
  • TODO?: Auto-locate tools based on env vars, common paths, etc.
  • TODO?: Auto-install missing tools for you.

Non-Goals

  • Directly compete with Ant, Groovy, etc. as a fully fledged Java build tool.

Quick Start

Install the JDK if you haven't already.

Add this to your Cargo.toml:

[lib]
crate-type = ["dylib"]

[dependencies]
jni-sys     = "0.3"

[build-dependencies]
jerk        = "0.2"

[dev-dependencies]
jerk        = "0.2"

And this to your build.rs:

fn main() {
    jerk::metabuild();
}

You can then write Java (src/Adder.java) code:

package com.maulingmonkey.jerk.example_hello_world_jar;
public class Adder {
    public native int add(int a, int b);
    public static void test() {
        System.loadLibrary("example_hello_world_jar");
        assert adder.add(1, 2) == 3;
    }
}

...alongside your Rust (src/Adder.rs) code:

use jni_sys::{JNIEnv, jobject, jint};
#[no_mangle] pub extern "stdcall" fn Java_com_maulingmonkey_jerk_example_1hello_1world_1jar_Adder_add__II(_env: *mut JNIEnv, _this: jobject, a: jint, b: jint) -> jint {
    a + b
}

...and write Java integration tests (tests/test.rs):

extern crate example_hello_world_jar; // force dylib to build
#[test] fn test() {
    jerk::run_test!("com.maulingmonkey.jerk.example_hello_world_jar", "Adder", "test");
}

...and then build and run the test!

C:\local\jerk>cargo t
    Finished dev [unoptimized + debuginfo] target(s) in 0.06s
     Running target\debug\deps\example_hello_world_jar-2997df28c387b743.exe

running 1 tests
test adder::test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Java <-> Rust Interop Pontificating

Rust code may sanely depend on Java code to build, but not vicea versa:

  • Java's ABI has great metadata (classes, methods, doc info, etc.), Rust doesn't even have a stable ABI.
  • Local Java <- Rust <- Java dependency cycles at compile time would be terrible to manage.

You can still have:

  • Java call into Rust, it should just be through native methods declared in Java.
  • Rust-driven packaging bundle Java JARs (e.g. when creating Android APKs) as a final step.
  • Rust define runtime classes implementing interfaces, they just wouldn't be visible to Java at compile time.

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Modules

jvm

Java VM Management APIs

paths

JDK and JVM path utilities

test

Macros

run_test

Execute a Java unit test. The method must be static, return void, and take no arguments.

Functions

metabuild

A cargo metabuild compatible entry point.