diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aa5814c..a3af252 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,10 +6,10 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 20 uses: actions/setup-java@v3 with: - java-version: '17' + java-version: '20' distribution: 'temurin' - name: Build with Gradle uses: gradle/gradle-build-action@v2 diff --git a/.github/workflows/graal.yml b/.github/workflows/graal.yml index 8a670fb..ad19766 100644 --- a/.github/workflows/graal.yml +++ b/.github/workflows/graal.yml @@ -9,7 +9,7 @@ jobs: - name: Set up GraalVM uses: graalvm/setup-graalvm@v1 with: - java-version: '17' + java-version: '20' distribution: 'graalvm' - name: Build with Gradle uses: gradle/gradle-build-action@v2 @@ -33,7 +33,7 @@ jobs: - name: Set up GraalVM uses: graalvm/setup-graalvm@v1 with: - java-version: '17' + java-version: '20' distribution: 'graalvm' - name: Build with Gradle uses: gradle/gradle-build-action@v2 @@ -57,7 +57,7 @@ jobs: - name: Set up GraalVM uses: graalvm/setup-graalvm@v1 with: - java-version: '17' + java-version: '20' distribution: 'graalvm' - name: Build with Gradle uses: gradle/gradle-build-action@v2 diff --git a/build.gradle.kts b/build.gradle.kts index 684b6a1..040c458 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,7 @@ plugins { - kotlin("jvm") version "1.9.10" apply false - kotlin("plugin.serialization") version "1.9.10" apply false + id("gay.pizza.pork.root") } tasks.withType { - gradleVersion = "8.3" + gradleVersion = "8.4-rc-1" } diff --git a/buildext/build.gradle.kts b/buildext/build.gradle.kts index 05ffc7e..ec781de 100644 --- a/buildext/build.gradle.kts +++ b/buildext/build.gradle.kts @@ -1,4 +1,5 @@ -@file:Suppress("UnstableApiUsage") +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { `kotlin-dsl` embeddedKotlin("plugin.serialization") @@ -10,14 +11,31 @@ repositories { } dependencies { - implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10") - implementation("org.jetbrains.kotlin:kotlin-serialization:1.9.10") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20-Beta2") + implementation("org.jetbrains.kotlin:kotlin-serialization:1.9.20-Beta2") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") implementation("com.charleskorn.kaml:kaml:0.55.0") } +java { + sourceCompatibility = JavaVersion.VERSION_20 + targetCompatibility = JavaVersion.VERSION_20 +} + +tasks.withType { + kotlinOptions.jvmTarget = "20" +} + gradlePlugin { plugins { + create("pork_root") { + id = "gay.pizza.pork.root" + implementationClass = "gay.pizza.pork.buildext.PorkRootPlugin" + + displayName = "Pork Root" + description = "Root convention for pork" + } + create("pork_ast") { id = "gay.pizza.pork.ast" implementationClass = "gay.pizza.pork.buildext.PorkAstPlugin" diff --git a/buildext/src/main/kotlin/gay/pizza/pork/buildext/PorkModulePlugin.kt b/buildext/src/main/kotlin/gay/pizza/pork/buildext/PorkModulePlugin.kt index d69105b..9153f3e 100644 --- a/buildext/src/main/kotlin/gay/pizza/pork/buildext/PorkModulePlugin.kt +++ b/buildext/src/main/kotlin/gay/pizza/pork/buildext/PorkModulePlugin.kt @@ -5,6 +5,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaPluginExtension import org.gradle.kotlin.dsl.* +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile open class PorkModulePlugin : Plugin { @@ -16,13 +17,17 @@ open class PorkModulePlugin : Plugin { target.repositories.maven(url = "https://gitlab.com/api/v4/projects/49101454/packages/maven") target.extensions.getByType().apply { - val javaVersion = JavaVersion.toVersion(17) + val javaVersion = JavaVersion.toVersion(21) sourceCompatibility = javaVersion targetCompatibility = javaVersion } target.tasks.withType { - kotlinOptions.jvmTarget = "17" + kotlinOptions.jvmTarget = "21" + } + + target.extensions.getByType().apply { + jvmToolchain(21) } target.dependencies { diff --git a/buildext/src/main/kotlin/gay/pizza/pork/buildext/PorkRootPlugin.kt b/buildext/src/main/kotlin/gay/pizza/pork/buildext/PorkRootPlugin.kt new file mode 100644 index 0000000..1c7150f --- /dev/null +++ b/buildext/src/main/kotlin/gay/pizza/pork/buildext/PorkRootPlugin.kt @@ -0,0 +1,8 @@ +package gay.pizza.pork.buildext + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class PorkRootPlugin : Plugin { + override fun apply(target: Project) {} +} diff --git a/ffi/build.gradle.kts b/ffi/build.gradle.kts index a33eb75..637c795 100644 --- a/ffi/build.gradle.kts +++ b/ffi/build.gradle.kts @@ -7,5 +7,4 @@ dependencies { api(project(":evaluator")) implementation(project(":common")) - implementation("net.java.dev.jna:jna:5.13.0") } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiFunctionDefinition.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiFunctionDefinition.kt index 176f618..82f000b 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiFunctionDefinition.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiFunctionDefinition.kt @@ -30,7 +30,10 @@ class FfiFunctionDefinition( library, functionName, returnType, - parameterString.split(",").map { it.trim() } + parameterString.splitToSequence(",") + .map { it.trim() } + .filter { it.isNotEmpty() } + .toList() ) } } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiLibraryCache.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiLibraryCache.kt new file mode 100644 index 0000000..edda80e --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiLibraryCache.kt @@ -0,0 +1,46 @@ +package gay.pizza.pork.ffi + +import java.lang.foreign.* + +object FfiLibraryCache { + private val dlopenFunctionDescriptor = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT) + private val dlsymFunctionDescriptor = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS) + + private val dlopenMemorySegment = Linker.nativeLinker().defaultLookup().find("dlopen").orElseThrow() + private val dlsymMemorySegment = Linker.nativeLinker().defaultLookup().find("dlsym").orElseThrow() + + private val dlopen = Linker.nativeLinker().downcallHandle( + dlopenMemorySegment, + dlopenFunctionDescriptor + ) + + private val dlsym = Linker.nativeLinker().downcallHandle( + dlsymMemorySegment, + dlsymFunctionDescriptor + ) + + private val libraryHandles = mutableMapOf() + + private fun dlopen(name: String): MemorySegment { + var handle = libraryHandles[name] + if (handle != null) { + return handle + } + return Arena.ofConfined().use { arena -> + val nameStringPointer = arena.allocateUtf8String(name) + handle = dlopen.invokeExact(nameStringPointer, 0) as MemorySegment + if (handle == MemorySegment.NULL) { + throw RuntimeException("Unable to dlopen library: $name") + } + handle!! + } + } + + fun dlsym(name: String, symbol: String): MemorySegment { + val libraryHandle = dlopen(name) + return Arena.ofConfined().use { arena -> + val symbolStringPointer = arena.allocateUtf8String(symbol) + dlsym.invokeExact(libraryHandle, symbolStringPointer) as MemorySegment + } + } +} diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiMacPlatform.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiMacPlatform.kt new file mode 100644 index 0000000..9a24c22 --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiMacPlatform.kt @@ -0,0 +1,25 @@ +package gay.pizza.pork.ffi + +import java.nio.file.Path +import kotlin.io.path.* + +object FfiMacPlatform : FfiPlatform { + private val frameworksDirectories = listOf( + "/Library/Frameworks" + ) + + override fun findLibrary(name: String): Path? { + val frameworksToCheck = frameworksDirectories.map { frameworkDirectory -> + Path("$frameworkDirectory/$name.framework/$name") + } + for (framework in frameworksToCheck) { + if (!framework.exists()) continue + return if (framework.isSymbolicLink()) { + return framework.parent.resolve(framework.readSymbolicLink()).absolute() + } else { + framework.absolute() + } + } + return null + } +} diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiNativeProvider.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiNativeProvider.kt new file mode 100644 index 0000000..79e67ab --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiNativeProvider.kt @@ -0,0 +1,79 @@ +package gay.pizza.pork.ffi + +import gay.pizza.pork.ast.ArgumentSpec +import gay.pizza.pork.evaluator.CallableFunction +import gay.pizza.pork.evaluator.NativeProvider +import gay.pizza.pork.evaluator.None +import java.lang.foreign.* +import java.nio.file.Path +import kotlin.io.path.Path +import kotlin.io.path.absolutePathString +import kotlin.io.path.exists + +class FfiNativeProvider : NativeProvider { + private val ffiTypeRegistry = FfiTypeRegistry() + + override fun provideNativeFunction(definitions: List, arguments: List): CallableFunction { + val functionDefinition = FfiFunctionDefinition.parse(definitions[0], definitions[1]) + val linker = Linker.nativeLinker() + val functionAddress = lookupSymbol(functionDefinition) + + val parameters = functionDefinition.parameters.map { id -> + ffiTypeRegistry.lookup(id) ?: throw RuntimeException("Unknown ffi type: $id") + } + + val returnTypeId = functionDefinition.returnType + val returnType = ffiTypeRegistry.lookup(returnTypeId) ?: + throw RuntimeException("Unknown ffi return type: $returnTypeId") + val parameterArray = parameters.map { typeAsLayout(it) }.toTypedArray() + val descriptor = if (returnType == FfiPrimitiveType.Void) + FunctionDescriptor.ofVoid(*parameterArray) + else FunctionDescriptor.of(typeAsLayout(returnType), *parameterArray) + val handle = linker.downcallHandle(functionAddress, descriptor) + return CallableFunction { functionArguments, _ -> + Arena.ofConfined().use { arena -> + handle.invokeWithArguments(functionArguments.map { valueAsFfi(it, arena) }) ?: None + } + } + } + + private fun lookupSymbol(functionDefinition: FfiFunctionDefinition): MemorySegment { + if (functionDefinition.library == "c") { + return SymbolLookup.loaderLookup().find(functionDefinition.function).orElseThrow { + RuntimeException("Unknown function: ${functionDefinition.function}") + } + } + val actualLibraryPath = findLibraryPath(functionDefinition.library) + val functionAddress = FfiLibraryCache.dlsym(actualLibraryPath.absolutePathString(), functionDefinition.function) + if (functionAddress.address() == 0L) { + throw RuntimeException("Unknown function: ${functionDefinition.function} in library $actualLibraryPath") + } + return functionAddress + } + + private fun typeAsLayout(type: FfiType): MemoryLayout = when (type) { + FfiPrimitiveType.UnsignedByte, FfiPrimitiveType.Byte -> ValueLayout.JAVA_BYTE + FfiPrimitiveType.UnsignedInt, FfiPrimitiveType.Int -> ValueLayout.JAVA_INT + FfiPrimitiveType.UnsignedShort, FfiPrimitiveType.Short -> ValueLayout.JAVA_SHORT + FfiPrimitiveType.UnsignedLong, FfiPrimitiveType.Long -> ValueLayout.JAVA_LONG + FfiPrimitiveType.String -> ValueLayout.ADDRESS + FfiPrimitiveType.Pointer -> ValueLayout.ADDRESS + FfiPrimitiveType.Void -> MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT) + else -> throw RuntimeException("Unknown ffi type to convert to memory layout: $type") + } + + private fun valueAsFfi(value: Any, allocator: SegmentAllocator): Any = when { + value is String -> allocator.allocateUtf8String(value) + value == None -> MemorySegment.NULL + else -> value + } + + private fun findLibraryPath(name: String): Path { + val initialPath = Path(name) + if (initialPath.exists()) { + return initialPath + } + return FfiPlatforms.current.platform.findLibrary(name) + ?: throw RuntimeException("Unable to find library: $name") + } +} diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPlatform.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPlatform.kt new file mode 100644 index 0000000..c60a82e --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPlatform.kt @@ -0,0 +1,24 @@ +package gay.pizza.pork.ffi + +import java.nio.file.Path + +enum class FfiPlatforms(val id: String, val platform: FfiPlatform) { + Mac("macOS", FfiMacPlatform), + Windows("Windows", FfiWindowsPlatform), + Unix("Unix", FfiUnixPlatform); + + companion object { + val current by lazy { + val operatingSystemName = System.getProperty("os.name").lowercase() + when { + operatingSystemName.contains("win") -> Windows + operatingSystemName.contains("mac") -> Mac + else -> Unix + } + } + } +} + +interface FfiPlatform { + fun findLibrary(name: String): Path? +} diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPrimitiveType.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPrimitiveType.kt index 3464aea..5f03d98 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPrimitiveType.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiPrimitiveType.kt @@ -1,10 +1,11 @@ package gay.pizza.pork.ffi import gay.pizza.pork.evaluator.None +import java.lang.foreign.MemorySegment enum class FfiPrimitiveType( val id: kotlin.String, - override val size: kotlin.Int, + override val size: kotlin.Long, val numberConvert: (Number.() -> Number)? = null, val nullableConversion: (Any?.() -> Any)? = null, val notNullConversion: (Any.() -> Any)? = null @@ -22,9 +23,10 @@ enum class FfiPrimitiveType( String("char*", 8, nullableConversion = { toString() }), Pointer("void*", 8, nullableConversion = { if (this is kotlin.Long) { - com.sun.jna.Pointer(this) + MemorySegment.ofAddress(this) } else if (this == None) { - com.sun.jna.Pointer.NULL - } else this as com.sun.jna.Pointer - }) + MemorySegment.NULL + } else this as MemorySegment + }), + Void("void", 0) } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiStruct.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiStruct.kt index 58109fe..e9cdf8b 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiStruct.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiStruct.kt @@ -9,6 +9,6 @@ class FfiStruct : FfiType { fields.add(FfiStructField(field, type)) } - override val size: Int + override val size: Long get() = fields.sumOf { it.type.size } } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiType.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiType.kt index 55ab5a7..e61710a 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiType.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiType.kt @@ -1,5 +1,5 @@ package gay.pizza.pork.ffi interface FfiType { - val size: Int + val size: Long } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiTypeRegistry.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiTypeRegistry.kt new file mode 100644 index 0000000..486ed0f --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiTypeRegistry.kt @@ -0,0 +1,18 @@ +package gay.pizza.pork.ffi + +class FfiTypeRegistry { + private val types = mutableMapOf() + + init { + for (type in FfiPrimitiveType.entries) { + add(type.id, type) + } + add("size_t", FfiPrimitiveType.Long) + } + + fun add(name: String, type: FfiType) { + types[name] = type + } + + fun lookup(name: String): FfiType? = types[name] +} diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiUnixPlatform.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiUnixPlatform.kt new file mode 100644 index 0000000..910c80d --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiUnixPlatform.kt @@ -0,0 +1,7 @@ +package gay.pizza.pork.ffi + +import java.nio.file.Path + +object FfiUnixPlatform : FfiPlatform { + override fun findLibrary(name: String): Path? = null +} diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiWindowsPlatform.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiWindowsPlatform.kt new file mode 100644 index 0000000..77a8409 --- /dev/null +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiWindowsPlatform.kt @@ -0,0 +1,7 @@ +package gay.pizza.pork.ffi + +import java.nio.file.Path + +object FfiWindowsPlatform : FfiPlatform { + override fun findLibrary(name: String): Path? = null +} diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JnaNativeProvider.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JnaNativeProvider.kt deleted file mode 100644 index 8413d76..0000000 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JnaNativeProvider.kt +++ /dev/null @@ -1,93 +0,0 @@ -package gay.pizza.pork.ffi - -import com.sun.jna.Function -import com.sun.jna.NativeLibrary -import gay.pizza.pork.ast.ArgumentSpec -import gay.pizza.pork.evaluator.CallableFunction -import gay.pizza.pork.evaluator.NativeProvider -import gay.pizza.pork.evaluator.None - -class JnaNativeProvider : NativeProvider { - override fun provideNativeFunction(definitions: List, arguments: List): CallableFunction { - val functionDefinition = FfiFunctionDefinition.parse(definitions[0], definitions[1]) - val library = NativeLibrary.getInstance(functionDefinition.library) - val function = library.getFunction(functionDefinition.function) - ?: throw RuntimeException("Failed to find function ${functionDefinition.function} in library ${functionDefinition.library}") - return CallableFunction { functionArgs, _ -> - val ffiArgs = mutableListOf() - for ((index, spec) in arguments.withIndex()) { - val ffiType = functionDefinition.parameters[index] - if (spec.multiple) { - val variableArguments = functionArgs - .subList(index, functionArgs.size) - ffiArgs.addAll(variableArguments) - break - } else { - val converted = convert(ffiType, functionArgs[index]) - ffiArgs.add(converted) - } - } - invoke(function, ffiArgs.toTypedArray(), functionDefinition.returnType) - } - } - - private fun invoke(function: Function, values: Array, type: String): Any = when (rewriteType(type)) { - "void*" -> function.invokePointer(values) - "int" -> function.invokeInt(values) - "long" -> function.invokeLong(values) - "float" -> function.invokeFloat(values) - "double" -> function.invokeDouble(values) - "void" -> function.invokeVoid(values) - "char*" -> function.invokeString(values, false) - else -> throw RuntimeException("Unsupported ffi return type: $type") - } ?: None - - private fun rewriteType(type: String): String = when (type) { - "size_t" -> "long" - else -> type - } - - private fun convert(type: String, value: Any?): Any? { - val rewritten = rewriteType(type) - val primitive = FfiPrimitiveType.entries.firstOrNull { it.id == rewritten } - ?: throw RuntimeException("Unsupported ffi type: $type") - if (primitive.numberConvert != null) { - return numberConvert(type, value, primitive.numberConvert) - } - - if (primitive.notNullConversion != null) { - return notNullConvert(type, value, primitive.notNullConversion) - } - - if (primitive.nullableConversion != null) { - return nullableConvert(value, primitive.nullableConversion) - } - - return value - } - - private fun notNullConvert(type: String, value: Any?, into: Any.() -> T): T { - if (value == null) { - throw RuntimeException("Null values cannot be used for converting to type $type") - } - return into(value) - } - - private fun nullableConvert(value: Any?, into: Any.() -> T): T? { - if (value == null || value == None) { - return null - } - return into(value) - } - - private fun numberConvert(type: String, value: Any?, into: Number.() -> T): T { - if (value == null || value == None) { - throw RuntimeException("Null values cannot be used for converting to numeric type $type") - } - - if (value !is Number) { - throw RuntimeException("Cannot convert value '$value' into type $type") - } - return into(value) - } -} diff --git a/ffi/src/main/resources/META-INF/native-image/gay/pizza/pork/ffi/jni-config.json b/ffi/src/main/resources/META-INF/native-image/gay/pizza/pork/ffi/jni-config.json deleted file mode 100644 index 36bccf4..0000000 --- a/ffi/src/main/resources/META-INF/native-image/gay/pizza/pork/ffi/jni-config.json +++ /dev/null @@ -1,653 +0,0 @@ -[ - { - "name": "[Z" - }, - { - "name": "com.sun.jna.Callback" - }, - { - "name": "com.sun.jna.CallbackReference", - "methods": [ - { - "name": "getCallback", - "parameterTypes": [ - "java.lang.Class", - "com.sun.jna.Pointer", - "boolean" - ] - }, - { - "name": "getFunctionPointer", - "parameterTypes": [ - "com.sun.jna.Callback", - "boolean" - ] - }, - { - "name": "getNativeString", - "parameterTypes": [ - "java.lang.Object", - "boolean" - ] - }, - { - "name": "initializeThread", - "parameterTypes": [ - "com.sun.jna.Callback", - "com.sun.jna.CallbackReference$AttachOptions" - ] - } - ] - }, - { - "name": "com.sun.jna.CallbackReference$AttachOptions" - }, - { - "name": "com.sun.jna.FromNativeConverter", - "methods": [ - { - "name": "nativeType", - "parameterTypes": [] - } - ] - }, - { - "name": "com.sun.jna.IntegerType", - "fields": [ - { - "name": "value" - } - ] - }, - { - "name": "com.sun.jna.JNIEnv" - }, - { - "name": "com.sun.jna.Native", - "methods": [ - { - "name": "dispose", - "parameterTypes": [] - }, - { - "name": "fromNative", - "parameterTypes": [ - "com.sun.jna.FromNativeConverter", - "java.lang.Object", - "java.lang.reflect.Method" - ] - }, - { - "name": "fromNative", - "parameterTypes": [ - "java.lang.Class", - "java.lang.Object" - ] - }, - { - "name": "fromNative", - "parameterTypes": [ - "java.lang.reflect.Method", - "java.lang.Object" - ] - }, - { - "name": "nativeType", - "parameterTypes": [ - "java.lang.Class" - ] - }, - { - "name": "toNative", - "parameterTypes": [ - "com.sun.jna.ToNativeConverter", - "java.lang.Object" - ] - } - ] - }, - { - "name": "com.sun.jna.Native$ffi_callback", - "methods": [ - { - "name": "invoke", - "parameterTypes": [ - "long", - "long", - "long" - ] - } - ] - }, - { - "name": "com.sun.jna.NativeMapped", - "methods": [ - { - "name": "toNative", - "parameterTypes": [] - } - ] - }, - { - "name": "com.sun.jna.Pointer", - "fields": [ - { - "name": "peer" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "long" - ] - } - ] - }, - { - "name": "com.sun.jna.PointerType", - "fields": [ - { - "name": "pointer" - } - ] - }, - { - "name": "com.sun.jna.Structure", - "fields": [ - { - "name": "memory" - }, - { - "name": "typeInfo" - } - ], - "methods": [ - { - "name": "autoRead", - "parameterTypes": [] - }, - { - "name": "autoWrite", - "parameterTypes": [] - }, - { - "name": "getTypeInfo", - "parameterTypes": [] - }, - { - "name": "newInstance", - "parameterTypes": [ - "java.lang.Class", - "long" - ] - } - ] - }, - { - "name": "com.sun.jna.Structure$ByValue" - }, - { - "name": "com.sun.jna.Structure$FFIType$FFITypes", - "fields": [ - { - "name": "ffi_type_double" - }, - { - "name": "ffi_type_float" - }, - { - "name": "ffi_type_longdouble" - }, - { - "name": "ffi_type_pointer" - }, - { - "name": "ffi_type_sint16" - }, - { - "name": "ffi_type_sint32" - }, - { - "name": "ffi_type_sint64" - }, - { - "name": "ffi_type_sint8" - }, - { - "name": "ffi_type_uint16" - }, - { - "name": "ffi_type_uint32" - }, - { - "name": "ffi_type_uint64" - }, - { - "name": "ffi_type_uint8" - }, - { - "name": "ffi_type_void" - } - ] - }, - { - "name": "com.sun.jna.WString", - "methods": [ - { - "name": "", - "parameterTypes": [ - "java.lang.String" - ] - } - ] - }, - { - "name": "java.lang.Boolean", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "boolean" - ] - }, - { - "name": "getBoolean", - "parameterTypes": [ - "java.lang.String" - ] - } - ] - }, - { - "name": "java.lang.Byte", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "byte" - ] - } - ] - }, - { - "name": "java.lang.Character", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "char" - ] - } - ] - }, - { - "name": "java.lang.Class", - "methods": [ - { - "name": "getComponentType", - "parameterTypes": [] - } - ] - }, - { - "name": "java.lang.Double", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "double" - ] - } - ] - }, - { - "name": "java.lang.Float", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "float" - ] - } - ] - }, - { - "name": "java.lang.Integer", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "int" - ] - } - ] - }, - { - "name": "java.lang.Long", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "long" - ] - } - ] - }, - { - "name": "java.lang.Object", - "methods": [ - { - "name": "toString", - "parameterTypes": [] - } - ] - }, - { - "name": "java.lang.Short", - "fields": [ - { - "name": "TYPE" - }, - { - "name": "value" - } - ], - "methods": [ - { - "name": "", - "parameterTypes": [ - "short" - ] - } - ] - }, - { - "name": "java.lang.String", - "methods": [ - { - "name": "", - "parameterTypes": [ - "byte[]" - ] - }, - { - "name": "", - "parameterTypes": [ - "byte[]", - "java.lang.String" - ] - }, - { - "name": "getBytes", - "parameterTypes": [] - }, - { - "name": "getBytes", - "parameterTypes": [ - "java.lang.String" - ] - }, - { - "name": "lastIndexOf", - "parameterTypes": [ - "int" - ] - }, - { - "name": "substring", - "parameterTypes": [ - "int" - ] - }, - { - "name": "toCharArray", - "parameterTypes": [] - } - ] - }, - { - "name": "java.lang.System", - "methods": [ - { - "name": "getProperty", - "parameterTypes": [ - "java.lang.String" - ] - }, - { - "name": "setProperty", - "parameterTypes": [ - "java.lang.String", - "java.lang.String" - ] - } - ] - }, - { - "name": "java.lang.Throwable", - "methods": [ - { - "name": "toString", - "parameterTypes": [] - } - ] - }, - { - "name": "java.lang.UnsatisfiedLinkError", - "methods": [ - { - "name": "", - "parameterTypes": [ - "java.lang.String" - ] - } - ] - }, - { - "name": "java.lang.Void", - "fields": [ - { - "name": "TYPE" - } - ] - }, - { - "name": "java.lang.reflect.Method", - "methods": [ - { - "name": "getParameterTypes", - "parameterTypes": [] - }, - { - "name": "getReturnType", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.Buffer", - "methods": [ - { - "name": "position", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.ByteBuffer", - "methods": [ - { - "name": "array", - "parameterTypes": [] - }, - { - "name": "arrayOffset", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.CharBuffer", - "methods": [ - { - "name": "array", - "parameterTypes": [] - }, - { - "name": "arrayOffset", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.DoubleBuffer", - "methods": [ - { - "name": "array", - "parameterTypes": [] - }, - { - "name": "arrayOffset", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.FloatBuffer", - "methods": [ - { - "name": "array", - "parameterTypes": [] - }, - { - "name": "arrayOffset", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.IntBuffer", - "methods": [ - { - "name": "array", - "parameterTypes": [] - }, - { - "name": "arrayOffset", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.LongBuffer", - "methods": [ - { - "name": "array", - "parameterTypes": [] - }, - { - "name": "arrayOffset", - "parameterTypes": [] - } - ] - }, - { - "name": "java.nio.ShortBuffer", - "methods": [ - { - "name": "array", - "parameterTypes": [] - }, - { - "name": "arrayOffset", - "parameterTypes": [] - } - ] - }, - { - "name": "sun.management.VMManagementImpl", - "fields": [ - { - "name": "compTimeMonitoringSupport" - }, - { - "name": "currentThreadCpuTimeSupport" - }, - { - "name": "objectMonitorUsageSupport" - }, - { - "name": "otherThreadCpuTimeSupport" - }, - { - "name": "remoteDiagnosticCommandsSupport" - }, - { - "name": "synchronizerUsageSupport" - }, - { - "name": "threadAllocatedMemorySupport" - }, - { - "name": "threadContentionMonitoringSupport" - } - ] - } -] diff --git a/ffi/src/main/resources/META-INF/native-image/gay/pizza/pork/ffi/resource-config.json b/ffi/src/main/resources/META-INF/native-image/gay/pizza/pork/ffi/resource-config.json deleted file mode 100644 index c77b9d5..0000000 --- a/ffi/src/main/resources/META-INF/native-image/gay/pizza/pork/ffi/resource-config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "resources": { - "includes": [ - { - "pattern": "\\Qcom/sun/jna/darwin-x86-64/libjnidispatch.jnilib\\E" - }, - { - "pattern": "\\Qcom/sun/jna/linux-x86-64/libjnidispatch.so\\E" - }, - { - "pattern": "\\Qcom/sun/jna/win32-x86-64/jnidispatch.dll\\E" - }, - { - "pattern": "\\Qcom/sun/jna/darwin-aarch64/libjnidispatch.jnilib\\E" - }, - { - "pattern": "\\Qcom/sun/jna/linux-aarch64/libjnidispatch.so\\E" - }, - { - "pattern": "\\Qcom/sun/jna/win32-aarch64/jnidispatch.dll\\E" - } - ] - }, - "bundles": [] -} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac72c34..b745ffc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-rc-1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/minimal/build.gradle.kts b/minimal/build.gradle.kts index 350b87a..0c7aa60 100644 --- a/minimal/build.gradle.kts +++ b/minimal/build.gradle.kts @@ -18,6 +18,8 @@ dependencies { application { applicationName = "pork-rt" mainClass.set("gay.pizza.pork.minimal.MainKt") + applicationDefaultJvmArgs += "-XstartOnFirstThread" + applicationDefaultJvmArgs += "--enable-native-access=ALL-UNNAMED" } for (task in arrayOf(tasks.shadowDistTar, tasks.shadowDistZip, tasks.shadowJar)) { diff --git a/minimal/src/main/kotlin/gay/pizza/pork/minimal/Tool.kt b/minimal/src/main/kotlin/gay/pizza/pork/minimal/Tool.kt index f761a8d..058cde7 100644 --- a/minimal/src/main/kotlin/gay/pizza/pork/minimal/Tool.kt +++ b/minimal/src/main/kotlin/gay/pizza/pork/minimal/Tool.kt @@ -4,9 +4,9 @@ import gay.pizza.pork.ast.CompilationUnit import gay.pizza.pork.ast.NodeVisitor import gay.pizza.pork.ast.visit import gay.pizza.pork.evaluator.* +import gay.pizza.pork.ffi.FfiNativeProvider import gay.pizza.pork.ffi.JavaAutogenContentSource import gay.pizza.pork.ffi.JavaNativeProvider -import gay.pizza.pork.ffi.JnaNativeProvider import gay.pizza.pork.frontend.ContentSource import gay.pizza.pork.frontend.ImportLocator import gay.pizza.pork.frontend.DynamicImportSource @@ -55,7 +55,7 @@ abstract class Tool { fun run(scope: Scope, quiet: Boolean = false) { val main = loadMainFunction(scope, setupEvaluator = { addNativeProvider("internal", InternalNativeProvider(quiet = quiet)) - addNativeProvider("ffi", JnaNativeProvider()) + addNativeProvider("ffi", FfiNativeProvider()) addNativeProvider("java", JavaNativeProvider()) }) main.call(emptyList(), CallStack()) diff --git a/tool/build.gradle.kts b/tool/build.gradle.kts index 1ac8a38..fc257c7 100644 --- a/tool/build.gradle.kts +++ b/tool/build.gradle.kts @@ -14,6 +14,7 @@ application { applicationName = "pork" mainClass.set("gay.pizza.pork.tool.MainKt") applicationDefaultJvmArgs += "-XstartOnFirstThread" + applicationDefaultJvmArgs += "--enable-native-access=ALL-UNNAMED" } for (task in arrayOf(tasks.shadowDistTar, tasks.shadowDistZip, tasks.shadowJar)) { diff --git a/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt b/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt index 40979b3..d78d594 100644 --- a/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt +++ b/tool/src/main/kotlin/gay/pizza/pork/tool/RunCommand.kt @@ -6,8 +6,8 @@ import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import gay.pizza.dough.fs.PlatformFsProvider import gay.pizza.pork.evaluator.* +import gay.pizza.pork.ffi.FfiNativeProvider import gay.pizza.pork.ffi.JavaNativeProvider -import gay.pizza.pork.ffi.JnaNativeProvider import gay.pizza.pork.minimal.FileTool class RunCommand : CliktCommand(help = "Run Program", name = "run") { @@ -22,7 +22,7 @@ class RunCommand : CliktCommand(help = "Run Program", name = "run") { val scope = Scope.root() val main = tool.loadMainFunction(scope, setupEvaluator = { addNativeProvider("internal", InternalNativeProvider(quiet = quiet)) - addNativeProvider("ffi", JnaNativeProvider()) + addNativeProvider("ffi", FfiNativeProvider()) addNativeProvider("java", JavaNativeProvider()) })