Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import io.github.andrefigas.rustjni.test.jvm.content.KotlinContentProvider
import org.gradle.api.Project
import org.gradle.api.Task
import java.io.File
import java.util.Properties

object JVMTestRunner {

Expand All @@ -25,9 +26,16 @@ object JVMTestRunner {
"rust"
)

val props = Properties()
project.file("${project.rootProject.projectDir}${File.separator}local.properties")
.inputStream().use { props.load(it) }

val ndkDir = "${props.getProperty("sdk.dir")}${File.separator}ndk"

apply(
project,
task,
ndkDir,
rustFile,
jniHost,
contentProvider,
Expand Down Expand Up @@ -78,6 +86,7 @@ object JVMTestRunner {

private fun apply(project: Project,
task: Task,
ndkDir: String,
rustFile : File,
jniHost : File,
provider : JVMContentProvider,
Expand All @@ -86,7 +95,13 @@ object JVMTestRunner {
clean(rustFile, jniHost, provider)
jniHost.writeText(data)

TestCases(project, task, jniHost, File(rustFile, "src${File.separator}lib.rs")).apply {
TestCases(project,
task,
jniHost,
ndkDir = ndkDir,
rustFile = File(rustFile, "src${File.separator}lib.rs"),
cargoConfigFile = File(rustFile,".cargo/config.toml"),
).apply {
all()
finish()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.andrefigas.rustjni.test.cases

import io.github.andrefigas.rustjni.test.JVMTestRunner
import io.github.andrefigas.rustjni.test.toml.TomlContentProvider
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Task
Expand All @@ -11,11 +12,16 @@ class TestCases(
private val project: Project,
private val task: Task,
private val jniHost: File,
private val rustFile: File
private val rustFile: File,
private val cargoConfigFile : File,
ndkDir : String,
) {

private val tomlContentProvider = TomlContentProvider(ndkDir)
private val rustContent by lazy { rustFile.readText() }
private val jvmContent by lazy { jniHost.readText() }
private val cargoConfigContent
get() = cargoConfigFile.readText()

private val isKotlin = jniHost.toString().endsWith(JVMTestRunner.KT)
private val logger = project.logger
Expand All @@ -31,6 +37,44 @@ class TestCases(
assert(true, "given a generated code, it should compile successfully")
}

@Test
fun assertCargoConfigIsSuccessfullyGenerated(){
assertCargoConfigContains(
tomlContentProvider.cargoConfig().trim(),
"given a generated code, it should generate the correct .cargo/config.toml"
)
}

@Test
fun assertCargoConfigEditsIsPreserved(){

val content = buildString {
appendLine("[section1]")
appendLine("definition1 = \"definition1\"")
appendLine(tomlContentProvider.cargoConfig().trim())
appendLine("[section2]")
appendLine("definition2 = \"definition2\"")
}

cargoConfigFile.writeText(
content
)

project.tasks.getByName("rust-jni-compile").actions.forEach { action ->
action.execute(task)
}

assertCargoConfigContains(
"[section1]\ndefinition1 = \"definition1\"",
"given a generated .cargo/config.toml edited manually, it should not remove the existing content before the generated one"
)

assertCargoConfigContains(
"[section2]\ndefinition2 = \"definition2\"",
"given a generated .cargo/config.toml edited manually, it should not remove the existing content after the generated one"
)
}

private fun assert(condition : Boolean, useCase : String, errorMessage : String = ""){
if(condition){
logger.lifecycle("RustJNI Test: 🦀 $useCase: ✅")
Expand All @@ -50,6 +94,10 @@ class TestCases(
assertContains(jvmContent, jniHost.toString(), substring, useCase)
}

private fun assertCargoConfigContains(substring: String, useCase: String) {
assertContains(cargoConfigContent, cargoConfigFile.toString(), substring, useCase)
}

private fun assertContains(text: String, path : String , substring: String, useCase: String) {

val normalizedText = text.replace("\\s".toRegex(), "")
Expand All @@ -58,7 +106,7 @@ class TestCases(
if (!normalizedText.contains(normalizedSubstring)) {
val missingPart = substring.lines().firstOrNull { !text.contains(it.trim()) }

val errorMessage = "assertContains fails:\n$path\nDoes not contain:\n$substring\nMissing part: $missingPart"
val errorMessage = "assertContains fails:\nfile:\n$path\n\ncontent:\n$text\n\nDoes not contain:\n$substring\n\nMissing part: $missingPart"
assert(false, useCase, errorMessage)
} else {
assert(true, useCase)
Expand All @@ -78,6 +126,8 @@ class TestCases(

fun all() {
assertCompilation()
assertCargoConfigIsSuccessfullyGenerated()
assertCargoConfigEditsIsPreserved()

assertIntParam()
assertLongParam()
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.github.andrefigas.rustjni.test.toml

class TomlContentProvider(ndkPath: String) {

val osName = System.getProperty("os.name").toLowerCase()
val defaultPrebuilt = when {
osName.contains("win") -> "windows-x86_64"
osName.contains("mac") -> "darwin-x86_64"
osName.contains("linux") -> "linux-x86_64"
else -> throw org.gradle.api.GradleException("Unsupported operating system: $osName")
}

private val binPath = "$ndkPath/27.1.12297006/toolchains/llvm/prebuilt/$defaultPrebuilt/bin"

val armv7_linux_androideabi = "[target.armv7-linux-androideabi]\n" +
"ar = \"$binPath/llvm-ar\"\n" +
"linker = \"$binPath/armv7a-linux-androideabi21-clang\""

val aarch64_linux_android = "[target.aarch64-linux-android]\n" +
"ar = \"$binPath/llvm-ar\"\n" +
"linker = \"$binPath/aarch64-linux-android21-clang\""

val i686_linux_android = "[target.i686-linux-android]\n" +
"ar = \"$binPath/llvm-ar\"\n" +
"linker = \"$binPath/i686-linux-android21-clang\""

val x86_64_linux_android = "[target.x86_64-linux-android]\n" +
"ar = \"$binPath/llvm-ar\"\n" +
"linker = \"$binPath/x86_64-linux-android21-clang\""

val all = listOf(
armv7_linux_androideabi,
aarch64_linux_android,
i686_linux_android,
x86_64_linux_android
)

fun cargoConfig(): String {
return buildString {
appendLine("#<RustJNI>")
appendLine("#auto-generated code")
all.forEach {
appendLine(it)
appendLine()
}
appendLine("#</RustJNI>")
}.trimStart()
}
}
2 changes: 1 addition & 1 deletion gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repositories {
google()
}

version = "0.0.22"
version = "0.0.23"
group = "io.github.andrefigas.rustjni"

gradlePlugin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ package io.github.andrefigas.rustjni

import java.io.File

internal object OSHelper {
object OSHelper {

fun isWindows(): Boolean {
return System.getProperty("os.name").toLowerCase().contains("win")
}

fun isMac(): Boolean {
return System.getProperty("os.name").toLowerCase().contains("mac")
}

fun isLinux(): Boolean {
return System.getProperty("os.name").toLowerCase().contains("linux")
}

fun doubleSeparatorIfNeeded(path: String): String {
return if (isWindows()) {
path.replace(File.separator, "${File.separator}${File.separator}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,15 +321,52 @@ class RustJNI : Plugin<Project> {
* This file tells cargo where to find the *compiler* and *linker* for different architectures when compiling for Android. */
private fun generateConfigToml() {
val configToml = File(rustDir, ".cargo${File.separator}config.toml")
if (configToml.exists()) {
configToml.delete()
}

val prebuiltPath = getPrebuiltPath()
configToml.parentFile.mkdirs()
configToml.writeText(buildConfigTomlContent(prebuiltPath))

val before = extractBeforeRustJniBlock(configToml)
val after = extractAfterRustJniBlock(configToml)

val finalContent = buildConfigTomlContent(
prebuiltPath = prebuiltPath,
beforeAutogenerated = before,
afterAutogenerated = after
).trimStart()

configToml.writeText(finalContent)

}

/** Extracts the content of the `config.toml` file before the `#<RustJNI>` block. */
private fun extractBeforeRustJniBlock(file: File): String {
if (!file.exists()) return ""

val content = file.readText()

val startPattern = Regex(
pattern = "(?s)(.*?)^[ \\t]*#<RustJNI>.*?$",
options = setOf(RegexOption.MULTILINE)
)

return startPattern.find(content)?.groupValues?.get(1) ?: content
}

private fun buildConfigTomlContent(prebuiltPath: String): String {
/** Extracts the content of the `config.toml` file after the `#</RustJNI>` block. */
private fun extractAfterRustJniBlock(file: File): String {
if (!file.exists()) return ""

val content = file.readText()

val endPattern = Regex(
pattern = "(?s)^.*?#</RustJNI>[ \\t]*(.*)",
options = setOf(RegexOption.MULTILINE)
)

return endPattern.find(content)?.groupValues?.get(1) ?: ""
}

private fun buildConfigTomlContent(prebuiltPath: String, beforeAutogenerated : String = "", afterAutogenerated : String = ""): String {
val architectures = extension.architecturesList
if (architectures.isEmpty()) {
throw org.gradle.api.GradleException("No architectures specified in rustJni extension")
Expand All @@ -338,6 +375,9 @@ class RustJNI : Plugin<Project> {
val prebuiltPath = OSHelper.doubleSeparatorIfNeeded(prebuiltPath)

return buildString {
if(beforeAutogenerated.isNotEmpty()){
appendLine(beforeAutogenerated.trimEnd())
}
appendLine("#<RustJNI>")
appendLine("#auto-generated code")
appendLine()
Expand All @@ -349,6 +389,9 @@ class RustJNI : Plugin<Project> {
appendLine()
}
appendLine("#</RustJNI>")
if(afterAutogenerated.isNotEmpty()){
appendLine(afterAutogenerated.trimStart())
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion sample/java/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import io.github.andrefigas.rustjni.reflection.Visibility
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
id("io.github.andrefigas.rustjni") version "0.0.22"
id("io.github.andrefigas.rustjni") version "0.0.23"
}

rustJni{
Expand Down
2 changes: 1 addition & 1 deletion sample/kotlin/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import io.github.andrefigas.rustjni.reflection.Visibility
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
id("io.github.andrefigas.rustjni") version "0.0.22"
id("io.github.andrefigas.rustjni") version "0.0.23"
}

rustJni{
Expand Down