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

Garry

03/07/2024, 11:42 AM
Hello! We're facing an issue where code completion and symbol recognition in Xcode doesn't work for our KMP library. Some details: • The library is integrated in Xcode using a build phase script which runs the
embedAndSignAppleFrameworkForXcode
Gradle task • The compiler knows about the library via the
FRAMEWORK_SEARCH_PATHS
and
OTHER_LDFLAGS=-framework TheKmpLibrary
settings • Our Xcode project uses custom configuration names (not the standard Debug and Release), so we set
KOTLIN_FRAMEWORK_BUILD_TYPE
to map our configurations to build types accordingly • Kotlin and KMP plugin version is 1.9.22. Code completion doesn't work, nor can Xcode locate the header file when command-clicking on a symbol imported from the library - it just shows the dreaded Giant Question Mark icon and burps. What's interesting is that both of these functions work if we build the library as an XCFramework, and import it using the standard Frameworks, libraries and embedded content mechanism in Xcode. This, however, is not a viable option in a monorepo where the KMP library is compiled from source alongside the Xcode project. Any ideas? Are we missing something in our setup? Not having code completion is an absolute developer experience killer, especially with the name mapping from Kotlin to Swift.
👀 2
And one more additional detail; this is how we integrate the framework:
Copy code
FRAMEWORK_SEARCH_PATHS=$(inherited) path/to/library/module/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)
Have done some digging in the meantime, and I think it's related to the interaction between the Xcode indexer, custom configuration names, and behind-the-scenes Xcode magic in how frameworks are handled when they're added to a project via the UI. When comparing the differences between including the KMP library as an XCFramework (where code completion works) and including it directly as a Framework using the official instructions (code completion broken), one disparity is what lands up in the indexer data folder. I'm not sure what's going on under the hood, but when Xcode indexes a project, all third-party Swift packages and frameworks that are included in a project via the Frameworks, libraries and embedded content UI get copied to
/Users/<user>/Library/Developer/Xcode/DerivedData/<project>/Index.noindex/Build/Products/<Configuration>-<Platform>
. When using an XCFramework linked in using the Xcode UI, the KMP shared library framework is copied to this folder. When using the
embedAndSignAppleFrameworkForXcode
task approach, it is not. What's also interesting is that that
configuration
component of the indexer data folder path doesn't pick up the custom configuration name; even when building the project with a custom configuration, it seems to always be plain ol' debug or release. Putting it together: this seems to make the difference for code completion; after manually copying the KMP library framework folder to the indexer data location, code completion and symbol recognition works again.
Hacky as hell approach that is working, in the same build phase script that builds the shared KMP library:
Copy code
./gradlew :shared:embedAndSignAppleFrameworkForXcode

DERIVED_DATA_DIR=$(echo "${TARGET_BUILD_DIR}" | awk -F'/Build/' '{print $1}')

INDEXER_DATA_DIR=${DERIVED_DATA_DIR}/Index.noindex/Build/Products/Debug-$PLATFORM_NAME
mkdir -p $INDEXER_DATA_DIR
cp -R shared/build/xcode-frameworks/$CONFIGURATION/$SDK_NAME/* ${INDEXER_DATA_DIR}
Maybe this'll help some other folks who were having issues with code completion.
23 Views