A (very dirty) configuration example of Project Panama.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

init

bpavuk 644ebdfb

+1606
+1
.direnv/flake-profile
··· 1 + flake-profile-9-link
+1
.envrc
··· 1 + use flake
+45
.gitignore
··· 1 + .gradle 2 + build/ 3 + !gradle/wrapper/gradle-wrapper.jar 4 + !**/src/main/**/build/ 5 + !**/src/test/**/build/ 6 + 7 + ### IntelliJ IDEA ### 8 + .idea/modules.xml 9 + .idea/jarRepositories.xml 10 + .idea/compiler.xml 11 + .idea/libraries/ 12 + *.iws 13 + *.iml 14 + *.ipr 15 + out/ 16 + !**/src/main/**/out/ 17 + !**/src/test/**/out/ 18 + 19 + ### Kotlin ### 20 + .kotlin 21 + 22 + ### Eclipse ### 23 + .apt_generated 24 + .classpath 25 + .factorypath 26 + .project 27 + .settings 28 + .springBeans 29 + .sts4-cache 30 + bin/ 31 + !**/src/main/**/bin/ 32 + !**/src/test/**/bin/ 33 + 34 + ### NetBeans ### 35 + /nbproject/private/ 36 + /nbbuild/ 37 + /dist/ 38 + /nbdist/ 39 + /.nb-gradle/ 40 + 41 + ### VS Code ### 42 + .vscode/ 43 + 44 + ### Mac OS ### 45 + .DS_Store
+10
.idea/.gitignore
··· 1 + # Default ignored files 2 + /shelf/ 3 + /workspace.xml 4 + # Ignored default folder with query files 5 + /queries/ 6 + # Datasource local storage ignored files 7 + /dataSources/ 8 + /dataSources.local.xml 9 + # Editor-based HTTP Client requests 10 + /httpRequests/
+6
.idea/AndroidProjectSystem.xml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <project version="4"> 3 + <component name="AndroidProjectSystem"> 4 + <option name="providerId" value="com.android.tools.idea.GradleProjectSystem" /> 5 + </component> 6 + </project>
+31
.idea/gradle.xml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <project version="4"> 3 + <component name="GradleMigrationSettings" migrationVersion="1" /> 4 + <component name="GradleSettings"> 5 + <option name="linkedExternalProjectsSettings"> 6 + <GradleProjectSettings> 7 + <compositeConfiguration> 8 + <compositeBuild compositeDefinitionSource="SCRIPT"> 9 + <builds> 10 + <build path="$PROJECT_DIR$/buildSrc" name="buildSrc"> 11 + <projects> 12 + <project path="$PROJECT_DIR$/buildSrc" /> 13 + </projects> 14 + </build> 15 + </builds> 16 + </compositeBuild> 17 + </compositeConfiguration> 18 + <option name="externalProjectPath" value="$PROJECT_DIR$" /> 19 + <option name="gradleJvm" value="corretto-24" /> 20 + <option name="modules"> 21 + <set> 22 + <option value="$PROJECT_DIR$" /> 23 + <option value="$PROJECT_DIR$/app" /> 24 + <option value="$PROJECT_DIR$/buildSrc" /> 25 + <option value="$PROJECT_DIR$/interop-panama" /> 26 + </set> 27 + </option> 28 + </GradleProjectSettings> 29 + </option> 30 + </component> 31 + </project>
+7
.idea/kotlinc.xml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <project version="4"> 3 + <component name="KotlinJpsPluginSettings"> 4 + <option name="externalSystemId" value="Gradle" /> 5 + <option name="version" value="2.3.0" /> 6 + </component> 7 + </project>
+9
.idea/misc.xml
··· 1 + <project version="4"> 2 + <component name="ExternalStorageConfigurationManager" enabled="true" /> 3 + <component name="FrameworkDetectionExcludesConfiguration"> 4 + <file type="web" url="file://$PROJECT_DIR$" /> 5 + </component> 6 + <component name="ProjectRootManager" version="2" languageLevel="JDK_24" default="true" project-jdk-name="corretto-24" project-jdk-type="JavaSDK"> 7 + <output url="file://$PROJECT_DIR$/out" /> 8 + </component> 9 + </project>
+6
.idea/vcs.xml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <project version="4"> 3 + <component name="VcsDirectoryMappings"> 4 + <mapping directory="$PROJECT_DIR$" vcs="Git" /> 5 + </component> 6 + </project>
+14
README.md
··· 1 + # panama-exploration 2 + 3 + This is an example configuration of Project Panama: 4 + 5 + - `rust-src` cdylib crate connected as a library 6 + - Dynamically generated bindings in `interop-panama` 7 + - `app` Kotlin consumer module 8 + - A Nix flake that includes everything you need to reproduce the results everywhere Nix is available 9 + 10 + I **strongly advise** you to use what Nix flake provides through `nix develop` or `direnv allow`. 11 + It’ll set up Cargo, glibc, and Azul Zulu Community JDK. That's all you need. 12 + 13 + To run, simply execute `./gradlew run`. If you want to learn more about how it works, dive into `src-rust` crate 14 + and `interop-panama` Gradle module, especially buildscript files.
+50
app/build.gradle.kts
··· 1 + plugins { 2 + // Apply the shared build logic from a convention plugin. 3 + // The shared code is located in `buildSrc/src/main/kotlin/kotlin-jvm.gradle.kts`. 4 + id("buildsrc.convention.kotlin-jvm") 5 + 6 + // Apply the Application plugin to add support for building an executable JVM application. 7 + application 8 + } 9 + 10 + dependencies { 11 + // Project "app" depends on project "utils". (Project paths are separated with ":", so ":utils" refers to the top-level "utils" project.) 12 + implementation(project(":interop-panama")) 13 + } 14 + 15 + application { 16 + // Define the Fully Qualified Name for the application main class 17 + // (Note that Kotlin compiles `App.kt` to a class with FQN `com.example.app.AppKt`.) 18 + mainClass = "org.example.app.AppKt" 19 + 20 + applicationDefaultJvmArgs = listOf( 21 + "--enable-native-access=ALL-UNNAMED", 22 + ) 23 + } 24 + 25 + val rustLibName = providers.provider { 26 + when { 27 + org.gradle.internal.os.OperatingSystem.current().isLinux -> "libsrc_rust.so" 28 + else -> error("Unsupported operating system") 29 + } 30 + } 31 + 32 + tasks.named<JavaExec>("run") { 33 + dependsOn(":interop-panama:copyRustLib") 34 + val nativeDir = project(":interop-panama").layout.buildDirectory.dir("native") 35 + jvmArgs( 36 + "--enable-native-access=ALL-UNNAMED", 37 + "--illegal-native-access=deny", 38 + "-Drust.library.path=${nativeDir.get().file(rustLibName.get()).asFile.absolutePath}" 39 + ) 40 + } 41 + 42 + tasks.withType<Test>().configureEach { 43 + dependsOn(":interop-panama:copyRustLib") 44 + val nativeDir = project(":interop-panama").layout.buildDirectory.dir("native") 45 + jvmArgs( 46 + "--enable-native-access=ALL-UNNAMED", 47 + "--illegal-native-access=deny", 48 + "-Drust.library.path=${nativeDir.get().file(rustLibName.get()).asFile.absolutePath}" 49 + ) 50 + }
+20
app/src/main/kotlin/App.kt
··· 1 + package org.example.app 2 + 3 + import org.example.interop.ExternStruct 4 + import org.example.interop.RustApi 5 + import org.example.interop.jvm_interop_h 6 + 7 + // if IDEA or Kotlin LSP is scared, run ./gradlew :interop-panama:generateJextractBindings. 8 + // jvm_interop_h is a jextract-generated class. 9 + fun main() { 10 + println("Hello from Kotlin!") 11 + println("Heavy Rust calculation: 40 + 2 = ${RustApi.add(40, 2)}") 12 + println("Testing generated Java code: 40 + 2 = ${jvm_interop_h.add(40, 2)}") 13 + 14 + // operating on Rust/C-defined structs 15 + val struct = jvm_interop_h.extern_struct_new(60, 9) // this returns MemorySegment! 16 + val xFromRust = ExternStruct.x(struct) // accessor methods - they read from MemorySegment 17 + val yFromRust = ExternStruct.y(struct) 18 + println("Rust owns these. x: $xFromRust, y: $yFromRust. also, xy = nice!") 19 + jvm_interop_h.extern_struct_free(struct) // remember to clean after yourself! 20 + }
+16
buildSrc/build.gradle.kts
··· 1 + plugins { 2 + // The Kotlin DSL plugin provides a convenient way to develop convention plugins. 3 + // Convention plugins are located in `src/main/kotlin`, with the file extension `.gradle.kts`, 4 + // and are applied in the project's `build.gradle.kts` files as required. 5 + `kotlin-dsl` 6 + } 7 + 8 + kotlin { 9 + // Keep the build logic on a Kotlin-supported JDK even if runtime is newer. 10 + jvmToolchain(24) 11 + } 12 + 13 + dependencies { 14 + // Add a dependency on the Kotlin Gradle plugin, so that convention plugins can apply it. 15 + implementation(libs.kotlinGradlePlugin) 16 + }
+17
buildSrc/settings.gradle.kts
··· 1 + dependencyResolutionManagement { 2 + 3 + // Use Maven Central and the Gradle Plugin Portal for resolving dependencies in the shared build logic (`buildSrc`) project. 4 + @Suppress("UnstableApiUsage") 5 + repositories { 6 + mavenCentral() 7 + } 8 + 9 + // Reuse the version catalog from the main build. 10 + versionCatalogs { 11 + create("libs") { 12 + from(files("../gradle/libs.versions.toml")) 13 + } 14 + } 15 + } 16 + 17 + rootProject.name = "buildSrc"
+29
buildSrc/src/main/kotlin/kotlin-jvm.gradle.kts
··· 1 + // The code in this file is a convention plugin - a Gradle mechanism for sharing reusable build logic. 2 + // `buildSrc` is a Gradle-recognized directory and every plugin there will be easily available in the rest of the build. 3 + package buildsrc.convention 4 + 5 + import org.gradle.api.tasks.testing.logging.TestLogEvent 6 + 7 + plugins { 8 + // Apply the Kotlin JVM plugin to add support for Kotlin in JVM projects. 9 + kotlin("jvm") 10 + } 11 + 12 + kotlin { 13 + // Use a specific Java version to make it easier to work in different environments. 14 + jvmToolchain(24) 15 + } 16 + 17 + tasks.withType<Test>().configureEach { 18 + // Configure all test Gradle tasks to use JUnitPlatform. 19 + useJUnitPlatform() 20 + 21 + // Log information about all test results, not only the failed ones. 22 + testLogging { 23 + events( 24 + TestLogEvent.FAILED, 25 + TestLogEvent.PASSED, 26 + TestLogEvent.SKIPPED 27 + ) 28 + } 29 + }
+63
flake.lock
··· 1 + { 2 + "nodes": { 3 + "fenix": { 4 + "inputs": { 5 + "nixpkgs": [ 6 + "nixpkgs" 7 + ], 8 + "rust-analyzer-src": "rust-analyzer-src" 9 + }, 10 + "locked": { 11 + "lastModified": 1769929675, 12 + "narHash": "sha256-EBpe7sXCPLs+qVePXbA7kc+Kmpmp0pWysEpjjEWTK+E=", 13 + "rev": "78d518f5ca32a86dc767de481160dbae640c70cf", 14 + "revCount": 2542, 15 + "type": "tarball", 16 + "url": "https://api.flakehub.com/f/pinned/nix-community/fenix/0.1.2542%2Brev-78d518f5ca32a86dc767de481160dbae640c70cf/019c1851-0ed1-7f81-b175-8e8bbad651e6/source.tar.gz" 17 + }, 18 + "original": { 19 + "type": "tarball", 20 + "url": "https://flakehub.com/f/nix-community/fenix/0.1" 21 + } 22 + }, 23 + "nixpkgs": { 24 + "locked": { 25 + "lastModified": 1771369470, 26 + "narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=", 27 + "rev": "0182a361324364ae3f436a63005877674cf45efb", 28 + "revCount": 948083, 29 + "type": "tarball", 30 + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.948083%2Brev-0182a361324364ae3f436a63005877674cf45efb/019c71f3-061e-7c0e-b75b-ea375738503a/source.tar.gz" 31 + }, 32 + "original": { 33 + "type": "tarball", 34 + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.1" 35 + } 36 + }, 37 + "root": { 38 + "inputs": { 39 + "fenix": "fenix", 40 + "nixpkgs": "nixpkgs" 41 + } 42 + }, 43 + "rust-analyzer-src": { 44 + "flake": false, 45 + "locked": { 46 + "lastModified": 1769857242, 47 + "narHash": "sha256-3eKpRRzKz0KzY7CJzRXFm4POwEqbuTohyQ2ajI/zKvg=", 48 + "owner": "rust-lang", 49 + "repo": "rust-analyzer", 50 + "rev": "17304e9c7e11d26139672d3d77aa498b1cae0d69", 51 + "type": "github" 52 + }, 53 + "original": { 54 + "owner": "rust-lang", 55 + "ref": "nightly", 56 + "repo": "rust-analyzer", 57 + "type": "github" 58 + } 59 + } 60 + }, 61 + "root": "root", 62 + "version": 7 63 + }
+82
flake.nix
··· 1 + { 2 + description = "A Nix-flake-based Rust development environment"; 3 + 4 + inputs = { 5 + nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1"; # unstable Nixpkgs 6 + fenix = { 7 + url = "https://flakehub.com/f/nix-community/fenix/0.1"; 8 + inputs.nixpkgs.follows = "nixpkgs"; 9 + }; 10 + }; 11 + 12 + outputs = 13 + { self, ... }@inputs: 14 + 15 + let 16 + supportedSystems = [ 17 + "x86_64-linux" 18 + "aarch64-linux" 19 + "x86_64-darwin" 20 + "aarch64-darwin" 21 + ]; 22 + forEachSupportedSystem = 23 + f: 24 + inputs.nixpkgs.lib.genAttrs supportedSystems ( 25 + system: 26 + f { 27 + pkgs = import inputs.nixpkgs { 28 + inherit system; 29 + overlays = [ 30 + inputs.self.overlays.default 31 + ]; 32 + }; 33 + } 34 + ); 35 + in 36 + { 37 + overlays.default = final: prev: { 38 + rustToolchain = 39 + with inputs.fenix.packages.${prev.stdenv.hostPlatform.system}; 40 + combine ( 41 + with stable; 42 + [ 43 + clippy 44 + rustc 45 + cargo 46 + rustfmt 47 + rust-src 48 + ] 49 + ); 50 + }; 51 + 52 + devShells = forEachSupportedSystem ( 53 + { pkgs }: 54 + { 55 + default = pkgs.mkShell { 56 + packages = with pkgs; [ 57 + clang 58 + rustToolchain 59 + openssl 60 + pkg-config 61 + cargo-deny 62 + cargo-edit 63 + cargo-watch 64 + rust-analyzer 65 + 66 + # Panama FFI 67 + jextract 68 + rust-cbindgen 69 + 70 + zulu25 71 + ]; 72 + 73 + env = { 74 + # Required by rust-analyzer 75 + RUST_SRC_PATH = "${pkgs.rustToolchain}/lib/rustlib/src/rust/library"; 76 + CPATH = "${pkgs.glibc.dev}/include"; 77 + }; 78 + }; 79 + } 80 + ); 81 + }; 82 + }
+9
gradle.properties
··· 1 + # Enable the build cache to save time by reusing outputs produced by other successful builds. 2 + # https://docs.gradle.org/current/userguide/build_cache.html 3 + org.gradle.caching=true 4 + # Enable the configuration cache to reuse the build configuration and enable parallel task execution. 5 + # (Note that some plugins may not yet be compatible with the configuration cache.) 6 + # https://docs.gradle.org/current/userguide/configuration_cache.html 7 + org.gradle.configuration-cache=true 8 + # Prefer the JDK provided by JAVA_HOME (e.g. the dev shell) for toolchains. 9 + org.gradle.java.installations.fromEnv=JAVA_HOME
+22
gradle/libs.versions.toml
··· 1 + # Version catalog is a central place for you to declare and version dependencies 2 + # https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog 3 + # https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format 4 + 5 + [versions] 6 + kotlin = "2.3.0" 7 + kotlinxDatetime = "0.7.1" 8 + kotlinxSerializationJSON = "1.9.0" 9 + kotlinxCoroutines = "1.10.2" 10 + 11 + [libraries] 12 + kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } 13 + kotlinxDatetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" } 14 + kotlinxSerialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJSON" } 15 + kotlinxCoroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } 16 + 17 + # Libraries can be bundled together for easier import 18 + [bundles] 19 + kotlinxEcosystem = ["kotlinxDatetime", "kotlinxSerialization", "kotlinxCoroutines"] 20 + 21 + [plugins] 22 + kotlinPluginSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
gradle/wrapper/gradle-wrapper.jar

This is a binary file and will not be displayed.

+6
gradle/wrapper/gradle-wrapper.properties
··· 1 + #Thu Feb 19 09:25:49 GMT 2026 2 + distributionBase=GRADLE_USER_HOME 3 + distributionPath=wrapper/dists 4 + distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip 5 + zipStoreBase=GRADLE_USER_HOME 6 + zipStorePath=wrapper/dists
+234
gradlew
··· 1 + #!/bin/sh 2 + 3 + # 4 + # Copyright © 2015-2021 the original authors. 5 + # 6 + # Licensed under the Apache License, Version 2.0 (the "License"); 7 + # you may not use this file except in compliance with the License. 8 + # You may obtain a copy of the License at 9 + # 10 + # https://www.apache.org/licenses/LICENSE-2.0 11 + # 12 + # Unless required by applicable law or agreed to in writing, software 13 + # distributed under the License is distributed on an "AS IS" BASIS, 14 + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + # See the License for the specific language governing permissions and 16 + # limitations under the License. 17 + # 18 + 19 + ############################################################################## 20 + # 21 + # Gradle start up script for POSIX generated by Gradle. 22 + # 23 + # Important for running: 24 + # 25 + # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 + # noncompliant, but you have some other compliant shell such as ksh or 27 + # bash, then to run this script, type that shell name before the whole 28 + # command line, like: 29 + # 30 + # ksh Gradle 31 + # 32 + # Busybox and similar reduced shells will NOT work, because this script 33 + # requires all of these POSIX shell features: 34 + # * functions; 35 + # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 + # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 + # * compound commands having a testable exit status, especially «case»; 38 + # * various built-in commands including «command», «set», and «ulimit». 39 + # 40 + # Important for patching: 41 + # 42 + # (2) This script targets any POSIX shell, so it avoids extensions provided 43 + # by Bash, Ksh, etc; in particular arrays are avoided. 44 + # 45 + # The "traditional" practice of packing multiple parameters into a 46 + # space-separated string is a well documented source of bugs and security 47 + # problems, so this is (mostly) avoided, by progressively accumulating 48 + # options in "$@", and eventually passing that to Java. 49 + # 50 + # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 + # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 + # see the in-line comments for details. 53 + # 54 + # There are tweaks for specific operating systems such as AIX, CygWin, 55 + # Darwin, MinGW, and NonStop. 56 + # 57 + # (3) This script is generated from the Groovy template 58 + # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 + # within the Gradle project. 60 + # 61 + # You can find Gradle at https://github.com/gradle/gradle/. 62 + # 63 + ############################################################################## 64 + 65 + # Attempt to set APP_HOME 66 + 67 + # Resolve links: $0 may be a link 68 + app_path=$0 69 + 70 + # Need this for daisy-chained symlinks. 71 + while 72 + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 + [ -h "$app_path" ] 74 + do 75 + ls=$( ls -ld "$app_path" ) 76 + link=${ls#*' -> '} 77 + case $link in #( 78 + /*) app_path=$link ;; #( 79 + *) app_path=$APP_HOME$link ;; 80 + esac 81 + done 82 + 83 + APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 + 85 + APP_NAME="Gradle" 86 + APP_BASE_NAME=${0##*/} 87 + 88 + # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 + DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 + 91 + # Use the maximum available, or set MAX_FD != -1 to use that value. 92 + MAX_FD=maximum 93 + 94 + warn () { 95 + echo "$*" 96 + } >&2 97 + 98 + die () { 99 + echo 100 + echo "$*" 101 + echo 102 + exit 1 103 + } >&2 104 + 105 + # OS specific support (must be 'true' or 'false'). 106 + cygwin=false 107 + msys=false 108 + darwin=false 109 + nonstop=false 110 + case "$( uname )" in #( 111 + CYGWIN* ) cygwin=true ;; #( 112 + Darwin* ) darwin=true ;; #( 113 + MSYS* | MINGW* ) msys=true ;; #( 114 + NONSTOP* ) nonstop=true ;; 115 + esac 116 + 117 + CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 + 119 + 120 + # Determine the Java command to use to start the JVM. 121 + if [ -n "$JAVA_HOME" ] ; then 122 + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 + # IBM's JDK on AIX uses strange locations for the executables 124 + JAVACMD=$JAVA_HOME/jre/sh/java 125 + else 126 + JAVACMD=$JAVA_HOME/bin/java 127 + fi 128 + if [ ! -x "$JAVACMD" ] ; then 129 + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 + 131 + Please set the JAVA_HOME variable in your environment to match the 132 + location of your Java installation." 133 + fi 134 + else 135 + JAVACMD=java 136 + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 + 138 + Please set the JAVA_HOME variable in your environment to match the 139 + location of your Java installation." 140 + fi 141 + 142 + # Increase the maximum file descriptors if we can. 143 + if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 + case $MAX_FD in #( 145 + max*) 146 + MAX_FD=$( ulimit -H -n ) || 147 + warn "Could not query maximum file descriptor limit" 148 + esac 149 + case $MAX_FD in #( 150 + '' | soft) :;; #( 151 + *) 152 + ulimit -n "$MAX_FD" || 153 + warn "Could not set maximum file descriptor limit to $MAX_FD" 154 + esac 155 + fi 156 + 157 + # Collect all arguments for the java command, stacking in reverse order: 158 + # * args from the command line 159 + # * the main class name 160 + # * -classpath 161 + # * -D...appname settings 162 + # * --module-path (only if needed) 163 + # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 + 165 + # For Cygwin or MSYS, switch paths to Windows format before running java 166 + if "$cygwin" || "$msys" ; then 167 + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 + 170 + JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 + 172 + # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 + for arg do 174 + if 175 + case $arg in #( 176 + -*) false ;; # don't mess with options #( 177 + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 + [ -e "$t" ] ;; #( 179 + *) false ;; 180 + esac 181 + then 182 + arg=$( cygpath --path --ignore --mixed "$arg" ) 183 + fi 184 + # Roll the args list around exactly as many times as the number of 185 + # args, so each arg winds up back in the position where it started, but 186 + # possibly modified. 187 + # 188 + # NB: a `for` loop captures its iteration list before it begins, so 189 + # changing the positional parameters here affects neither the number of 190 + # iterations, nor the values presented in `arg`. 191 + shift # remove old arg 192 + set -- "$@" "$arg" # push replacement arg 193 + done 194 + fi 195 + 196 + # Collect all arguments for the java command; 197 + # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 + # shell script including quotes and variable substitutions, so put them in 199 + # double quotes to make sure that they get re-expanded; and 200 + # * put everything else in single quotes, so that it's not re-expanded. 201 + 202 + set -- \ 203 + "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 + -classpath "$CLASSPATH" \ 205 + org.gradle.wrapper.GradleWrapperMain \ 206 + "$@" 207 + 208 + # Use "xargs" to parse quoted args. 209 + # 210 + # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 + # 212 + # In Bash we could simply go: 213 + # 214 + # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 + # set -- "${ARGS[@]}" "$@" 216 + # 217 + # but POSIX shell has neither arrays nor command substitution, so instead we 218 + # post-process each arg (as a line of input to sed) to backslash-escape any 219 + # character that might be a shell metacharacter, then use eval to reverse 220 + # that process (while maintaining the separation between arguments), and wrap 221 + # the whole thing up as a single "set" statement. 222 + # 223 + # This will of course break if any of these variables contains a newline or 224 + # an unmatched quote. 225 + # 226 + 227 + eval "set -- $( 228 + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 + xargs -n1 | 230 + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 + tr '\n' ' ' 232 + )" '"$@"' 233 + 234 + exec "$JAVACMD" "$@"
+89
gradlew.bat
··· 1 + @rem 2 + @rem Copyright 2015 the original author or authors. 3 + @rem 4 + @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 + @rem you may not use this file except in compliance with the License. 6 + @rem You may obtain a copy of the License at 7 + @rem 8 + @rem https://www.apache.org/licenses/LICENSE-2.0 9 + @rem 10 + @rem Unless required by applicable law or agreed to in writing, software 11 + @rem distributed under the License is distributed on an "AS IS" BASIS, 12 + @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 + @rem See the License for the specific language governing permissions and 14 + @rem limitations under the License. 15 + @rem 16 + 17 + @if "%DEBUG%" == "" @echo off 18 + @rem ########################################################################## 19 + @rem 20 + @rem Gradle startup script for Windows 21 + @rem 22 + @rem ########################################################################## 23 + 24 + @rem Set local scope for the variables with windows NT shell 25 + if "%OS%"=="Windows_NT" setlocal 26 + 27 + set DIRNAME=%~dp0 28 + if "%DIRNAME%" == "" set DIRNAME=. 29 + set APP_BASE_NAME=%~n0 30 + set APP_HOME=%DIRNAME% 31 + 32 + @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 + for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 + 35 + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 + set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 + 38 + @rem Find java.exe 39 + if defined JAVA_HOME goto findJavaFromJavaHome 40 + 41 + set JAVA_EXE=java.exe 42 + %JAVA_EXE% -version >NUL 2>&1 43 + if "%ERRORLEVEL%" == "0" goto execute 44 + 45 + echo. 46 + echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 + echo. 48 + echo Please set the JAVA_HOME variable in your environment to match the 49 + echo location of your Java installation. 50 + 51 + goto fail 52 + 53 + :findJavaFromJavaHome 54 + set JAVA_HOME=%JAVA_HOME:"=% 55 + set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 + 57 + if exist "%JAVA_EXE%" goto execute 58 + 59 + echo. 60 + echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 + echo. 62 + echo Please set the JAVA_HOME variable in your environment to match the 63 + echo location of your Java installation. 64 + 65 + goto fail 66 + 67 + :execute 68 + @rem Setup the command line 69 + 70 + set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 + 72 + 73 + @rem Execute Gradle 74 + "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 + 76 + :end 77 + @rem End local scope for the variables with windows NT shell 78 + if "%ERRORLEVEL%"=="0" goto mainEnd 79 + 80 + :fail 81 + rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 + rem the _cmd.exe /c_ return code! 83 + if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 + exit /b 1 85 + 86 + :mainEnd 87 + if "%OS%"=="Windows_NT" endlocal 88 + 89 + :omega
+82
interop-panama/build.gradle.kts
··· 1 + import org.gradle.internal.os.OperatingSystem 2 + import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 3 + 4 + plugins { 5 + // Apply the shared build logic from a convention plugin. 6 + // The shared code is located in `buildSrc/src/main/kotlin/kotlin-jvm.gradle.kts`. 7 + id("buildsrc.convention.kotlin-jvm") 8 + id("java") 9 + } 10 + 11 + val rustProjectDir = rootProject.layout.projectDirectory.dir("src-rust") 12 + val rustTargetDir = rustProjectDir.dir("target/debug") 13 + val rustHeadersDir = rustProjectDir.dir("bindings") 14 + val jextractOutputDir = layout.buildDirectory.dir("generated/jextract") 15 + 16 + val rustLibFileName = providers.provider { 17 + when { 18 + OperatingSystem.current().isLinux -> "libsrc_rust.so" 19 + else -> error("Unsupported operating system: ${OperatingSystem.current()}") 20 + } 21 + } 22 + 23 + val buildRustCdylib by tasks.registering(Exec::class) { 24 + group = "interop" 25 + description = "Build src-rust cdylib with Cargo" 26 + workingDir = rustProjectDir.asFile 27 + commandLine("cargo", "build") 28 + } 29 + 30 + val copyRustLib by tasks.registering(Copy::class) { 31 + group = "interop" 32 + description = "Copy Rust shared library into interop build output" 33 + dependsOn(buildRustCdylib) 34 + from(rustTargetDir.file(rustLibFileName)) 35 + into(layout.buildDirectory.dir("native")) 36 + } 37 + 38 + val copyHeaders by tasks.registering(Copy::class) { 39 + group = "interop" 40 + description = "Copy generated headers into interop build output" 41 + dependsOn(buildRustCdylib) 42 + from(rustHeadersDir.file("jvm_interop.h")) 43 + into(layout.buildDirectory.dir("native")) 44 + } 45 + 46 + // HACK: I'd rather interact with jextract as a build-time dependency, much like 47 + // Rust's cbindgen crate in rust-src/build.rs 48 + val generateJextractBindings by tasks.registering(Exec::class) { 49 + group = "interop" 50 + description = "Generate bindings from headers" 51 + workingDir = layout.projectDirectory.asFile 52 + dependsOn(copyRustLib, copyHeaders) 53 + val nativeDir = layout.buildDirectory.dir("native").get().asFile 54 + val nativeLibPath = layout.buildDirectory.dir("native").get().file(rustLibFileName).get().asFile.absolutePath 55 + outputs.dir(jextractOutputDir) 56 + commandLine( 57 + "jextract", 58 + "--include-dir", nativeDir.absolutePath, 59 + "--output", jextractOutputDir.get().asFile.absolutePath, 60 + "--target-package", "org.example.interop", 61 + "--library", ":$nativeLibPath", 62 + layout.buildDirectory.dir("native").get().file("jvm_interop.h").asFile.absolutePath 63 + ) 64 + } 65 + 66 + tasks.named("classes") { 67 + dependsOn(generateJextractBindings) 68 + } 69 + 70 + sourceSets { 71 + named("main") { 72 + java.srcDir(jextractOutputDir) 73 + } 74 + } 75 + 76 + tasks.withType<KotlinCompile>().configureEach { 77 + dependsOn(generateJextractBindings) 78 + } 79 + 80 + dependencies { 81 + testImplementation(kotlin("test")) 82 + }
+30
interop-panama/src/main/kotlin/interop/Main.kt
··· 1 + package org.example.interop 2 + 3 + import java.lang.foreign.Arena 4 + import java.lang.foreign.FunctionDescriptor 5 + import java.lang.foreign.Linker 6 + import java.lang.foreign.SymbolLookup 7 + import java.lang.foreign.ValueLayout.JAVA_LONG 8 + import java.nio.file.Path 9 + 10 + object RustApi { 11 + // Most of the time, you do not need to interact with these low-level APIs, 12 + // as jextract generates bindings for you. 13 + private val addHandle by lazy { 14 + val libPath = System.getProperty("rust.library.path") 15 + ?: error("Missing -Drust.library.path JVM property") 16 + 17 + val arena = Arena.ofAuto() 18 + val symbols = SymbolLookup.libraryLookup(Path.of(libPath), arena) 19 + val symbol = symbols.find("add") 20 + .orElseThrow { IllegalStateException("Symbol 'add' not found in $libPath") } 21 + 22 + Linker.nativeLinker().downcallHandle( 23 + symbol, 24 + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, JAVA_LONG) 25 + ) 26 + } 27 + 28 + fun add(left: Long, right: Long): Long = 29 + addHandle.invoke(left, right) as Long 30 + }
+25
settings.gradle.kts
··· 1 + // The settings file is the entry point of every Gradle build. 2 + // Its primary purpose is to define the subprojects. 3 + // It is also used for some aspects of project-wide configuration, like managing plugins, dependencies, etc. 4 + // https://docs.gradle.org/current/userguide/settings_file_basics.html 5 + 6 + dependencyResolutionManagement { 7 + // Use Maven Central as the default repository (where Gradle will download dependencies) in all subprojects. 8 + @Suppress("UnstableApiUsage") 9 + repositories { 10 + mavenCentral() 11 + } 12 + } 13 + 14 + plugins { 15 + // Use the Foojay Toolchains plugin to automatically download JDKs required by subprojects. 16 + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" 17 + } 18 + 19 + // Include the `app` and `utils` subprojects in the build. 20 + // If there are changes in only one of the projects, Gradle will rebuild only the one that has changed. 21 + // Learn more about structuring projects with Gradle - https://docs.gradle.org/8.7/userguide/multi_project_builds.html 22 + include(":app") 23 + include(":interop-panama") 24 + 25 + rootProject.name = "panama-exploration"
+2
src-rust/.gitignore
··· 1 + /target 2 + /bindings
+623
src-rust/Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "anstream" 7 + version = "0.6.21" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" 10 + dependencies = [ 11 + "anstyle", 12 + "anstyle-parse", 13 + "anstyle-query", 14 + "anstyle-wincon", 15 + "colorchoice", 16 + "is_terminal_polyfill", 17 + "utf8parse", 18 + ] 19 + 20 + [[package]] 21 + name = "anstyle" 22 + version = "1.0.13" 23 + source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" 25 + 26 + [[package]] 27 + name = "anstyle-parse" 28 + version = "0.2.7" 29 + source = "registry+https://github.com/rust-lang/crates.io-index" 30 + checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 31 + dependencies = [ 32 + "utf8parse", 33 + ] 34 + 35 + [[package]] 36 + name = "anstyle-query" 37 + version = "1.1.5" 38 + source = "registry+https://github.com/rust-lang/crates.io-index" 39 + checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" 40 + dependencies = [ 41 + "windows-sys", 42 + ] 43 + 44 + [[package]] 45 + name = "anstyle-wincon" 46 + version = "3.0.11" 47 + source = "registry+https://github.com/rust-lang/crates.io-index" 48 + checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" 49 + dependencies = [ 50 + "anstyle", 51 + "once_cell_polyfill", 52 + "windows-sys", 53 + ] 54 + 55 + [[package]] 56 + name = "anyhow" 57 + version = "1.0.101" 58 + source = "registry+https://github.com/rust-lang/crates.io-index" 59 + checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" 60 + 61 + [[package]] 62 + name = "bitflags" 63 + version = "2.11.0" 64 + source = "registry+https://github.com/rust-lang/crates.io-index" 65 + checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" 66 + 67 + [[package]] 68 + name = "cbindgen" 69 + version = "0.29.2" 70 + source = "registry+https://github.com/rust-lang/crates.io-index" 71 + checksum = "befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799" 72 + dependencies = [ 73 + "clap", 74 + "heck", 75 + "indexmap", 76 + "log", 77 + "proc-macro2", 78 + "quote", 79 + "serde", 80 + "serde_json", 81 + "syn", 82 + "tempfile", 83 + "toml", 84 + ] 85 + 86 + [[package]] 87 + name = "cfg-if" 88 + version = "1.0.4" 89 + source = "registry+https://github.com/rust-lang/crates.io-index" 90 + checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 91 + 92 + [[package]] 93 + name = "clap" 94 + version = "4.5.59" 95 + source = "registry+https://github.com/rust-lang/crates.io-index" 96 + checksum = "c5caf74d17c3aec5495110c34cc3f78644bfa89af6c8993ed4de2790e49b6499" 97 + dependencies = [ 98 + "clap_builder", 99 + ] 100 + 101 + [[package]] 102 + name = "clap_builder" 103 + version = "4.5.59" 104 + source = "registry+https://github.com/rust-lang/crates.io-index" 105 + checksum = "370daa45065b80218950227371916a1633217ae42b2715b2287b606dcd618e24" 106 + dependencies = [ 107 + "anstream", 108 + "anstyle", 109 + "clap_lex", 110 + "strsim", 111 + ] 112 + 113 + [[package]] 114 + name = "clap_lex" 115 + version = "1.0.0" 116 + source = "registry+https://github.com/rust-lang/crates.io-index" 117 + checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" 118 + 119 + [[package]] 120 + name = "colorchoice" 121 + version = "1.0.4" 122 + source = "registry+https://github.com/rust-lang/crates.io-index" 123 + checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 124 + 125 + [[package]] 126 + name = "equivalent" 127 + version = "1.0.2" 128 + source = "registry+https://github.com/rust-lang/crates.io-index" 129 + checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 130 + 131 + [[package]] 132 + name = "errno" 133 + version = "0.3.14" 134 + source = "registry+https://github.com/rust-lang/crates.io-index" 135 + checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 136 + dependencies = [ 137 + "libc", 138 + "windows-sys", 139 + ] 140 + 141 + [[package]] 142 + name = "fastrand" 143 + version = "2.3.0" 144 + source = "registry+https://github.com/rust-lang/crates.io-index" 145 + checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 146 + 147 + [[package]] 148 + name = "foldhash" 149 + version = "0.1.5" 150 + source = "registry+https://github.com/rust-lang/crates.io-index" 151 + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 152 + 153 + [[package]] 154 + name = "getrandom" 155 + version = "0.4.1" 156 + source = "registry+https://github.com/rust-lang/crates.io-index" 157 + checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" 158 + dependencies = [ 159 + "cfg-if", 160 + "libc", 161 + "r-efi", 162 + "wasip2", 163 + "wasip3", 164 + ] 165 + 166 + [[package]] 167 + name = "hashbrown" 168 + version = "0.15.5" 169 + source = "registry+https://github.com/rust-lang/crates.io-index" 170 + checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 171 + dependencies = [ 172 + "foldhash", 173 + ] 174 + 175 + [[package]] 176 + name = "hashbrown" 177 + version = "0.16.1" 178 + source = "registry+https://github.com/rust-lang/crates.io-index" 179 + checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" 180 + 181 + [[package]] 182 + name = "heck" 183 + version = "0.5.0" 184 + source = "registry+https://github.com/rust-lang/crates.io-index" 185 + checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 186 + 187 + [[package]] 188 + name = "id-arena" 189 + version = "2.3.0" 190 + source = "registry+https://github.com/rust-lang/crates.io-index" 191 + checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" 192 + 193 + [[package]] 194 + name = "indexmap" 195 + version = "2.13.0" 196 + source = "registry+https://github.com/rust-lang/crates.io-index" 197 + checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" 198 + dependencies = [ 199 + "equivalent", 200 + "hashbrown 0.16.1", 201 + "serde", 202 + "serde_core", 203 + ] 204 + 205 + [[package]] 206 + name = "is_terminal_polyfill" 207 + version = "1.70.2" 208 + source = "registry+https://github.com/rust-lang/crates.io-index" 209 + checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" 210 + 211 + [[package]] 212 + name = "itoa" 213 + version = "1.0.17" 214 + source = "registry+https://github.com/rust-lang/crates.io-index" 215 + checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" 216 + 217 + [[package]] 218 + name = "leb128fmt" 219 + version = "0.1.0" 220 + source = "registry+https://github.com/rust-lang/crates.io-index" 221 + checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" 222 + 223 + [[package]] 224 + name = "libc" 225 + version = "0.2.182" 226 + source = "registry+https://github.com/rust-lang/crates.io-index" 227 + checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" 228 + 229 + [[package]] 230 + name = "linux-raw-sys" 231 + version = "0.11.0" 232 + source = "registry+https://github.com/rust-lang/crates.io-index" 233 + checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" 234 + 235 + [[package]] 236 + name = "log" 237 + version = "0.4.29" 238 + source = "registry+https://github.com/rust-lang/crates.io-index" 239 + checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" 240 + 241 + [[package]] 242 + name = "memchr" 243 + version = "2.8.0" 244 + source = "registry+https://github.com/rust-lang/crates.io-index" 245 + checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" 246 + 247 + [[package]] 248 + name = "once_cell" 249 + version = "1.21.3" 250 + source = "registry+https://github.com/rust-lang/crates.io-index" 251 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 252 + 253 + [[package]] 254 + name = "once_cell_polyfill" 255 + version = "1.70.2" 256 + source = "registry+https://github.com/rust-lang/crates.io-index" 257 + checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" 258 + 259 + [[package]] 260 + name = "prettyplease" 261 + version = "0.2.37" 262 + source = "registry+https://github.com/rust-lang/crates.io-index" 263 + checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" 264 + dependencies = [ 265 + "proc-macro2", 266 + "syn", 267 + ] 268 + 269 + [[package]] 270 + name = "proc-macro2" 271 + version = "1.0.106" 272 + source = "registry+https://github.com/rust-lang/crates.io-index" 273 + checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" 274 + dependencies = [ 275 + "unicode-ident", 276 + ] 277 + 278 + [[package]] 279 + name = "quote" 280 + version = "1.0.44" 281 + source = "registry+https://github.com/rust-lang/crates.io-index" 282 + checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" 283 + dependencies = [ 284 + "proc-macro2", 285 + ] 286 + 287 + [[package]] 288 + name = "r-efi" 289 + version = "5.3.0" 290 + source = "registry+https://github.com/rust-lang/crates.io-index" 291 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 292 + 293 + [[package]] 294 + name = "rustix" 295 + version = "1.1.3" 296 + source = "registry+https://github.com/rust-lang/crates.io-index" 297 + checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" 298 + dependencies = [ 299 + "bitflags", 300 + "errno", 301 + "libc", 302 + "linux-raw-sys", 303 + "windows-sys", 304 + ] 305 + 306 + [[package]] 307 + name = "semver" 308 + version = "1.0.27" 309 + source = "registry+https://github.com/rust-lang/crates.io-index" 310 + checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" 311 + 312 + [[package]] 313 + name = "serde" 314 + version = "1.0.228" 315 + source = "registry+https://github.com/rust-lang/crates.io-index" 316 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 317 + dependencies = [ 318 + "serde_core", 319 + "serde_derive", 320 + ] 321 + 322 + [[package]] 323 + name = "serde_core" 324 + version = "1.0.228" 325 + source = "registry+https://github.com/rust-lang/crates.io-index" 326 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 327 + dependencies = [ 328 + "serde_derive", 329 + ] 330 + 331 + [[package]] 332 + name = "serde_derive" 333 + version = "1.0.228" 334 + source = "registry+https://github.com/rust-lang/crates.io-index" 335 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 336 + dependencies = [ 337 + "proc-macro2", 338 + "quote", 339 + "syn", 340 + ] 341 + 342 + [[package]] 343 + name = "serde_json" 344 + version = "1.0.149" 345 + source = "registry+https://github.com/rust-lang/crates.io-index" 346 + checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" 347 + dependencies = [ 348 + "itoa", 349 + "memchr", 350 + "serde", 351 + "serde_core", 352 + "zmij", 353 + ] 354 + 355 + [[package]] 356 + name = "serde_spanned" 357 + version = "1.0.4" 358 + source = "registry+https://github.com/rust-lang/crates.io-index" 359 + checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" 360 + dependencies = [ 361 + "serde_core", 362 + ] 363 + 364 + [[package]] 365 + name = "src-rust" 366 + version = "0.1.0" 367 + dependencies = [ 368 + "cbindgen", 369 + ] 370 + 371 + [[package]] 372 + name = "strsim" 373 + version = "0.11.1" 374 + source = "registry+https://github.com/rust-lang/crates.io-index" 375 + checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 376 + 377 + [[package]] 378 + name = "syn" 379 + version = "2.0.116" 380 + source = "registry+https://github.com/rust-lang/crates.io-index" 381 + checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" 382 + dependencies = [ 383 + "proc-macro2", 384 + "quote", 385 + "unicode-ident", 386 + ] 387 + 388 + [[package]] 389 + name = "tempfile" 390 + version = "3.25.0" 391 + source = "registry+https://github.com/rust-lang/crates.io-index" 392 + checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" 393 + dependencies = [ 394 + "fastrand", 395 + "getrandom", 396 + "once_cell", 397 + "rustix", 398 + "windows-sys", 399 + ] 400 + 401 + [[package]] 402 + name = "toml" 403 + version = "0.9.12+spec-1.1.0" 404 + source = "registry+https://github.com/rust-lang/crates.io-index" 405 + checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" 406 + dependencies = [ 407 + "indexmap", 408 + "serde_core", 409 + "serde_spanned", 410 + "toml_datetime", 411 + "toml_parser", 412 + "toml_writer", 413 + "winnow", 414 + ] 415 + 416 + [[package]] 417 + name = "toml_datetime" 418 + version = "0.7.5+spec-1.1.0" 419 + source = "registry+https://github.com/rust-lang/crates.io-index" 420 + checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" 421 + dependencies = [ 422 + "serde_core", 423 + ] 424 + 425 + [[package]] 426 + name = "toml_parser" 427 + version = "1.0.9+spec-1.1.0" 428 + source = "registry+https://github.com/rust-lang/crates.io-index" 429 + checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" 430 + dependencies = [ 431 + "winnow", 432 + ] 433 + 434 + [[package]] 435 + name = "toml_writer" 436 + version = "1.0.6+spec-1.1.0" 437 + source = "registry+https://github.com/rust-lang/crates.io-index" 438 + checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" 439 + 440 + [[package]] 441 + name = "unicode-ident" 442 + version = "1.0.24" 443 + source = "registry+https://github.com/rust-lang/crates.io-index" 444 + checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" 445 + 446 + [[package]] 447 + name = "unicode-xid" 448 + version = "0.2.6" 449 + source = "registry+https://github.com/rust-lang/crates.io-index" 450 + checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 451 + 452 + [[package]] 453 + name = "utf8parse" 454 + version = "0.2.2" 455 + source = "registry+https://github.com/rust-lang/crates.io-index" 456 + checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 457 + 458 + [[package]] 459 + name = "wasip2" 460 + version = "1.0.2+wasi-0.2.9" 461 + source = "registry+https://github.com/rust-lang/crates.io-index" 462 + checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" 463 + dependencies = [ 464 + "wit-bindgen", 465 + ] 466 + 467 + [[package]] 468 + name = "wasip3" 469 + version = "0.4.0+wasi-0.3.0-rc-2026-01-06" 470 + source = "registry+https://github.com/rust-lang/crates.io-index" 471 + checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" 472 + dependencies = [ 473 + "wit-bindgen", 474 + ] 475 + 476 + [[package]] 477 + name = "wasm-encoder" 478 + version = "0.244.0" 479 + source = "registry+https://github.com/rust-lang/crates.io-index" 480 + checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" 481 + dependencies = [ 482 + "leb128fmt", 483 + "wasmparser", 484 + ] 485 + 486 + [[package]] 487 + name = "wasm-metadata" 488 + version = "0.244.0" 489 + source = "registry+https://github.com/rust-lang/crates.io-index" 490 + checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" 491 + dependencies = [ 492 + "anyhow", 493 + "indexmap", 494 + "wasm-encoder", 495 + "wasmparser", 496 + ] 497 + 498 + [[package]] 499 + name = "wasmparser" 500 + version = "0.244.0" 501 + source = "registry+https://github.com/rust-lang/crates.io-index" 502 + checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" 503 + dependencies = [ 504 + "bitflags", 505 + "hashbrown 0.15.5", 506 + "indexmap", 507 + "semver", 508 + ] 509 + 510 + [[package]] 511 + name = "windows-link" 512 + version = "0.2.1" 513 + source = "registry+https://github.com/rust-lang/crates.io-index" 514 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 515 + 516 + [[package]] 517 + name = "windows-sys" 518 + version = "0.61.2" 519 + source = "registry+https://github.com/rust-lang/crates.io-index" 520 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 521 + dependencies = [ 522 + "windows-link", 523 + ] 524 + 525 + [[package]] 526 + name = "winnow" 527 + version = "0.7.14" 528 + source = "registry+https://github.com/rust-lang/crates.io-index" 529 + checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" 530 + 531 + [[package]] 532 + name = "wit-bindgen" 533 + version = "0.51.0" 534 + source = "registry+https://github.com/rust-lang/crates.io-index" 535 + checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" 536 + dependencies = [ 537 + "wit-bindgen-rust-macro", 538 + ] 539 + 540 + [[package]] 541 + name = "wit-bindgen-core" 542 + version = "0.51.0" 543 + source = "registry+https://github.com/rust-lang/crates.io-index" 544 + checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" 545 + dependencies = [ 546 + "anyhow", 547 + "heck", 548 + "wit-parser", 549 + ] 550 + 551 + [[package]] 552 + name = "wit-bindgen-rust" 553 + version = "0.51.0" 554 + source = "registry+https://github.com/rust-lang/crates.io-index" 555 + checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" 556 + dependencies = [ 557 + "anyhow", 558 + "heck", 559 + "indexmap", 560 + "prettyplease", 561 + "syn", 562 + "wasm-metadata", 563 + "wit-bindgen-core", 564 + "wit-component", 565 + ] 566 + 567 + [[package]] 568 + name = "wit-bindgen-rust-macro" 569 + version = "0.51.0" 570 + source = "registry+https://github.com/rust-lang/crates.io-index" 571 + checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" 572 + dependencies = [ 573 + "anyhow", 574 + "prettyplease", 575 + "proc-macro2", 576 + "quote", 577 + "syn", 578 + "wit-bindgen-core", 579 + "wit-bindgen-rust", 580 + ] 581 + 582 + [[package]] 583 + name = "wit-component" 584 + version = "0.244.0" 585 + source = "registry+https://github.com/rust-lang/crates.io-index" 586 + checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" 587 + dependencies = [ 588 + "anyhow", 589 + "bitflags", 590 + "indexmap", 591 + "log", 592 + "serde", 593 + "serde_derive", 594 + "serde_json", 595 + "wasm-encoder", 596 + "wasm-metadata", 597 + "wasmparser", 598 + "wit-parser", 599 + ] 600 + 601 + [[package]] 602 + name = "wit-parser" 603 + version = "0.244.0" 604 + source = "registry+https://github.com/rust-lang/crates.io-index" 605 + checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" 606 + dependencies = [ 607 + "anyhow", 608 + "id-arena", 609 + "indexmap", 610 + "log", 611 + "semver", 612 + "serde", 613 + "serde_derive", 614 + "serde_json", 615 + "unicode-xid", 616 + "wasmparser", 617 + ] 618 + 619 + [[package]] 620 + name = "zmij" 621 + version = "1.0.21" 622 + source = "registry+https://github.com/rust-lang/crates.io-index" 623 + checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+10
src-rust/Cargo.toml
··· 1 + [package] 2 + name = "src-rust" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [lib] 7 + crate-type = ["cdylib"] 8 + 9 + [build-dependencies] 10 + cbindgen = "0.29.2"
+24
src-rust/build.rs
··· 1 + fn main() { 2 + let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); 3 + let header_path = "bindings/jvm_interop.h"; 4 + cbindgen::Builder::new() 5 + .with_crate(crate_dir.clone()) 6 + .with_language(cbindgen::Language::C) 7 + .generate() 8 + .expect("Unable to generate bindings") 9 + .write_to_file(header_path); 10 + strip_unneeded_includes(header_path); 11 + } 12 + 13 + fn strip_unneeded_includes(header_path: &str) { 14 + // HACK: jextract generates incorrect code unless stdlib and stdarg are excluded 15 + let contents = std::fs::read_to_string(header_path).expect("Unable to read generated header"); 16 + let filtered = contents 17 + .lines() 18 + .filter(|line| { 19 + *line != "#include <stdlib.h>" && *line != "#include <stdarg.h>" 20 + }) 21 + .collect::<Vec<_>>() 22 + .join("\n"); 23 + std::fs::write(header_path, filtered).expect("Unable to write filtered header"); 24 + }
+38
src-rust/src/lib.rs
··· 1 + use std::ffi::c_int; 2 + 3 + #[unsafe(no_mangle)] // FFI is always unsafe. 4 + pub extern "C" fn add(left: u64, right: u64) -> u64 { 5 + left + right 6 + } 7 + 8 + #[repr(C)] 9 + pub struct ExternStruct { 10 + x: c_int, // exposed structs should use C types from std::ffi 11 + y: c_int, 12 + } 13 + 14 + // your code should provide a constructor method... 15 + #[unsafe(no_mangle)] 16 + pub extern "C" fn extern_struct_new(x: c_int, y: c_int) -> *mut ExternStruct { 17 + let s = Box::new(ExternStruct { x, y }); 18 + Box::into_raw(s) 19 + } 20 + 21 + // ...as well as a destructor. 22 + #[unsafe(no_mangle)] 23 + pub extern "C" fn extern_struct_free(s: *mut ExternStruct) { 24 + if !s.is_null() { 25 + unsafe { drop(Box::from_raw(s)) }; // KABOOM! 26 + } 27 + } 28 + 29 + #[cfg(test)] 30 + mod tests { 31 + use super::*; 32 + 33 + #[test] 34 + fn it_works() { 35 + let result = add(2, 2); 36 + assert_eq!(result, 4); 37 + } 38 + }
+1
src-rust/target/.rustc_info.json
··· 1 + {"rustc_fingerprint":7833272153447333061,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.93.0 (254b59607 2026-01-19)\nbinary: rustc\ncommit-hash: 254b59607d4417e9dffbc307138ae5c86280fe4c\ncommit-date: 2026-01-19\nhost: x86_64-unknown-linux-gnu\nrelease: 1.93.0\nLLVM version: 21.1.8\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/nix/store/2w8pppicnsddp3n61ar96cnv3r6iyrdh-rust-mixed\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"11857020428658561806":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/nix/store/2w8pppicnsddp3n61ar96cnv3r6iyrdh-rust-mixed\noff\npacked\nunpacked\n___\ndebug_assertions\nemscripten_wasm_eh\nfmt_debug=\"full\"\noverflow_checks\npanic=\"unwind\"\nproc_macro\nrelocation_model=\"pic\"\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"x87\"\ntarget_has_atomic\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_has_reliable_f128\ntarget_has_reliable_f16\ntarget_has_reliable_f16_math\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nub_checks\nunix\n","stderr":""}},"successes":{}}
+3
src-rust/target/CACHEDIR.TAG
··· 1 + Signature: 8a477f597d28d172789f06886806bc55 2 + # This file is a cache directory tag created by cargo. 3 + # For information about cache directory tags see https://bford.info/cachedir/
src-rust/target/debug/.cargo-lock

This is a binary file and will not be displayed.