https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
j

Justin

09/27/2019, 7:42 PM
Is it possible to get the root path of the project (as a string) in commonTest?
b

basher

09/27/2019, 7:44 PM
In a gradle file or in Kotlin?
i guess if you're asking about commonTest, you mean Kotlin
j

Justin

09/27/2019, 7:44 PM
Basically I need to be able to access the files in
project/src/commonTest/resources/
i have file reader actuals implemented in jvm/ios/js
in jvm i can do
val filePath: String = System.getProperty("user.dir") + "/src/commonTest/resources/" + fileName
but i can't do that in js or ios obviously
b

basher

09/27/2019, 7:46 PM
In your build, you can codegen a Kotlin file that has that constant (in an
object
or something). You'd spit out that file in your
build
dir somewhere and then add that folder to your commonTest sourceSet
j

Justin

09/27/2019, 7:46 PM
is that complicated to do?
or relatedly, is it possible to make values declared in build.gradle.kts available in kotlin sources?
b

basher

09/27/2019, 7:48 PM
I believe this is generally the way it's done. It's basically what android gradle plugin does
with
BuildConfig
. one sec. sample code coming
j

Justin

09/27/2019, 7:48 PM
ok sweet thanks!
b

basher

09/27/2019, 7:52 PM
Copy code
afterEvaluate {
    tasks.register("generateTheCodes") {
        def packageRoot = file("build/mycodgen/kotlin/com/<package-path>")
        def buildConfigFile = new File(packageRoot, "BuildConfig.kt")
        outputs.file(buildConfigFile)

        doLast {
            // make the directory tree
            mkdir packageRoot

            buildConfigFile.text = ""

            buildConfigFile << """package <your-package>
              |object MyBuildConfig {
              |    const val resourcesPath = ${file("src/commonTest/resources").path}              
              |}
            """.stripMargin().stripIndent()
        }
    }

    // Include this in our source sets
    kotlin.sourceSets.named("commonTest") {
        kotlin.srcDirs += uidsRoot
    }
    // Ensure this runs before any compile task
    tasks.withType(AbstractCompile.class).each {
        it.configure {
            dependsOn 'generateTheCodes'
        }
    }
}
this creates a task called
generateTheCodes
which outputs a .kt file that has an
object
in it, then at the end we add it to commonTest sources and add it to the task graph (with a bit of a broad brush, but should work fine)
j

Justin

09/27/2019, 7:53 PM
you're the man
b

basher

09/27/2019, 7:53 PM
there are some things that you'll have to adjust for your case like the package paths and all that, but hopefully this gives a good start
j

Justin

09/27/2019, 7:53 PM
let me try it out
thank you!
b

basher

09/27/2019, 7:53 PM
codegen is great, once you get the hang of it. you can save yourself a lot of time making it part of your teams workflow to automate common classes, etc.
j

Justin

09/27/2019, 7:54 PM
oh definitely. i'm just new-ish to kotlin
but it's served well on other platforms
b

basher

09/27/2019, 7:54 PM
yeah no worries 🙂
j

Justin

09/27/2019, 7:56 PM
hmm packageRoot should point to what exactly
b

basher

09/27/2019, 7:56 PM
com/mycompany/mylibrary/
j

Justin

09/27/2019, 7:56 PM
inside of the build folder though?
or is the build meaningless in the sample
b

basher

09/27/2019, 7:58 PM
oh yeah so inside the build folder, pick a name that makes sense for your root for this codegen
like
build/mybuildconfig
j

Justin

09/27/2019, 7:58 PM
gotcha
b

basher

09/27/2019, 7:58 PM
and then source will be
build/mybuildconfig/com/mycompany/mypackage/
basically mirroring package/folder structure in your lib
j

Justin

09/27/2019, 7:59 PM
ok trying that now
last q: what is
uidsRoot
supposed to point to?
i guess packageRoot
b

basher

09/27/2019, 8:35 PM
oh yeah sorry. i was adapting some personal code and forgot to fix that var name
uidsRoot is `build/mybuildconfig`` in this case
so not package root
j

Justin

09/27/2019, 9:01 PM
@basher It's almost working! The `BuildConfig.kt`gets created in
build/<package>
, but I still can't reference
BuildConfig.resourcesPath
from the files in
commonTest
(suggesting that something's not working with adding the dir to the sourceset)?
b

basher

09/27/2019, 9:01 PM
does the BuildConfig.kt have the right package declaration at the top?
and you're adding bulid/mybuildconfig to commonTest right? not the full path?
j

Justin

09/27/2019, 9:02 PM
yea it does. this is what i got
Copy code
afterEvaluate {
    val generateBuildConfig = tasks.register("generateBuildConfig") {
        val packageRoot = file("build/codegen/kotlin/com/n8p6/enkounter/")
        val buildConfigFile = File(packageRoot,"BuildConfig.kt")
        outputs.file(buildConfigFile)

        doLast {
            mkdir(packageRoot)

            buildConfigFile.writeText("""
                package com.n8p6.enkounter
                
                object BuildConfig {
                    const val resourcesPath: String = "${file("src/commonTest/kotlin/com/n8p6/enkounter/resources").path}"
                }
                """.trimMargin().trimIndent()
            )
        }
    }

    kotlin.sourceSets.named("commonTest") {
        kotlin.srcDirs += file("build/codegen/kotlin/com/n8p6/enkounter")
    }

    tasks.withType<AbstractCompile>().forEach {
        it.dependsOn(generateBuildConfig)
    }
}
b

basher

09/27/2019, 9:04 PM
one thing to be careful of is that if you have an Android target, Android also makes an object called BuildConfig (may want to consider a prefix)
j

Justin

09/27/2019, 9:04 PM
ah i don't
but might be worth changing regardless just to be safe
b

basher

09/27/2019, 9:04 PM
kotlin.srcDirs += file("build/codegen/kotlin/com/n8p6/enkounter")
should be
kotlin.srcDirs += file("build/codegen")
j

Justin

09/27/2019, 9:04 PM
ohhh
i see what you meant
let me try that
b

basher

09/27/2019, 9:05 PM
🙂
j

Justin

09/27/2019, 9:24 PM
finally got it with
commonTest.kotlin.setSrcDirs(commonTest.kotlin.srcDirs + "build/codegen")
thank you so much for your help @basher!
b

basher

09/27/2019, 9:24 PM
🎉 np!
r

russhwolf

09/27/2019, 11:29 PM
FYI there's a library BuildKonfig that does some of this work for you if you want the configuration to feel more like an Android project. https://github.com/yshrsmz/BuildKonfig
👍 1
b

basher

09/28/2019, 12:22 AM
Ooh nice!
8 Views