Andrew Dunbar
04/20/2023, 10:42 AMKonstantin Tskhovrebov
04/20/2023, 10:53 AMAdam S
04/20/2023, 10:55 AMAndrew Dunbar
04/20/2023, 10:58 AMKonstantin Tskhovrebov
04/20/2023, 11:01 AMAndrew Dunbar
04/20/2023, 11:08 AMAdam S
04/20/2023, 11:12 AMAndrew Dunbar
04/20/2023, 11:14 AMplugins {
kotlin("multiplatform") version "1.8.0"
}
group = "me.hippietrail"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
kotlin {
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosArm64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
nativeTarget.apply {
binaries {
executable {
entryPoint = "main"
}
}
}
linuxX64()
macosX64()
sourceSets {
val nativeMain by getting
val linuxX64Main by getting
val macosX64Main by getting
}
}
Adam S
04/20/2023, 11:19 AMval nativeTarget = ...
config from here is correct https://kotlinlang.slack.com/archives/C3SGXARS6/p1679899986973039
and it looks like you have that alreadyAndrew Dunbar
04/20/2023, 11:21 AMhostOs == "Mac OS X" -> macosX64("native")
to hostOs == "Mac OS X" -> macosArm64("native")
e: file:///Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/src/linuxX64Main/kotlin/Fred.kt:6:12 Actual function 'foo' has no corresponding expected declaration
package me.hippietrail
expect fun foo(): String
fun main() {
println("Hello, Kotlin/Native!")
println(foo())
}
// actual fun foo(): String {
// return "foobie"
// }
Adam S
04/20/2023, 11:24 AMsrc/commonMain/kotlin/foo.kt
, and in that file put something like
expect fun foo(): Unit
Then it will complain unless you add `actual`s in all the other targets. You’ve defined targets linuxX64
, macosX64
, and a target that’s dynamic based on the current machine - which in your case will be macosArm64
The point behind the dynamic ‘native’ target, is that you don’t need to define the other targets - Gradle will automatically switch the target when it’s loaded on another machine. This is good for experimenting, but perhaps not so good if you want to build all the targets on one machine. So I would say, either explicitly add all targets (which can make the Gradle config a little more complicated), or remove the explicit targets and just use the dynamic ‘native’ targetAndrew Dunbar
04/20/2023, 11:24 AMpackage me.hippietrail
// actual fun foo(): String {
// return "foobie fred"
// }
actual fun foo(): String = "Linux implementation of foo"
src/macosX64Main/kotlin/Barney.kt
Adam S
04/20/2023, 11:27 AMAndrew Dunbar
04/20/2023, 11:27 AMsrc/nativeMain/kotlin/foo.kt
with just actual fun foo(): String
in it and still get same build error:
e: file😕//Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/src/linuxX64Main/kotlin/Fred.kt:6:12 Actual function ‘foo’ has no corresponding expected declarationAdam S
04/20/2023, 11:32 AMkotlin {
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosArm64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
nativeTarget.apply {
binaries {
executable {
entryPoint = "main"
}
}
}
linuxX64()
macosX64()
}
Since you’re on an M1 Mac, nativeTarget
will be macosArm64
, and this will have a hardcoded name of native
so in your src dir you’ll have
src/commonMain/kotlin
src/commonTest/kotlin
src/linuxX64Main/kotlin
src/linuxX64Test/kotlin
src/nativeMain/kotlin
src/nativeTest/kotlin
src/macosX64Main/kotlin
src/macosX64Test/kotlin
Note that because the ‘native’ target might be dynamic, but the directory structure will be the sameexpect
in commonMain MUST have an actual
in nativeMain, and macosX64Main, and linuxX64Main. Which is probably not what you want.
What you probably want is to set the targets explicitly, so nativeMain is not dynamic.
kotlin {
mingwX64()
macosArm64()
linuxX64()
macosX64()
}
Then you can code in commonMain, and write `expect`s in commonMain, and implement the actuals in each target.
However, what happens if you want to add a JS or JVM target? That might be annoying because you might end up copy-pasting code between each of the mingw/macos/linux targets. There’s a cool way of fixing that, which I can explain if you want?Andrew Dunbar
04/20/2023, 11:36 AMsrc
|____linuxX64Main
| |____resources
| |____kotlin
| | |____Fred.kt
|____nativeMain
| |____resources
| |____kotlin
| | |____foo.kt
| | |____Main.kt
|____macosX64Main
| |____resources
| |____kotlin
| | |____Barney.kt
expect fun foo(): String
is not matching this actual now
actual fun foo(): String {
return "foobie"
}
e: file😕//Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/src/nativeMain/kotlin/Main.kt:3:12 Expected function ‘foo’ has no actual declaration in module <me.hippietrail:kotlin-multiplatform-native> for Native
e: file😕//Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/src/nativeMain/kotlin/foo.kt:1:12 Actual function ‘foo’ has no corresponding expected declarationAdam S
04/20/2023, 11:45 AMAndrew Dunbar
04/20/2023, 11:46 AMAdam S
04/20/2023, 11:50 AMAndrew Dunbar
04/20/2023, 11:50 AMe: file:///Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/src/linuxArm64Main/kotlin/Fred.kt:6:12 Actual function 'foo' has no corresponding expected declaration
Adam S
04/20/2023, 11:54 AMexpect fun foo()
in src/nativeMain/kotlin/foo.kt
?Andrew Dunbar
04/20/2023, 11:56 AMAdam S
04/20/2023, 11:58 AMexpect fun foo()
to src/commonMain/kotlin/foot.kt
The error says that there’s an actual
in linuxArm64Main, but there’s no expect
in any ‘parent_‘of linuxArm64Main. In fact, the only ‘parent’ of linuxArm64Main is commonMain..
└── commonMain/
├── linuxX64Main
├── nativeMain
└── macosX64Main
but you’ve written your expect/actuals like this is the hierarchy
.
└── commonMain/
├── nativeMain/
│ └── linuxX64Main
└── macosX64Main
which isn’t what you’ve defined in the Gradle config
(note this is the model hierarchy, not the directory layout)Andrew Dunbar
04/20/2023, 12:01 PMAdam S
04/20/2023, 12:04 PMkotlin {
macosArm64("native")
linuxArm64()
sourceSets {
val nativeMain by getting
val nativeTest by getting
val linuxArm64Main by getting { dependsOn(nativeMain)}
val linuxArm64Test by getting { dependsOn(nativeTest)}
}
}
Andrew Dunbar
04/20/2023, 12:04 PMAdam S
04/20/2023, 12:04 PMAndrew Dunbar
04/20/2023, 12:05 PMkotlin {
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosArm64("native")
hostOs == "Linux" -> linuxArm64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
nativeTarget.apply {
binaries {
executable {
entryPoint = "main"
}
}
}
linuxArm64()
macosArm64()
sourceSets {
val nativeMain by getting
val linuxArm64Main by getting
val macosArm64Main by getting
}
}
Adam S
04/20/2023, 12:06 PMAndrew Dunbar
04/20/2023, 12:07 PMAdam S
04/20/2023, 12:07 PMAndrew Dunbar
04/20/2023, 12:08 PMAdam S
04/20/2023, 12:09 PM.
└── src/
├── commonMain/
├── nativeMain/
├── linuxMain/
├── windowsMain/
├── macosMain/
└── ...
kotlin {
// ...
jvm()
}
Now your source set hierarchy looks like this
.
└── common/
├── native/
│ ├── windows
│ ├── mac
│ └── linux
└── jvm/
Andrew Dunbar
04/20/2023, 12:12 PMFAILURE: Build failed with an exception.
* Where:
Build file '/Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/build.gradle.kts' line: 1
* What went wrong:
Plugin [id: 'org.jetbrains.kotlin.multiplatform'] was not found in any of the following sources:
Adam S
04/20/2023, 12:12 PMkotlin("multiplatform") version "1.8.20"
Andrew Dunbar
04/20/2023, 12:15 PMplugins{
stuff?Adam S
04/20/2023, 12:15 PMAndrew Dunbar
04/20/2023, 12:16 PMAdam S
04/20/2023, 12:16 PMAndrew Dunbar
04/20/2023, 12:16 PMAdam S
04/20/2023, 12:18 PMAndrew Dunbar
04/20/2023, 12:18 PMAdam S
04/20/2023, 12:19 PMAndrew Dunbar
04/20/2023, 12:19 PMAdam S
04/20/2023, 12:21 PMAndrew Dunbar
04/20/2023, 12:23 PMFAILURE: Build failed with an exception.
* What went wrong:
Could not determine the dependencies of task ':compileNativeMainKotlinMetadata'.
> Could not resolve all artifacts for configuration ':nativeMainResolvableDependenciesMetadata'.
> Cannot resolve external dependency org.jetbrains.kotlin:kotlin-stdlib-common:1.8.20 because no repositories are defined.
Required by:
project :
Adam S
04/20/2023, 12:25 PMexpect fun foo()
. Native is used in targets X/Y/Z. Do they all have an implementation?”build.gradle.kts
repositories {
mavenCentral()
}
Andrew Dunbar
04/20/2023, 12:27 PMAdam S
04/20/2023, 12:27 PMAndrew Dunbar
04/20/2023, 12:29 PMe: file:///Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/src/commonMain/kotlin/Main.kt:5:13 Unresolved reference: foo
expect
from Main.kt into foo.ktAdam S
04/20/2023, 12:31 PMAndrew Dunbar
04/20/2023, 12:33 PMpackage me.hippietrail
- i think the code that IDEA made for me didn’t have that but i know the AI kept adding itAdam S
04/20/2023, 12:36 PMAndrew Dunbar
04/20/2023, 12:36 PMAdam S
04/20/2023, 12:38 PMAndrew Dunbar
04/20/2023, 12:39 PMAdam S
04/20/2023, 12:40 PMAndrew Dunbar
04/20/2023, 12:41 PMnativeTarget.apply {
binaries {
executable {
entryPoint = "main"
}
}
}
Adam S
04/20/2023, 12:43 PM./gradlew runDebugExecutableMacosArmX64
(or whatever the actual target name is)
kotlin {
targets.withType<KotlinNativeTarget>().configureEach {
binaries {
executable {
entryPoint = "main"
}
}
}
}
kotlin {
macosArm64 {
binaries {
executable {
entryPoint = "main"
}
}
}
}
./gradlew runDebugExecutableNative
Andrew Dunbar
04/20/2023, 12:45 PMkotlin {
or does just part of this new one go inside my current one?Adam S
04/20/2023, 12:46 PMkotlin {}
config blocks as you like. I just put it like that so it would be easier to understand :)Andrew Dunbar
04/20/2023, 12:47 PMAdam S
04/20/2023, 12:48 PMkotlin {}
blockAndrew Dunbar
04/20/2023, 12:49 PM> Task :linkDebugExecutableMacosArm64 FAILED
e: Could not find 'main' in '<root>' package.
FAILURE: Build failed with an exception.
Adam S
04/20/2023, 1:06 PMentryPoint = "me.hippietrail.main"
Andrew Dunbar
04/20/2023, 1:07 PM> Configure project :
e: /Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/build.gradle.kts:9:20: Unresolved reference: KotlinNativeTarget
e: /Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/build.gradle.kts:10:5: Unresolved reference: binaries
e: /Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/build.gradle.kts:11:7: Unresolved reference: executable
e: /Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/build.gradle.kts:12:9: Unresolved reference: entryPoint
The Kotlin source set commonTest was configured but not added to any Kotlin compilation. You can add a source set to a target's compilation by connecting it with the compilation's default source set using 'dependsOn'.
See <https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#connecting-source-sets>
FAILURE: Build failed with an exception.
* Where:
Build file '/Users/hippietrail/IdeaProjects/kotlin-multiplatform-native/build.gradle.kts' line: 9
* What went wrong:
Script compilation errors:
Line 09: targets.withType<KotlinNativeTarget>().configureEach {
^ Unresolved reference: KotlinNativeTarget
Line 10: binaries {
^ Unresolved reference: binaries
Line 11: executable {
^ Unresolved reference: executable
Line 12: entryPoint = "main"
^ Unresolved reference: entryPoint
4 errors
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at <https://help.gradle.org>
BUILD FAILED in 1s
Adam S
04/20/2023, 1:07 PMimport org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
Andrew Dunbar
04/20/2023, 1:09 PMAdam S
04/20/2023, 1:12 PMAndrew Dunbar
04/20/2023, 1:14 PM> Task :linkDebugExecutableLinuxArm64 FAILED
e: Could not find 'main' in '<root>' package.
FAILURE: Build failed with an exception.
Adam S
04/20/2023, 1:15 PMfun main()
, what’s the package at the top?Andrew Dunbar
04/20/2023, 1:18 PMpackage me.hippietrail
Adam S
04/20/2023, 1:18 PMCould not find 'main'
means the entry point is missing the packageAndrew Dunbar
04/20/2023, 1:20 PMAdam S
04/20/2023, 1:30 PMAndrew Dunbar
04/20/2023, 1:31 PM#ifdef
et al?Adam S
04/20/2023, 1:38 PMAndrew Dunbar
04/20/2023, 1:42 PMAdam S
04/20/2023, 1:43 PMexpect
in commonMain, and then .kt files with actual
in linuxMain, windowsMain, macosMain, etc…. So it would need multiple filesAndrew Dunbar
04/20/2023, 1:44 PMAdam S
04/20/2023, 1:44 PMAndrew Dunbar
04/20/2023, 1:46 PMactual
should i change my maosMain folder to macosArm64Main and make a second one macosX64Main or should i create two new folders with those names inside my current macosMain?Adam S
04/20/2023, 2:08 PMexpect fun currentTargetName(): String
in src/commonMain/kotlin
• and then in each specific target (linuxX64. mingwX64, macosX64), create an actual fun
• (and so I don’t need to create any `actual fun`s in src/windowsMain
or src/linuxMain
)
BUT if you said “make a commonMain function that returns the name of the operating system of the target”, then because of the hierarchy I don’t need to make an actual fun
in each specific target - instead I only have to make an actual fun
in src/windowsMain
, src/linuxMain
, src/macosMain
Andrew Dunbar
04/20/2023, 2:25 PMsrc
and gave each an actual
and commented out the old `actual`from macosMain