skiptools / skiptools/skip

Android Studio cannot index Skip modules without explicit includeBuild in project's settings.gradle.kts

Open
#627 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
3.2k
Forks
106
Avg merge
6d 13h
Merged PRs (30d)
1

Description

Problem

When using Skip with Android Studio, the generated Kotlin project (skipstone) is included as a composite build via includeBuild. However, the path to skipstone is only known at Gradle configuration time — it's computed dynamically from the Skip plugin's output directory.

Android Studio requires a static, pre-configured settings.gradle.kts to properly index composite builds. When the skipstone path is computed dynamically, AS fails to index Skip modules, resulting in:

  • All Skip-generated types showing as unresolved (red) in the Android app module
  • No code completion for Skip module APIs
  • No navigation to Skip module source
  • The IDE being effectively unusable for the Android side of a Skip project

Root Cause

The skip-build-plugin generates the Gradle project configuration dynamically. When Skip's Gradle plugin is applied, the skipstone includeBuild path is added at runtime. This works for command-line Gradle builds but not for Android Studio's indexing, which requires the composite build structure to be statically declared in settings.gradle.kts before any plugin resolution occurs.

Workaround

We worked around this by maintaining a custom static settings.gradle.kts in the Android project that:

  1. Resolves the skipstone path from Xcode's DerivedData (always authoritative since the project is built from Xcode)
  2. Reads version configuration from skipstone's auto-generated settings.gradle.kts
  3. Calls includeBuild(skipstonePath) statically so AS can index it
val skipstonePath = run {
    val derivedDataDir = file("${System.getProperty("user.home")}/Library/Developer/Xcode/DerivedData/")
    derivedDataDir.listFiles()
        ?.filter { it.name.startsWith("WhatWatt-") }
        ?.maxByOrNull { it.lastModified() }
        ?.resolve("Build/Intermediates.noindex/BuildToolPluginIntermediaries/whatwatthybrid.output/WhatWatt/skipstone")
        ?.takeIf { it.exists() }
        ?: error("Skipstone not found in DerivedData — build the project from Xcode first")
}.path

This workaround has some rough edges — though we mitigate them:

  • It hardcodes the DerivedData path structure (which may change between Xcode versions)
  • Version information is read directly from skipstone's own auto-generated settings.gradle.kts at sync time, so it stays in sync without manual duplication
  • Multiple WhatWatt DerivedData entries are handled by picking the most recently modified one, which is always the active build

Suggested Fix

The ideal fix would be for Skip to either:

  1. Generate a static includeBuild entry — write a stable, path-resolved includeBuild(...) call into the Android project's settings.gradle.kts after transpilation, so AS can see it without dynamic evaluation.

  2. Document the includeBuild requirement — clarify in the Skip docs that AS users need to manually add the includeBuild path and explain how to find it.

Environment

  • Skip: 1.7.0
  • Xcode: 26.2 (Build 17C52)
  • Android Studio: 2025.2 (Meerkat)
  • Gradle: 8.14.3
  • Android Gradle Plugin: 8.13.0
  • Kotlin: 2.2.0

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the skip-build-plugin behavior and the generated skipstone and Android project's settings.gradle.kts files described in the issue. Reproduce Android Studio indexing with the current dynamic includeBuild, then determine whether a generated static includeBuild or documentation is appropriate; done means Skip modules index with resolved types, completion, and navigation.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin, swift
Domain
build-system, developer-experience, mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.