Hi folks,
First of all, let me tell you that I’m new to Gradle so I’m probably missing some important concepts.
This is working:
My project contains Java classes in src/main/java
that load a shared libname.so
library, compiled by the same project from the C++ files in src/main/cpp
. The build.gradle.kts
file shared below works well: I’m using both cpp-library
and java-library
plugins. I get the following output files from its execution: build/lib/main/debug/libname.so
, build/lib/main/release/libname.so
, build/libs/name.jar
.
What I would like to achieve:
I have also some test code in src/test/cpp
and src/test/java
. I would like to compile these C++ files to a shared libname_test.so
library, which would be loaded in turn by my Java tests (that use TestNG). In short, I would like to get the following output files too: build/lib/test/debug/libname_test.so
, build/lib/test/release/libname_test.so
, which would be loaded by a Java test task. I don’t know how to do that. How can I change the layout mentioned in this section?
My build.gradle.kts:
import java.io.*
import org.gradle.internal.jvm.Jvm
plugins {
`cpp-library`
`java-library`
}
val nameDir = "../../.."
val nameSrc = "src"
val currentDir: String? by project
val myUsage = Attribute.of("org.gradle.usage", Usage::class.java)
configurations.all {
afterEvaluate {
attributes {
attribute(myUsage, project.objects.named(Usage::class.java, "java-runtime"))
}
}
}
val jniImplementation by configurations.creating
configurations.matching {
it.name.startsWith("cppCompile") ||
it.name.startsWith("nativeLink") ||
it.name.startsWith("nativeRuntime")
}.all {
extendsFrom(jniImplementation)
}
dependencies {
attributesSchema {
attribute(myUsage)
}
testImplementation("org.testng:testng:6.9.10")
}
tasks.register<Copy>("copyHeaders") {
from(
"$keraDir/$nameSrc",
"$keraDir/${findNameBin()}"
)
include("**/*.h")
into("$buildDir/headers")
}
tasks.withType<CppCompile>().configureEach {
dependsOn("copyHeaders")
}
/*
tasks.getByName<Test>("test") {
useTestNG()
minHeapSize = "1024m"
maxHeapSize = "1024m"
dependsOn("linkDebug")
}
*/
val jniHeaderDirectory = layout.buildDirectory.dir("jniHeaders")
tasks.compileJava {
outputs.dir(jniHeaderDirectory)
options.compilerArgumentProviders.add(CommandLineArgumentProvider {
listOf("-h", jniHeaderDirectory.get().asFile.canonicalPath)
})
}
tasks.compileTestJava {
outputs.dir(jniHeaderDirectory)
options.compilerArgumentProviders.add(CommandLineArgumentProvider {
listOf("-h", jniHeaderDirectory.get().asFile.canonicalPath)
})
}
library {
// Private headers are stored in src/main/headers.
// Public headers are stored build/headers.
publicHeaders.from("$buildDir/headers")
binaries.configureEach {
compileTask.get().dependsOn(tasks.compileJava)
compileTask.get().compilerArgs.addAll(compileTask.get().toolChain.map {
if (it is Gcc || it is Clang) listOf("--std=c++11", "-g", "-msse4.2")
else emptyList()
})
compileTask.get().compilerArgs.addAll(jniHeaderDirectory.map {
listOf("-I", it.asFile.canonicalPath)
})
val javaHome = Jvm.current().javaHome.canonicalPath
compileTask.get().compilerArgs.addAll(compileTask.get().targetPlatform.map {
listOf("-I", "$javaHome/include") + when {
it.operatingSystem.isMacOsX -> listOf("-I", "$javaHome/include/darwin")
it.operatingSystem.isLinux -> listOf("-I", "$javaHome/include/linux")
else -> emptyList()
}
})
}
}
// Gradle populates library.binaries in afterEvaluate, so we can't access it earlier
afterEvaluate {
library.binaries.get()
.filterIsInstance<CppSharedLibrary>()
.forEach { binary ->
binary.linkTask.get().linkerArgs.add("-L../../../obj.${getCurrentGitBranch()}")
}
}
tasks.jar {
from(library.developmentBinary.flatMap {
(it as CppSharedLibrary).linkFile
})
}
Any ideas? Let me know if I should provide more details.
Best regards,
Tom