Skip to content

Commit c1d7813

Browse files
sundararajanamcimadamore
authored andcommitted
7903121: initial jextract tool code, tests and samples
Reviewed-by: mcimadamore, jvernee
1 parent 91cbf88 commit c1d7813

File tree

401 files changed

+34700
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

401 files changed

+34700
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.gradle
2+
**/build/

Makefile

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
default: all
2+
3+
.NOTPARALLEL:
4+
5+
include make/Common.gmk
6+
7+
JEXTRACT_NATIVE_TEST_DIR ?= $(JEXTRACT_IMAGE_NATIVE_TEST_DIR)
8+
JEXTRACT_TEST_JDK ?= $(JEXTRACT_IMAGE_TEST_JDK_DIR)
9+
JEXTRACT_DIR ?= $(JEXTRACT_IMAGE_DIR)
10+
11+
TEST ?= test
12+
13+
all: bundles
14+
15+
TARGETS += all
16+
17+
18+
image images test-image bundles:
19+
$(MAKE) -f make/Build.gmk $@
20+
21+
TARGETS += image images test-image bundles
22+
23+
24+
verify: test test-integration
25+
26+
TARGETS += verify
27+
28+
29+
test-prebuilt:
30+
@( \
31+
$(MAKE) --no-print-directory -r -R -I make/common/ -f make/RunTestsPrebuilt.gmk \
32+
test-prebuilt $(MAKE_ARGS) \
33+
JEXTRACT_TEST_JDK="$(JEXTRACT_TEST_JDK)" \
34+
JEXTRACT_NATIVE_TEST_DIR="$(JEXTRACT_NATIVE_TEST_DIR)" \
35+
JEXTRACT_DIR="$(JEXTRACT_DIR)" \
36+
TEST="$(TEST)" \
37+
)
38+
39+
TARGETS += test-prebuilt
40+
41+
42+
test: image test-image test-prebuilt
43+
44+
TARGETS += test
45+
46+
clean:
47+
rm -rf $(BUILD_DIR)
48+
49+
TARGETS += clean
50+
51+
52+
.PHONY: default $(TARGETS)

README.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
## Proposal: jextract
1+
## jextract
22

33
`jextract` is a tool that mechanically generates Java bindings from a native library headers. We would like to include this tool, originally developed in the context of [Project Panama](https://openjdk.java.net/projects/panama/) (and available in the Project Panama [Early Access binaries](https://jdk.java.net/panama/)) in the set of tools that are part of the code-tools project.
44

5-
### Rationale
6-
75
The Java SE 18 API defines an [incubating API](https://openjdk.java.net/jeps/419) to:
86

97
* manipulate foreign memory, that is memory which resides *outside* the Java heap; and
@@ -155,3 +153,40 @@ It is easy to see how this mechanism allows developers to look into the set of s
155153

156154
For more examples on how to use the `jextract` tool with real-world libraries, please refer to this [document](https://github.com/openjdk/panama-foreign/blob/d8c0fe5918cb1c6c744eb26797ea4fa04142c237/doc/panama_jextract.md).
157155

156+
157+
### Building jextract tool
158+
159+
jextract depends on clang+LLVM binaries. Please download and install clang+LLVM binaries for your platform.
160+
You can find the prebuilt binaries from [https://releases.llvm.org/download.html](https://releases.llvm.org/download.html). The path of the clang+LLVM installation is provided using the `libclang_home` variable.
161+
162+
Gradle tool needs jdk 17 or below to run. JAVA_HOME should be set to
163+
jdk 17 or below. Or PATH should contain java from jdk 17 or below. jdk18 build is
164+
needed to build jextract which is passed from command with -Pjdk18_home option.
165+
166+
You can download jdk18 early access build from [https://jdk.java.net/18/](https://jdk.java.net/18/)
167+
168+
For Windows, please use gradlew.bat.
169+
170+
```sh
171+
172+
$ sh ./gradlew -Pjdk18_home=<jdk18_home_dir> -Plibclang_home=<libclang_dir> clean verify
173+
174+
```
175+
176+
### Testing jextract tool
177+
178+
jextract tests are written for jtreg test framework. Please download and install jtreg binaries.
179+
The path of the jtreg installation is provided using the `jtreg_home` variable.
180+
181+
For Windows, please use gradlew.bat.
182+
183+
```sh
184+
185+
$ sh ./gradlew -Pjdk18_home=<jdk18_home_dir> -Plibclang_home=<libclang_dir> -Pjtreg_home=<jtreg_dir> clean jtreg
186+
187+
```
188+
189+
### jextract samples
190+
191+
jextract samples can be found "samples" top-level directory. Building/running particular sample may require
192+
specific third-party software installation.

build.gradle

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import org.apache.tools.ant.taskdefs.condition.Os
2+
3+
plugins {
4+
id "java"
5+
// moditect for module-info.class injection and jlink
6+
id "org.moditect.gradleplugin" version "1.0.0-rc3"
7+
// jpackage plugin for packging jextract native app
8+
id "org.panteleyev.jpackageplugin" version "1.3.1"
9+
}
10+
11+
version = '1.0'
12+
13+
def libclang_home = project.property("libclang_home")
14+
def clang_version = new File("${libclang_home}/lib/clang/").list()[0]
15+
16+
def jextract_path
17+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
18+
jextract_path = "$buildDir/jextract/jextract.exe"
19+
} else if (Os.isFamily(Os.FAMILY_MAC)) {
20+
jextract_path = "$buildDir/jextract.app/Contents/MacOS/jextract"
21+
} else {
22+
jextract_path = "$buildDir/jextract/bin/jextract"
23+
}
24+
25+
def clang_include_dir = "${libclang_home}/lib/clang/${clang_version}/include"
26+
def os_lib_dir = Os.isFamily(Os.FAMILY_WINDOWS)? "bin" : "lib"
27+
def libclang_dir = "${libclang_home}/${os_lib_dir}"
28+
29+
repositories {
30+
mavenCentral()
31+
}
32+
33+
dependencies {
34+
implementation "net.sf.jopt-simple:jopt-simple:5.0.4"
35+
}
36+
37+
compileJava {
38+
options.compilerArgs.addAll(['--release', '18'])
39+
options.compilerArgs << "--add-modules=jdk.incubator.foreign"
40+
options.compilerArgs << "-Xlint:all"
41+
options.fork = true
42+
options.forkOptions.executable = "${jdk18_home}/bin/javac"
43+
}
44+
45+
jar {
46+
archiveBaseName = 'jextract'
47+
archiveVersion = project.version
48+
}
49+
50+
moditect {
51+
// moditect uses java.home to find JDK tools
52+
System.setProperty("java.home", "$jdk18_home")
53+
54+
// inject module-info.class for org.openjdk.jextract module
55+
addMainModuleInfo {
56+
dependsOn build
57+
58+
jvmVersion = '18'
59+
version = project.version
60+
module {
61+
moduleInfoSource = '''
62+
module org.openjdk.jextract {
63+
requires transitive java.compiler;
64+
requires transitive jdk.incubator.foreign;
65+
requires jopt.simple;
66+
requires java.prefs;
67+
exports org.openjdk.jextract;
68+
69+
provides java.util.spi.ToolProvider with
70+
org.openjdk.jextract.JextractTool.JextractToolProvider;
71+
}
72+
'''
73+
}
74+
}
75+
76+
// inject module-info.class for jopt.simple module
77+
addDependenciesModuleInfo {
78+
jvmVersion = '18'
79+
outputDirectory = file("$buildDir/modules")
80+
modules {
81+
module {
82+
artifact 'net.sf.jopt-simple:jopt-simple:5.0.4'
83+
moduleInfoSource = '''
84+
module jopt.simple {
85+
exports joptsimple;
86+
exports joptsimple.util;
87+
}
88+
'''
89+
}
90+
}
91+
}
92+
93+
// jlink a JDK image with org.openjdk.jextract & dependent modules only
94+
createRuntimeImage {
95+
onlyIf { !new File("$buildDir/jextract-jdk-image").exists() }
96+
outputDirectory = file("$buildDir/jextract-jdk-image")
97+
modulePath = [file("$buildDir/modules")]
98+
modules = ['org.openjdk.jextract', 'jdk.compiler']
99+
}
100+
}
101+
102+
task copyLibClang(type: Copy) {
103+
dependsOn createRuntimeImage
104+
105+
into("$buildDir")
106+
107+
from("${libclang_dir}") {
108+
include("*clang.*")
109+
include("libLLVM.*")
110+
into("jextract-jdk-image/${os_lib_dir}")
111+
}
112+
113+
from("$clang_include_dir") {
114+
include("*.h")
115+
into("jextract-jdk-image/conf/jextract")
116+
}
117+
}
118+
119+
// jpackage jextract jdk image as a platform dependent native app
120+
jpackage {
121+
dependsOn copyLibClang
122+
onlyIf { !new File(jextract_path).exists() }
123+
124+
appName = "jextract"
125+
runtimeImage = "$buildDir/jextract-jdk-image/"
126+
module = "org.openjdk.jextract/org.openjdk.jextract.JextractTool"
127+
type = "APP_IMAGE"
128+
appVersion = "1.0"
129+
destination = "$buildDir"
130+
javaOptions = [
131+
"--add-modules=jdk.incubator.foreign",
132+
"--enable-native-access=org.openjdk.jextract"
133+
]
134+
winConsole = true
135+
}
136+
137+
// very simple integration test for generated jpackage'd jextract
138+
task verify(type: Exec) {
139+
dependsOn jpackage
140+
141+
executable = "${jextract_path}"
142+
args = [ "test.h", "-d", "$buildDir/integration_test" ]
143+
}
144+
145+
// jlink a JDK image with org.openjdk.jextract for testing
146+
task createRuntimeImageForTest(type: org.moditect.gradleplugin.image.CreateRuntimeImageTask) {
147+
dependsOn verify
148+
149+
onlyIf { !new File("$buildDir/jextract-jdk-test-image").exists() }
150+
outputDirectory = file("$buildDir/jextract-jdk-test-image")
151+
modulePath = [file("$buildDir/modules"),file("$jdk18_home/jmods")]
152+
modules = ['ALL-MODULE-PATH']
153+
}
154+
155+
task prepareTestJDK(type: Copy) {
156+
dependsOn createRuntimeImageForTest
157+
158+
into("$buildDir")
159+
160+
from("${libclang_dir}") {
161+
include("*clang.*")
162+
include("libLLVM.*")
163+
into("jextract-jdk-test-image/${os_lib_dir}")
164+
}
165+
166+
from("$clang_include_dir") {
167+
include("*.h")
168+
into("jextract-jdk-test-image/conf/jextract")
169+
}
170+
}
171+
172+
task cmakeConfigure(type: Exec) {
173+
executable = "cmake"
174+
args = [
175+
"-B", "$buildDir/testlib-build",
176+
"-S", "$projectDir/test/test-support",
177+
"-DTEST_SOURCE_ROOT:FILEPATH=$projectDir/test",
178+
"-DCMAKE_BUILD_TYPE:STRING=Release",
179+
"-DCMAKE_INSTALL_PREFIX:FILEPATH=$buildDir/testlib-install"
180+
]
181+
}
182+
183+
task cmakeBuild(type: Exec) {
184+
dependsOn cmakeConfigure
185+
186+
executable = "cmake"
187+
args = [
188+
"--build", "$buildDir/testlib-build",
189+
"--config", "Release",
190+
"--target", "install"
191+
]
192+
}
193+
194+
// run jtreg tests. Note: needs jtreg_cmd variable set to point to the jtreg
195+
task jtreg(type: JavaExec) {
196+
dependsOn prepareTestJDK,cmakeBuild
197+
198+
workingDir = "$buildDir"
199+
200+
classpath = files(findProperty("jtreg_home") + "/lib/jtreg.jar")
201+
202+
args = [
203+
"-jdk", "$buildDir/jextract-jdk-test-image",
204+
"-nativepath:$buildDir/testlib-install/${os_lib_dir}",
205+
"-javaoption:--enable-native-access=org.openjdk.jextract,ALL-UNNAMED",
206+
"-avm", "-conc:auto", "-verbose:summary",
207+
"../test"
208+
]
209+
}

gradle/wrapper/gradle-wrapper.jar

58.1 KB
Binary file not shown.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
4+
zipStoreBase=GRADLE_USER_HOME
5+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)