ankushg
10/06/2021, 7:33 PMquizlet-kmp
and quizlet-ios
). Our current approach is that `quizlet-kmp`'s CI builds the framework and publishes it to our private spec repo. iOS folks can then just pull the latest version.
Problem:
This approach has worked fine for us for the past while, but some issues with this approach that are starting to get annoying are:
1. It takes a lot of time to iterate within KMP and test the change on iOS. Having to push, wait for a release to be published, update your podfile, etc is time consuming. We want an opt-in way to allow iOS folks to develop using locally checked out KMP sources.
2. We can't drop breakpoints into the KMP code to debug issues on iOS. My understanding is that this is impossible to do unless you've built the code locally.
What we're thinking:
1. The official Kotlin/Native Cocoapods Plugin seems to address issue 1 if we use it in an opt-in way (defaulting to CI builds instead).
2. Touchlab's xcode-kotlin plugin for Xcode seems to address issue 2 if the framework is built locally (and I think it's designed to be used alongside the cocoapods plugin?)
Both of the examples for these tools are using a monorepo setup though. Has anyone gotten them working with separate, independent repos?
I think I should be able to get the cocoapods plugin working by pointing the ios app's Podfile
to the absolute path of `quizlet-kmp`'s generated Podspec (regardless of directory). This could be conditionally done for every iOS engineer, since the Podfile is just a ruby script.
I also think the xcode-kotlin plugin should also allow me to drag in files from any arbitrary directory.
I'd love to hear if anyone else has done so and can confirm!KamilH
10/07/2021, 5:44 AMNSException
) and I would like to catch and handle them, is it possible?
I can see that the documentation mentions that it’s not yet possible, but maybe some work has been done in this topic? Is there any issue I can star and follow?
Note that the opposite reversed translation is not implemented yet: Swift/Objective-C error-throwing methods aren’t imported to Kotlin as exception-throwing.
martmists
10/10/2021, 9:03 PMCPointer<ByteVar>
? I only see .cstr
documented but that turns it into a CValues<ByteVar>
martmists
10/11/2021, 12:12 PMGavin Ray
10/12/2021, 2:25 PMJNIEnv*
param implicit in all calls.
Or am I out of my mind hahaGavin Ray
10/12/2021, 2:42 PMJava_org_jetbrains_skija_Canvas__1nDrawPicture
without (what looks like) passing any JNIEnv
🤔Benoit Quenaudon
10/12/2021, 7:10 PMrealpath
(platform.posix.realpath) but for some reason, a private
prefix is added on the resolved path. Any idea why that could be?
Code is something like that
val fullpath = realpath(path.toString(), null)
try {
symlinkTarget = Buffer().writeNullTerminated(fullpath).toPath()
} finally {
free(fullpath)
}
And my test fails with
kotlin.AssertionError: Expected </base/symlink-target>, actual </private/base/symlink-target>.
Benoit Quenaudon
10/12/2021, 8:02 PMfun realpath(arg0: String?, arg1: CValuesRef<stat>?): Int
In the console, there are multiple params like --logical
, --zero
, etc. How do we set those up when calling from Kotlin native?Bailey Pollard
10/13/2021, 7:03 PMSIGSEGV: Attempted to dereference garbage pointer 0xe480162a0.
? Total iOS noob here, but any suggestions could helpMiSikora
10/14/2021, 8:44 AMdispatcher
gets frozen after launching the job? I noticed it does not happen when channel
is a global value. I’m having issues wrapping my head around it.
class FreezeTest {
private val dispatcher = ImmediateDispatcher()
private val callbacks = AtomicReference(emptyList<() -> Unit>().freeze())
@Test
fun freezeTest() = runBlocking(dispatcher) {
println("1 isFrozen: ${dispatcher.isFrozen}") // False
val job = launch {
val channel = Channel<Unit>()
val callback: () -> Unit = { channel.trySend(Unit) }
callbacks.update { it + callback }
try {
for (signal in channel) {
channel.send(Unit)
}
} finally {
callbacks.update { it - callback }
}
}
println("2 isFrozen: ${dispatcher.isFrozen}") // True
job.cancel()
}
}
fun <T> AtomicReference<T>.update(func: (T) -> T) {
while (true) {
val old = value
val new = func(old).freeze()
if (compareAndSet(old, new)) break
}
}
class ImmediateDispatcher : CoroutineDispatcher() {
override fun dispatch(context: CoroutineContext, block: Runnable) = block.run()
}
altavir
10/17/2021, 8:04 AMjw
10/18/2021, 5:07 PMCValuesRef
to the leading item + item count to a C function? I've done with things like ByteArray where I can call refTo(0)
but I don't see an explanation or example of how to do this with a struct type.Gavin Ray
10/21/2021, 4:16 PMC .h -> Kotlin Native type
you could write a compiler plugin that did codegen and emitted an .h
?
interface SomeStruct {
@CType.Int32
val anInt: Int
}
typedef struct SomeStruct {
int32_t anInt;
} SomeStruct;
TheOnlyTails
10/21/2021, 6:10 PMjimmyt
10/21/2021, 11:04 PMpod("MatrixSDK"){
extraOpts = listOf("-compiler-options = -fmodules -fcxx-modules")
}
But I continue to get an error that says:
Exception in thread "main" java.lang.IllegalStateException: Unknown option -compiler-options = -fmodules -fcxx-modules
I'm clearly just using the command wrong, but I can't find any documentation for proper use anywhere. Can someone help me out with this?Philip Dukhov
10/22/2021, 2:27 PMKotlinEnum
to Identifiable
with the following code:
extension KotlinEnum: Identifiable {
public var id: Int32 { ordinal }
}
but the build fails with the following:
Extension of a generic Objective-C class cannot access the class's generic parameters at runtime
I don't understand the problem, as ordinal
has strict type Int32
, not a generic one. How can I bypass it?ankushg
10/22/2021, 8:33 PMlinkReleaseFramework<Target>
tasks (KotlinNativeLink
) are starting late in the build and executing serially, even though there are plenty of idle workers available.
Things got much worse once we added M1 support since there was now yet another framework to link 😕
The KotlinNativeLink
tasks don't seem to depend on each other in any way.
Are these tasks supposed to be able to run in parallel? If so, how can I find out why they aren't for our builds? If not, is there a YT ticket for this?
Screenshot/description of build scan timeline in 🧵jean
10/25/2021, 6:52 AMdatabaseQueries.transactionWithResult { ... }
(SQLDelight) but it throws the following error :
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.Array@10f1738it works correctly on my android target. Am I suppose to do/use something else?
Nicolas Patin
10/25/2021, 10:05 AMactual suspend fun areNotificationsSystemEnabled() : Boolean = suspendCoroutine { continuation ->
val settingsCompletionHandler = { settings: UNNotificationSettings? ->
val enabled = settings?.authorizationStatus == UNAuthorizationStatusAuthorized
continuation.resume(enabled)
}.freeze()
val notificationCenter = UNUserNotificationCenter.currentNotificationCenter()
notificationCenter.getNotificationSettingsWithCompletionHandler(settingsCompletionHandler)
}
My problem here is that the “continuation” used inside the completion handler is frozen, so it crashes on the continuation.resume(enabled)
:
Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.coroutines.SafeContinuation@80487928
[...]
at 7 KMM 0x00000001071d43e0 kfun:kotlin.coroutines.SafeContinuation#resumeWith(kotlin.Result<1:0>)
I think my issue is more or less the same than this one : https://youtrack.jetbrains.com/issue/KT-43566
I don’t know if I should ask this on #coroutines but if anyone already hit this issue, I’ll be glad to hear from you 😄
Thanks !Yashar
10/25/2021, 3:10 PM0.7.1
https://kotlinlang.slack.com/archives/C3SGXARS6/p1528475089000678 but I wanted to get another opinion from the community.
Our dynamic scanner has identified a use of private iOS API: Frameworks/Core.framework/Core: _unsymbolicated_function accessed _NSBlock
within a KMP library module. Upon some digging, I came across this similar old issue on github with fix already merged. So my question is, has anyone else come across this? And if so, is this issue already addressed and have folks been fine publishing to App store without rejections?Michael Clancy
10/25/2021, 4:59 PMnapperley
10/26/2021, 1:42 AMMarc Reichelt
10/26/2021, 1:20 PM./gradlew createSwiftPackage
command, which in turn creates an xcframework using KMP’s tooling.
However, the built framework only contains x64 simulator and arm64 (real device) code, so the simulator on my MacBook M1 will not run.
Did anyone successfully build an xcframework for all 3 targets, that is also able to run on M1 simulators as well as on Intel simulators?Sylvain Patenaude
10/26/2021, 1:55 PM@SharedImmutable is applicable only to top level declarations
and also this one in enums:
@SharedImmutable is applicable only to val with backing field or to property with delegation
Example of data class:
data class SomeDataClass(
@SharedImmutable val someInt: Int,
@SharedImmutable val someString: String,
@SharedImmutable val someBool: Boolean
)
Example of enum class:
enum class SomeEnumClass(
/** The [Int] representation of this enum value. */
@SharedImmutable val value: Int
) {
@SharedImmutable ValueA(0),
@SharedImmutable ValueB(1);
companion object {
internal fun fromInt(value: Int) = values().firstOrNull() { it.value == value } ?: ValueA
}
}
crumpf
10/26/2021, 3:28 PMpod("AFNetworking")
to the cocoapods
section of the build.gradle.kts. When I try to do a gradle sync after that the following error appears:
Execution failed for task ':shared:cinteropAFNetworkingIos'.
> Process 'command '/Users/me/Library/Java/JavaVirtualMachines/corretto-16.0.2/Contents/Home/bin/java'' finished with non-zero exit value 1
* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':shared:cinteropAFNetworkingIos'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:187)
<36 internal calls>
Caused by: org.gradle.process.internal.ExecException: Process 'command '/Users/me/Library/Java/JavaVirtualMachines/corretto-16.0.2/Contents/Home/bin/java'' finished with non-zero exit value 1
at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:414)
at org.gradle.process.internal.DefaultJavaExecAction.execute(DefaultJavaExecAction.java:52)
at org.gradle.process.internal.DefaultExecActionFactory.javaexec(DefaultExecActionFactory.java:198)
at org.gradle.api.internal.project.DefaultProject.javaexec(DefaultProject.java:1145)
at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.runViaExec(KotlinToolRunner.kt:102)
at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.run(KotlinToolRunner.kt:77)
at org.jetbrains.kotlin.gradle.tasks.CInteropProcess.processInterop(KotlinNativeTasks.kt:1017)
<122 internal calls>
ankushg
10/26/2021, 9:06 PMspec.name
that the cocoapods plugin generates?
We use an umbrella module with a name like xcode-umbrella
but... that's not the name we want for our actual cocoapod.
Setting framework.baseName
works for the final .framework
and the value for what's included in the Podspec, but doesn't impact the spec.name
or actual *.podspec
filenamegaetan
10/27/2021, 12:04 PMCADisplayLink
in the Kotlin code. This is the code of my “timer”:
@ThreadLocal
object AppTimer {
fun start(){
val selector = NSSelectorFromString("execution")
val displayLink = CADisplayLink.displayLinkWithTarget(this, selector)
displayLink.addToRunLoop(NSRunLoop.currentRunLoop, NSRunLoop.currentRunLoop.currentMode)
}
@ObjCAction
fun execution(){
NSLog("AppTimer::Execution through CADisplayLink")
}
}
It works without problem if the timer code is located in the shared module. But, when I move it into the library, it throws this error:
2021-10-27 13:45:35.769237+0200 iOSApp1[21754:6605253] -[App1_kobjcc0 execution]: unrecognized selector sent to instance 0x6000026025e0
2021-10-27 13:45:35.793415+0200 iOSApp1[21754:6605253] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[App1_kobjcc0 execution]: unrecognized selector sent to instance 0x6000026025e0'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff20422fba __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff20193ff5 objc_exception_throw + 48
2 CoreFoundation 0x00007fff20431d2f +[NSObject(NSObject) instanceMethodSignatureForSelector:] + 0
3 CoreFoundation 0x00007fff204274cf ___forwarding___ + 1455
4 CoreFoundation 0x00007fff204297a8 _CF_forwarding_prep_0 + 120
Does anyone have an idea of why this is happening?reactormonk
10/27/2021, 6:47 PMankushg
10/27/2021, 10:13 PMxcodeConfigurationToNativeBuildType
in Gradle Cocoapods plugin in 1.5.31?
In Xcode, we have a custom configuration named Development
In Gradle, we're setting xcodeConfigurationToNativeBuildType["Development"] = NativeBuildType.DEBUG
But we still see this in our logs:
Unable to detect Kotlin framework build type for CONFIGURATION=Development automatically. Specify 'KOTLIN_FRAMEWORK_BUILD_TYPE' to 'debug' or 'release'
It looks like it's still building the debug framework, but would love to know if
• this is already known,
• we're doing something wrong,
• or if we should file a YTianrumac
10/28/2021, 1:44 PMkotlinc-native test.kt -nomain
it fails with
“could not find ‘main’ in ‘<root>’ package.”Same thing happens until I strictly provide a entry point with -e and the entry point method needs to have either 0 args or an arg array. Is there a way to compile it without having a main method? I thought
-nomain
option does that already but it just turns out ignored 🤔
fun run(args: Array<String>, result: Test){
val array = args
array[0] = "42"
result.res(array[0])
}
interface Test {
fun res(string: String)
}