Using Gradle `from project` in `settings.gradle` for a module in the same level of folder cannot be found - gradle

In https://docs.gradle.org/current/userguide/platforms.html#sec:importing-published-catalog, when we want to include a versionCatalog from another library, in our settings.gradle, we can use
dependencyResolutionManagement {
versionCatalogs {
libs {
from("com.mycompany:catalog:1.0")
}
}
}
If the catalog is in the same project, I tried to do as below
dependencyResolutionManagement {
versionCatalogs {
libs {
from project(":catalog")
}
}
}
It keeps complaining that Project with path ':catalog' could not be found. even though the catalog project is there in the same level as settings.gradle.
How can I solve the problem?

Related

no build output compiled for common module of Kotlin Multiplatform project

I'm trying to figure out why dependent projects for my Kotlin MPP library don't see any provided modules in their common modules even though the targets (jvm, android) can see them.
Published via maven-publish.
The /build directory for the library contains nothing I can identify as an intermediate representation of my common modules, leading me to think that I need to explicitly tell Gradle to produce the files to be included as common in the published package.
As it is, the .aar and .jar files produced in the android and desktop (jvm) modules each look normal, but the published common module is empty.
I need that common module to be populated before I can code against it inside the common module of dependent projects.
Here is the relevant section of my build.gradle.kts. I omit the repository config as it appears to work.
I basically followed the instructions from kotlinlang.org.
I've looked at the maven-publish plugin configuration, the settings for the kotlin-multiplatformm plugin, and the configured project structure.
kotlin version is 1.6.10, unable to update due to Jetbrains Compose dependency.
plugins {
kotlin("multiplatform")
id("com.android.library")
id("maven-publish")
}
kotlin {
android {
publishLibraryVariants = listOf("release", "debug")
}
jvm("desktop") {
compilations.all {
kotlinOptions {
jvmTarget = "11"
}
}
}
val publicationsFromMainHost = listOf(jvm("desktop").name, "kotlinMultiplatform")
publishing {
publications {
matching { it.name in publicationsFromMainHost }.all {
val targetPublication = this#all
tasks.withType<AbstractPublishToMaven>()
.matching { it.publication == targetPublication }
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("androidx.startup:startup-runtime:1.1.1")
}
}
val androidTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
implementation("androidx.test:core:1.4.0")
implementation("androidx.test:runner:1.4.0")
implementation("androidx.test:rules:1.4.0")
implementation("org.robolectric:robolectric:4.6.1")
}
}
val desktopMain by getting
val desktopTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
}
}
}
}
The answer is to manually supply the Kotlin stdlib dependency, rather than relying on the gradle plugin to add it.
When there are only jvm-based builds present, commonMain will be built with platform type of jdk8 rather than common. By making an explicit dependency on stdlib-common, it will be coerced back to the common platform, and then the correct metadata will be created and published.
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
}
}

How to add a dependency in a multiplatform kotlin / native intellij project?

I have the following build.gradle configuration:
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.41'
}
repositories {
mavenCentral()
}
kotlin {
linuxX64("linux") {
binaries {
executable {
entryPoint = 'sample.main'
runTask?.args('')
}
}
}
sourceSets {
linuxMain {
dependencies {
api("org.http4k:http4k-core:3.183.0")
}
}
linuxTest {
}
}
}
And the following source file src/linuxMain/kotlin/sample/SampleLinux.kt :
package sample
fun hello(): String = "Hello, Kotlin/Native!"
fun main() {
println(hello())
}
How to add a external library in order to be able to use autocomplete in imports for the library org.http4k:http4k-core:3.183.0?
As you can see, I tried to add the line api("org.http4k:http4k-core:3.183.0") in linuxMain dependencies, but although intellij show the library in External Libraries section, I cannot work with the packages neither classes of http4k in SampleLinux.kt file: any org.http4k..... import attempt is not recognized and generates compilation error.
After a quick look, I am almost sure that http4k is JVM-only library, at least for now. According to this issue, they are still waiting for Native to grow. If you are interested, it would be nice if one can ask the library maintainers again. As far as K/N has grown a lot by the last year, maybe they change their mind.

How to include headers for C compilation in Gradle?

I am a newbie to Gradle. I am trying to compile a set of source files which contain headers which are distributed across the project directory. My source directory structure does not comply with the Gradle convention. How do I add the header locations needed for compilation in my build.gradle? Attached here is my build.gradle file.
// build.gradle
apply plugin: 'c'
model {
components {
my_project (NativeExecutableSpec){
sources {
c {
source {
srcDir "my_proj_src/a/a1.1"
include "**/*.c"
}
exportedHeaders {
srcDir "my_proj_src/a/a1.1", "fsw/b/b1.2"
}
}
}
}
}
}
This does not work. And additionally, is there a possibility to do partial linking using Gradle?
EDIT: Additionally, I would like to also know how to make Gradle search recursively for headers within the source hierarchy.
exportedHeaders` are for exporting headers from the component itself, not for adding headers. So this would not work.
You would need to create a library and add it as the api linkage so that those headers will be added to headers your component is compiled against:
model {
repositories {
libs(PrebuiltLibraries) {
ffmpegHeaders {
headers.srcDirs "$ffmpegDir/include"
}
}
}
components {
libUsingHeaders(NativeLibrarySpec) {
sources {
c {
lib library: 'ffmpegHeaders', linkage: 'api'
}
}
}
}
}

Gradle - "apply from" a ZIP dependency

In my Gradle build script I want to import a ZIP dependency that contains static analysis configuration (CheckStyle, PMD etc.) and then "apply from" the files in that ZIP. When anyone runs the "check" task, my custom static analysis configuration should be used then.
I've tried the somewhat convoluted solution below, but I can't get it to work. The files are retrieved and unpacked into the "config" directory, but "apply from" does not work - Gradle complains it cannot find the files; I assume this is due to "apply from" being run during the build configuration phase.
Is there a simpler way to do this?
repositories {
maven { url MY_MAVEN_REPO }
}
configurations {
staticAnalysis {
description = "Static analysis configuration"
}
}
dependencies {
staticAnalysis group:'my-group', name:'gradle-static-analysis-conf', version:'+', ext:'zip'
}
// Unzip static analysis conf files to "config" in root project dir.
// This is the Gradle default location.
task prepareStaticAnalysisConf(type: Copy) {
def confDir = new File(rootProject.projectDir, "config")
if (!confDir.exists()) {
confDir.mkdirs()
}
from {
configurations.staticAnalysis.collect { zipTree(it) }
}
into confDir
apply from: 'config/quality.gradle'
}
check.dependsOn('prepareStaticAnalysisConf')
You are perfectly right: Gradle runs apply during evaluation phase, but the prepareStaticAnalysisConf was not executed yet and the archive is not unpacked.
Instead of a task, just write some top-level code. It should do the trick. Also, you'd better use the buildscript level dependency, so that it is resolved before script is executed.
Here is the full script
buildScript {
repositories {
maven { url MY_MAVEN_REPO }
}
dependencies {
classpath group:'my-group', name:'gradle-static-analysis-conf', version:'+', ext:'zip'
}
}
def zipFile = buildscript.configurations.classpath.singleFile
copy {
from zipTree(it)
into 'config'
}
apply from: 'config/quality.gradle'

Gradle sourceSet depends on another sourceSet

This Question is similar to Make one source set dependent on another
Besides the main SourceSet I also have a testenv SourceSet.
The code in the testenv SourceSet references the main code, therefor I need to add the main SourceSet to the testenvCompile configuration.
sourceSets {
testenv
}
dependencies {
testenvCompile sourceSets.main
}
This does not work, because you cannot directly add sourceSets as dependencies. The recommended way to do this is:
sourceSets {
testenv
}
dependencies {
testenvCompile sourceSets.main.output
}
But this does not work correctly with eclipse, because when I clean the gradle build folder, eclipse can't compile anymore, since it depends on the gradle build.
Also if I change main code I'd have to rebuild the project in gradle for the changes to take effect in eclipse.
How do I declare the dependencies correctly?
EDIT:
This
sourceSets {
testenv
}
dependencies {
testenvCompile files(sourceSets.testenv.java.srcDirs, sourceSets.testenv.resources.srcDirs)
}
works for the main source, but because I now reference the .java files I am missing generated classes from the Annotation-Processor :(
So after all this is the way to go:
sourceSets {
testenv
}
dependencies {
testenvCompile sourceSets.main.output
}
To make it work correctly with eclipse you have to manually exclude all sourceSet outputs from the eclipse classpath.
This is ugly, but it works for me:
Project proj = project
eclipse {
classpath {
file {
whenMerged { cp ->
project.logger.lifecycle "[eclipse] Excluding sourceSet outputs from eclipse dependencies for project '${project.path}'"
cp.entries.grep { it.kind == 'lib' }.each { entry ->
rootProject.allprojects { Project project ->
String buildDirPath = project.buildDir.path.replace('\\', '/') + '/'
String entryPath = entry.path
if (entryPath.startsWith(buildDirPath)) {
cp.entries.remove entry
if (project != proj) {
boolean projectContainsProjectDep = false
for (Configuration cfg : proj.configurations) {
boolean cfgContainsProjectDependency = cfg.allDependencies.withType(ProjectDependency).collect { it.dependencyProject }.contains(project)
if(cfgContainsProjectDependency) {
projectContainsProjectDep = true
break;
}
}
if (!projectContainsProjectDep) {
throw new GradleException("The project '${proj.path}' has a dependency to the outputs of project '${project.path}', but not to the project itself. This is not allowed because it will cause compilation in eclipse to behave differently than in gradle.")
}
}
}
}
}
}
}
}
}

Resources