Skip to content

Commit a34e1ce

Browse files
committed
Test harness for JNA
1 parent e3918a2 commit a34e1ce

File tree

5 files changed

+304
-155
lines changed

5 files changed

+304
-155
lines changed

libpkl/gradle.lockfile

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ com.github.ajalt.mordant:mordant-markdown-jvm:3.0.1=runtimeClasspath,testRuntime
2222
com.github.ajalt.mordant:mordant-markdown:3.0.1=runtimeClasspath,testRuntimeClasspath
2323
com.github.ajalt.mordant:mordant:3.0.1=apiDependenciesMetadata,compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
2424
net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
25-
net.java.dev.jna:jna:5.14.0=runtimeClasspath,testRuntimeClasspath
25+
net.java.dev.jna:jna-platform:5.17.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
26+
net.java.dev.jna:jna:5.14.0=runtimeClasspath
27+
net.java.dev.jna:jna:5.17.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
2628
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata
2729
org.assertj:assertj-core:3.27.3=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
2830
org.graalvm.polyglot:polyglot:24.1.2=compileClasspath,compileOnlyDependenciesMetadata,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
@@ -57,19 +59,19 @@ org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=kotlinBuildToolsApiClass
5759
org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinCompilerPluginClasspathTestJdk17,kotlinKlibCommonizerClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
5860
org.jetbrains:markdown-jvm:0.7.3=runtimeClasspath,testRuntimeClasspath
5961
org.jetbrains:markdown:0.7.3=runtimeClasspath,testRuntimeClasspath
60-
org.junit.jupiter:junit-jupiter-api:5.12.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
62+
org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
6163
org.junit.jupiter:junit-jupiter-api:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
62-
org.junit.jupiter:junit-jupiter-engine:5.12.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
64+
org.junit.jupiter:junit-jupiter-engine:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
6365
org.junit.jupiter:junit-jupiter-engine:5.8.2=testJdk17RuntimeClasspath
64-
org.junit.jupiter:junit-jupiter-params:5.12.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
66+
org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
6567
org.junit.jupiter:junit-jupiter-params:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
6668
org.junit.jupiter:junit-jupiter:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
67-
org.junit.platform:junit-platform-commons:1.12.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
69+
org.junit.platform:junit-platform-commons:1.12.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
6870
org.junit.platform:junit-platform-commons:1.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
69-
org.junit.platform:junit-platform-engine:1.12.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
71+
org.junit.platform:junit-platform-engine:1.12.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
7072
org.junit.platform:junit-platform-engine:1.8.2=testJdk17RuntimeClasspath
7173
org.junit.platform:junit-platform-launcher:1.8.2=testJdk17RuntimeClasspath
72-
org.junit:junit-bom:5.12.1=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
74+
org.junit:junit-bom:5.11.4=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
7375
org.junit:junit-bom:5.8.2=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath
7476
org.msgpack:msgpack-core:0.9.8=compileClasspath,implementationDependenciesMetadata,runtimeClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
7577
org.opentest4j:opentest4j:1.2.0=testJdk17CompileClasspath,testJdk17ImplementationDependenciesMetadata,testJdk17RuntimeClasspath

libpkl/libpkl.gradle.kts

Lines changed: 142 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ dependencies {
4444
implementation(libs.truffleRuntime)
4545

4646
testImplementation(projects.pklCommonsTest)
47+
testImplementation("net.java.dev.jna:jna:5.17.0")
48+
testImplementation("net.java.dev.jna:jna-platform:5.17.0")
4749

4850
fun sharedLibrary(osAndArch: String) = files(nativeLibraryOutputFiles(osAndArch))
4951

@@ -121,137 +123,138 @@ private fun NativeImageBuild.setClasspath() {
121123
}
122124

123125
val macNativeLibraryAmd64 by
124-
tasks.registering(NativeImageBuild::class) {
125-
outputDir = project.layout.buildDirectory.dir("libs/macos-amd64")
126-
imageName = executableSpec.name.map { "$it-macos-amd64" }
127-
mainClass = executableSpec.mainClass
128-
amd64()
129-
setClasspath()
130-
extraNativeImageArgs = listOf("--shared")
131-
132-
setOutputFiles("macos-amd64")
133-
}
126+
tasks.registering(NativeImageBuild::class) {
127+
outputDir = project.layout.buildDirectory.dir("libs/macos-amd64")
128+
imageName = executableSpec.name.map { "$it-macos-amd64" }
129+
mainClass = executableSpec.mainClass
130+
amd64()
131+
setClasspath()
132+
extraNativeImageArgs = listOf("--shared")
133+
134+
setOutputFiles("macos-amd64")
135+
}
134136

135137
val macNativeLibraryAarch64 by
136-
tasks.registering(NativeImageBuild::class) {
137-
outputDir = project.layout.buildDirectory.dir("libs/macos-aarch64")
138-
imageName = executableSpec.name.map { "$it-macos-aarch64" }
139-
mainClass = executableSpec.mainClass
140-
aarch64()
141-
setClasspath()
142-
extraNativeImageArgs = listOf("--shared")
143-
144-
setOutputFiles("macos-aarch64")
145-
}
138+
tasks.registering(NativeImageBuild::class) {
139+
outputDir = project.layout.buildDirectory.dir("libs/macos-aarch64")
140+
imageName = executableSpec.name.map { "$it-macos-aarch64" }
141+
mainClass = executableSpec.mainClass
142+
aarch64()
143+
setClasspath()
144+
extraNativeImageArgs = listOf("--shared")
145+
146+
setOutputFiles("macos-aarch64")
147+
}
146148

147149
val linuxNativeLibraryAmd64 by
148-
tasks.registering(NativeImageBuild::class) {
149-
outputDir = project.layout.buildDirectory.dir("libs/linux-amd64")
150-
imageName = executableSpec.name.map { "$it-linux-amd64" }
151-
mainClass = executableSpec.mainClass
152-
amd64()
153-
setClasspath()
154-
extraNativeImageArgs = listOf("--shared")
155-
156-
setOutputFiles("linux-amd64")
157-
}
150+
tasks.registering(NativeImageBuild::class) {
151+
outputDir = project.layout.buildDirectory.dir("libs/linux-amd64")
152+
imageName = executableSpec.name.map { "$it-linux-amd64" }
153+
mainClass = executableSpec.mainClass
154+
amd64()
155+
setClasspath()
156+
extraNativeImageArgs = listOf("--shared")
157+
158+
setOutputFiles("linux-amd64")
159+
}
158160

159161
val linuxNativeLibraryAarch64 by
160-
tasks.registering(NativeImageBuild::class) {
161-
outputDir = project.layout.buildDirectory.dir("libs/linux-aarch64")
162-
imageName = executableSpec.name.map { "$it-linux-aarch64" }
163-
mainClass = executableSpec.mainClass
164-
aarch64()
165-
setClasspath()
166-
167-
extraNativeImageArgs =
168-
listOf(
169-
"--shared",
170-
// Ensure compatibility for kernels with page size set to 4k, 16k and 64k
171-
// (e.g. Raspberry Pi 5, Asahi Linux)
172-
"-H:PageSize=65536",
173-
)
162+
tasks.registering(NativeImageBuild::class) {
163+
outputDir = project.layout.buildDirectory.dir("libs/linux-aarch64")
164+
imageName = executableSpec.name.map { "$it-linux-aarch64" }
165+
mainClass = executableSpec.mainClass
166+
aarch64()
167+
setClasspath()
168+
169+
extraNativeImageArgs =
170+
listOf(
171+
"--shared",
172+
// Ensure compatibility for kernels with page size set to 4k, 16k and 64k
173+
// (e.g. Raspberry Pi 5, Asahi Linux)
174+
"-H:PageSize=65536",
175+
)
174176

175-
setOutputFiles("linux-aarch64")
176-
}
177+
setOutputFiles("linux-aarch64")
178+
}
177179

178180
val alpineNativeLibraryAmd64 by
179-
tasks.registering(NativeImageBuild::class) {
180-
outputDir = project.layout.buildDirectory.dir("libs/alpine-linux-amd64")
181-
imageName = executableSpec.name.map { "$it-alpine-linux-amd64" }
182-
mainClass = executableSpec.mainClass
183-
amd64()
184-
setClasspath()
185-
186-
extraNativeImageArgs =
187-
listOf(
188-
"--shared",
189-
// TODO(kushal): https://github.com/oracle/graal/issues/3053
190-
"--libc=musl",
191-
)
181+
tasks.registering(NativeImageBuild::class) {
182+
outputDir = project.layout.buildDirectory.dir("libs/alpine-linux-amd64")
183+
imageName = executableSpec.name.map { "$it-alpine-linux-amd64" }
184+
mainClass = executableSpec.mainClass
185+
amd64()
186+
setClasspath()
187+
188+
extraNativeImageArgs =
189+
listOf(
190+
"--shared",
191+
// TODO(kushal): https://github.com/oracle/graal/issues/3053
192+
"--libc=musl",
193+
)
192194

193-
setOutputFiles("alpine-linux-amd64")
194-
}
195+
setOutputFiles("alpine-linux-amd64")
196+
}
195197

196198
val windowsNativeLibraryAmd64 by
197-
tasks.registering(NativeImageBuild::class) {
198-
outputDir = project.layout.buildDirectory.dir("libs/windows-amd64")
199-
imageName = executableSpec.name.map { "$it-windows-amd64" }
200-
mainClass = executableSpec.mainClass
201-
amd64()
202-
setClasspath()
203-
extraNativeImageArgs = listOf("--shared", "-Dfile.encoding=UTF-8")
204-
205-
setOutputFiles("windows-amd64")
206-
}
199+
tasks.registering(NativeImageBuild::class) {
200+
outputDir = project.layout.buildDirectory.dir("libs/windows-amd64")
201+
imageName = executableSpec.name.map { "$it-windows-amd64" }
202+
mainClass = executableSpec.mainClass
203+
amd64()
204+
setClasspath()
205+
extraNativeImageArgs = listOf("--shared", "-Dfile.encoding=UTF-8")
206+
207+
setOutputFiles("windows-amd64")
208+
}
207209

208210
val assembleNative by
209-
tasks.existing {
210-
// TODO(kushal): Remove this later. Only exists to debug output files are in the graph.
211-
finalizedBy(validateNativeLibraryFilestasks)
212-
}
211+
tasks.existing {
212+
// TODO(kushal): Remove this later. Only exists to debug output files are in the graph.
213+
finalizedBy(validateNativeLibraryFilestasks)
214+
}
213215

214216
// TODO(kushal): Remove this later. Only exists to debug output files are in the graph.
215-
val validateNativeLibraryFilestasks by tasks.registering {
216-
val assembleTasks = mutableSetOf<TaskProvider<NativeImageBuild>>()
217-
218-
when {
219-
buildInfo.os.isMacOsX -> {
220-
assembleTasks.add(macNativeLibraryAmd64)
221-
if (buildInfo.arch == "aarch64") {
222-
assembleTasks.add(macNativeLibraryAarch64)
217+
val validateNativeLibraryFilestasks by
218+
tasks.registering {
219+
val assembleTasks = mutableSetOf<TaskProvider<NativeImageBuild>>()
220+
221+
when {
222+
buildInfo.os.isMacOsX -> {
223+
assembleTasks.add(macNativeLibraryAmd64)
224+
if (buildInfo.arch == "aarch64") {
225+
assembleTasks.add(macNativeLibraryAarch64)
226+
}
223227
}
224-
}
225228

226-
buildInfo.os.isWindows -> {
227-
assembleTasks.add(windowsNativeLibraryAmd64)
228-
}
229+
buildInfo.os.isWindows -> {
230+
assembleTasks.add(windowsNativeLibraryAmd64)
231+
}
229232

230-
buildInfo.os.isLinux && buildInfo.arch == "aarch64" -> {
231-
assembleTasks.add(linuxNativeLibraryAarch64)
232-
}
233+
buildInfo.os.isLinux && buildInfo.arch == "aarch64" -> {
234+
assembleTasks.add(linuxNativeLibraryAarch64)
235+
}
233236

234-
buildInfo.os.isLinux && buildInfo.arch == "amd64" -> {
235-
assembleTasks.add(linuxNativeLibraryAmd64)
236-
if (buildInfo.hasMuslToolchain) {
237-
assembleTasks.add(alpineNativeLibraryAmd64)
237+
buildInfo.os.isLinux && buildInfo.arch == "amd64" -> {
238+
assembleTasks.add(linuxNativeLibraryAmd64)
239+
if (buildInfo.hasMuslToolchain) {
240+
assembleTasks.add(alpineNativeLibraryAmd64)
241+
}
238242
}
239243
}
240-
}
241244

242-
dependsOn(assembleTasks)
245+
dependsOn(assembleTasks)
243246

244-
doLast {
245-
for (taskProvider in assembleTasks) {
246-
val task = taskProvider.get()
247-
val outputFiles = task.outputs.files.files
247+
doLast {
248+
for (taskProvider in assembleTasks) {
249+
val task = taskProvider.get()
250+
val outputFiles = task.outputs.files.files
248251

249-
println("==== Validating Native Library Files Exist ====")
250-
println("${task.name} outputs:")
251-
outputFiles.forEach { file -> println("- ${file.absolutePath} (exists: ${file.exists()})") }
252+
println("==== Validating Native Library Files Exist ====")
253+
println("${task.name} outputs:")
254+
outputFiles.forEach { file -> println("- ${file.absolutePath} (exists: ${file.exists()})") }
255+
}
252256
}
253257
}
254-
}
255258

256259
// Expose underlying task's outputs
257260
private fun <T : Task> Task.wraps(other: TaskProvider<T>) {
@@ -271,31 +274,46 @@ val assembleNativeAlpineLinuxAmd64 by tasks.existing { wraps(alpineNativeLibrary
271274

272275
val assembleNativeWindowsAmd64 by tasks.existing { wraps(windowsNativeLibraryAmd64) }
273276

274-
val macNativeFullLibraryAarch64 by tasks.registering(Exec::class) {
275-
dependsOn(macNativeLibraryAarch64)
277+
val macNativeFullLibraryAarch64 by
278+
tasks.registering(Exec::class) {
279+
dependsOn(macNativeLibraryAarch64)
280+
281+
val libraryOutputDir = project.layout.buildDirectory.dir("libs/macos-aarch64").get()
282+
val projectDir = project.layout.projectDirectory.asFile.path
283+
284+
workingDir = libraryOutputDir.asFile
285+
286+
// TODO: Make this portable.
287+
commandLine(
288+
"/usr/bin/cc",
289+
"-shared",
290+
"-o",
291+
"libpkl.dylib",
292+
"$projectDir/src/main/c/libpkl.c",
293+
"-I$projectDir/src/main/c",
294+
"-I$libraryOutputDir",
295+
"-L$libraryOutputDir",
296+
"-lpkl-internal-macos-aarch64",
297+
)
298+
}
276299

277-
val libraryOutputDir = project.layout.buildDirectory.dir("libs/macos-aarch64").get()
278-
val projectDir = project.layout.projectDirectory.asFile.path
300+
val macNativeFullLibraryAarch64Copy by
301+
tasks.registering(Exec::class) {
302+
dependsOn(macNativeFullLibraryAarch64)
279303

280-
workingDir = libraryOutputDir.asFile
304+
val libraryOutputDir = project.layout.buildDirectory.dir("libs/macos-aarch64").get()
305+
val projectDir = project.layout.projectDirectory.asFile.path
281306

282-
// TODO: Make this portable.
283-
commandLine("/usr/bin/cc", "-shared",
284-
"-o", "libpkl.dylib",
285-
"$projectDir/src/main/c/libpkl.c",
286-
"-I$projectDir/src/main/c",
287-
"-I$libraryOutputDir",
288-
"-L$libraryOutputDir",
289-
"-lpkl-internal-macos-aarch64")
290-
}
307+
workingDir = libraryOutputDir.asFile
291308

292-
val macNativeFullLibraryAarch64Copy by tasks.registering(Exec::class) {
293-
dependsOn(macNativeFullLibraryAarch64)
309+
commandLine("cp", "$projectDir/src/main/c/libpkl.h", libraryOutputDir)
310+
}
294311

295-
val libraryOutputDir = project.layout.buildDirectory.dir("libs/macos-aarch64").get()
296-
val projectDir = project.layout.projectDirectory.asFile.path
312+
tasks.withType<Test> {
313+
dependsOn(macNativeFullLibraryAarch64Copy)
297314

298-
workingDir = libraryOutputDir.asFile
315+
val nativeLibsDir = project.layout.buildDirectory.dir("libs/macos-aarch64").get().asFile
316+
jvmArgs("-Djna.library.path=${nativeLibsDir.absolutePath}")
299317

300-
commandLine("cp", "$projectDir/src/main/c/libpkl.h", libraryOutputDir)
318+
useJUnitPlatform()
301319
}

libpkl/src/main/c/libpkl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ int pkl_close() {
5656

5757
pkl_internal_server_stop(isolatethread);
5858
pkl_internal_close(isolatethread);
59+
isolatethread = NULL;
5960

6061
if (pthread_mutex_unlock(&graal_mutex) != 0) {
6162
return -1;

libpkl/src/main/c/libpkl.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,7 @@
1-
/**
2-
* @brief The Pkl Message Response Handler that a user should implement.
3-
*
4-
* The resulting messages from `pkl_send` will be sent to this
5-
* handler using a callback style.
6-
*/
71
typedef void (*PklMessageResponseHandler)(int length, char* message);
82

9-
/**
10-
* @brief Initialises and allocates a Pkl executor.
11-
*
12-
* @return -1 on failure.
13-
* @return 0 on success.
14-
*/
153
int pkl_init(PklMessageResponseHandler handler);
164

17-
/**
18-
* @brief Send a message to Pkl, providing the length and a pointer to the first byte.
19-
*
20-
* @return -1 on failure.
21-
* @return 0 on success.
22-
*/
235
int pkl_send_message(int length, char* message);
246

25-
/**
26-
* @brief Cleans up any resources that were created as part of the `pkl_init` process.
27-
*
28-
* @return -1 on failure.
29-
* @return 0 on success.
30-
*/
317
int pkl_close();

0 commit comments

Comments
 (0)