russhwolf / multiplatform-settings

A Kotlin Multiplatform library for saving simple key-value data
Apache License 2.0
1.61k stars 67 forks source link

AppleSettings : Unresolved reference #76

Closed francismariano closed 3 years ago

francismariano commented 3 years ago

Hello

I am trying to use AppleSettings constructor, but it seems to me as Unresolved reference.

  val commonMain by getting {
            dependencies {
                implementation("com.russhwolf:multiplatform-settings:0.7.1")
            }
        }

I have added its dependencies like the code above and into module shared:iosMain I try to use the following:

val delegate: NSUserDefaults // ...
val settings: Settings = AppleSettings(delegate)

However the AppleSettings constructor is not available.

russhwolf commented 3 years ago

It will probably work from a gradle build even if the IDE shows an error. The library has a deep structure of intermediate source-sets which the IDE doesn't fully support yet.

afaucogney commented 3 years ago

@francismariano I'm also in that situation. Did you succeed to build ? From Xcode or gradle it doesn't work by my side.

russhwolf commented 3 years ago

If you're seeing failures from command line that'd definitely more alarming to me and I'd like to solve it. What Kotlin version are you using? Do you have kotlin.mpp.enableGranularSourceSetsMetadata=true and/or kotlin.native.enableDependencyPropagation=false in your gradle.properties? Do you have a project I can look at to understand the issue better?

krottv commented 3 years ago

The same issue is here. I don't have kotlin.mpp.enableGranularSourceSetsMetadata=true nor kotlin.native.enableDependencyPropagation=false

russhwolf commented 3 years ago

@krottv Do you have a project I can look at? I need help understanding how to reproduce the issue.

krottv commented 3 years ago

@russhwolf Yes, I have a project. Which files do you need from there? Or the whole project? Would it be fine if I send a part which will not compile?

russhwolf commented 3 years ago

I'd want to see enough that I can try to build and see what the issue is. Probably that's the whole project unless you have it isolated in a separate module or something.

krottv commented 3 years ago

@russhwolf Link to the project. It should compile fine - https://yadi.sk/d/fJl_G8aa20bb8w

cmota commented 3 years ago

I've faced the same issue while compiling on a Mac with the M1 processor.

If instead of building your app @krottv to both architecture you just compile it to arm it should work.

To overcome having a single arch, I'm using the lib multiplatform-swiftpackage to generate the packages to be used on iOS.

Not sure if there's something that you can do on multiplatform-settings @russhwolf?

russhwolf commented 3 years ago

There's different issues being conflated here and I want to differentiate what people are asking for better.

One issue is, the library builds but there's red code in the IDE. This is probably from using a shared iOS source-set (often, from the ios() target builder) when the library doesn't declare the HMPP gradle properties. I've been wary of adding that because I don't want to break consumers who aren't using those flags yet, and also I've had build issues in the past when enabling it. It's probably worth re-examining at some point, but it's been a lower priority for me because it doesn't block your build and it likely only impacts one file where you're initializing your iOS Settings instance.

Another issue is, the project doesn't build at all. That's what @afaucogney seems to be reporting.. That's a bigger issue that I'd like to understand better, but I've never seen it in action in any of my own projects, so I could use some help here with a full project that reproduces it.

@krottv your sample appears to be only a single module from a larger project and doesn't build on its own, so it doesn't help me. But I'm also not clear on which of those two buckets you fall into

@cmota brings up a further confounding factor in the new M1 macs. I haven't used one myself yet so I don't have a good sense of how it impacts this whole story. If multiplatform-swiftpackage gives you what you need, then that sounds great. I suspect doing an ad-hoc target declaration similar to the sample project would also work, but I'm not sure that's a solution that scales great for large multimodule projects. In any event, I don't think there's anything that makes sense to add at the library level to help here. Packaging is a concern that should really be handled at the application level.

GautierLouis commented 3 years ago

Hello, I've also the same issue than @ francismariano (AppleSettings not resolved, build failed) I can't share the hole project as well but this is my build.gradle.kts :

import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
    kotlin("multiplatform")
    id("com.android.library")
}
kotlin {
    // Android target
    android {
        compilations.all {
            kotlinOptions { jvmTarget = "1.8" }
        }
    }
    // iOS target
    ios {
        binaries {
            framework {
                baseName = "common-database"
                export("com.russhwolf:multiplatform-settings:0.7.7")
                transitiveExport = true
            }
        }
    }
    sourceSets {
        val commonMain by getting {
            dependencies {
                api(project(":common:kmmcore"))
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
            }
        }
        val androidMain by getting
        val androidAndroidTestRelease by getting
        val androidTest by getting {
            dependsOn(androidAndroidTestRelease)
            dependencies {
                implementation(kotlin("test-junit"))
                implementation("junit:junit:4.13.2")
            }
        }
        val iosMain by getting
        val iosTest by getting
    }
}
android {
    compileSdkVersion(Version.androidSdk)
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdkVersion(Version.androidSdkMin)
        targetSdkVersion(Version.androidSdk)
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}
// Tasks
val packForXcode by tasks.creating(Sync::class) {
    group = "build"
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
    val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
    val framework = kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-frameworks")
    from({ framework.outputDirectory })
    into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations.create("compileClasspath")

-> :common:kmmcore is exactly the same except for commonMain dependencies :

sourceSets {
        sourceSets["commonMain"].dependencies {
            api("io.github.aakira:napier:1.5.0")
            api("com.russhwolf:multiplatform-settings-no-arg:0.7.7")
            api("org.jetbrains.kotlinx:kotlinx-datetime:0.2.1")
            api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1")
            api(Dependencies.kotlinStdlibJdk8)
            api(Dependencies.koinMultiplatform)
        }
}

In usage :

actual fun Module.loadNativeModules() {
    SettingsNames.values().forEach { name ->
        single(named(name)) { AppleSettings.Factory().create(name.name) } bind Settings::class
    }
}

Build result : e: .../common/kmmdatabase/src/iosMain/kotlin/com/daxium/air/common/kmmdatabase/Settings.kt: (9, 31): Unresolved reference: AppleSettings

Hope it's helps

GautierLouis commented 3 years ago

I figured out ! (maybe way to late for you but can save some time to someone else)

Add this in your gradle (between ios and sourceSets blocks) :

val onPhone = System.getenv("SDK_NAME")?.startsWith("iphoneos") ?: false
    if (onPhone) {
        iosArm64("ios")
    } else {
        iosX64("ios")
    }

Code found on https://github.com/cashapp/sqldelight/issues/2044#issuecomment-721299517 for similar issue

krottv commented 3 years ago

@GautierLouis Awesome. Now it works!

russhwolf commented 3 years ago

You should now be able to resolve AppleSettings in the IDE in shared iOS sourcesets in version 0.8

manjukumari1 commented 4 months ago

@russhwolf I am still facing the same issue: [AppleSettings : Unresolved reference] in version 0.8.1 and 1.1.1 any help will be appreciated.

Thanks