Skip to main content

Swift compiler

Building distributable frameworks

Because SKIE adds Swift code to the Kotlin framework, you need to choose whether that produced framework should be distributable to other computers.

Due to the nature of KMP projects, the Kotlin framework is usually needed only to build the final binary and never leaves the computer on which it was built. In those cases, the framework does not need to be distributable even if the binary itself is distributed. Therefore, SKIE produces a non-distributable framework by default.

If you plan to distribute the Kotlin framework to other computers, you must explicitly configure the support for that use case using the following Gradle configuration:

build.gradle.kts
skie {
build {
produceDistributableFramework()
}
}
note

The produceDistributableFramework() is only a convenience function that enables the enableSwiftLibraryEvolution, noClangModuleBreadcrumbsInStaticFrameworks and enableRelativeSourcePathsInDebugSymbols properties (explained below).

Swift Library Evolution

Swift library evolution is a feature of the Swift compiler that ensures binary compatibility for Frameworks distributed as binaries. Having library evolution in KMP projects is usually unnecessary, so SKIE does not use library evolution by default.

The only exception is when building XCFrameworks, which requires the library evolution to be enabled. However, if this restriction is lifted in the future, SKIE will also disable library evolution for XCFrameworks. Therefore, do not rely on this behavior, and explicitly enable the library evolution if needed.

The Swift library evolution can be enabled using the following Gradle configuration:

build.gradle.kts
skie {
build {
enableSwiftLibraryEvolution.set(true)
}
}

However, if you need library evolution, you will likely want to use the convenience produceDistributableFramework() function instead (as explained above).

Removing Clang module breadcrumbs in static frameworks

SKIE can optionally pass the -no-clang-module-breadcrumbs flag to the Swift compiler frontend when building a static framework.

Enable this flag when building a distributable static framework.

This flag ensures the compiler doesn't emit DWARF skeleton CUs for imported Clang modules. Without this flag, you will likely get the following warning when importing the framework on computers that haven't produced the framework:

...../xyz.pcm: No such file or directory
Linking a static library that was built with `-gmodules`, but the module cache was not found.
Redistributable static libraries should never be built with module debugging enabled.
The debug experience will be degraded due to incomplete debug information.

This flag can be enabled using the following Gradle configuration:

build.gradle.kts
skie {
build {
noClangModuleBreadcrumbsInStaticFrameworks.set(true)
}
}

However, if you need to enable this flag, you will likely want to use the convenience produceDistributableFramework() function instead (as explained above).

Making debug source paths relative

By default, all source paths in the debug information are absolute. This is a problem when distributing the framework to other computers, because the sourcepaths usually don't match the paths on the target computer. It results in the debugger not being able to stop at breakpoints unless you manually configure LLDB to expect the different paths.

While the Kotlin compiler can be configured to produce relative source paths, it requires declaring all the source directories due to a bug in Kotlin compiler.

SKIE has a support for relative source paths that doesn't require any additional configuration. It works by working around the Kotlin compiler bug and should enable the relative source paths for all project-local sources. Any sources that come from 3rd party dependencies will still have absolute paths.

With this feature enabled, you can distribute the framework to other computers and debug it on those computers without any additional configuration. LLDB will automatically match the relative paths to the source files on the target computer and stop at breakpoints.

This feature can be enabled using the following Gradle configuration:

build.gradle.kts
skie {
build {
enableRelativeSourcePathsInDebugSymbols.set(true)
}
}

However, if you need to enable this flag, you will likely want to use the convenience produceDistributableFramework() function instead (as explained above).