refactor(page): 删除旧版页面文件
This commit is contained in:
154
.agents/skills/kotlin-tooling-native-build-performance/SKILL.md
Normal file
154
.agents/skills/kotlin-tooling-native-build-performance/SKILL.md
Normal file
@@ -0,0 +1,154 @@
|
||||
---
|
||||
name: kotlin-tooling-native-build-performance
|
||||
description: >
|
||||
Diagnoses and fixes slow Kotlin/Native compilation and linking in Kotlin
|
||||
Multiplatform projects that target iOS. Use when the user reports slow iOS or
|
||||
shared-framework builds, long linkDebug*/linkRelease* or XCFramework tasks,
|
||||
cold CI builds that re-download the Kotlin/Native toolchain, KSP or other
|
||||
generated code on the native path, transitiveExport usage, or asks for a
|
||||
local-development versus CI build performance plan.
|
||||
license: Apache-2.0
|
||||
metadata:
|
||||
author: JetBrains
|
||||
version: "1.0.0"
|
||||
tested_models: "openai/gpt-5.5, openai/gpt-5.4-mini"
|
||||
last_eval: "2026-07-06"
|
||||
---
|
||||
|
||||
# Kotlin/Native Build Performance
|
||||
|
||||
Turn "the iOS build is slow" into a measured diagnosis and a small set of safe
|
||||
fixes. Two rules apply throughout:
|
||||
|
||||
1. Never trade away required release behavior. A faster local loop must not
|
||||
change what CI publishes.
|
||||
2. Measure before and after with the same command and the same build state.
|
||||
An unmeasured fix is a guess.
|
||||
|
||||
## Step 0: Classify the Slow Scenario
|
||||
|
||||
Establish four facts before editing anything: **where** (local or CI),
|
||||
**what** (debug feedback loop or release/distribution artifact), **state**
|
||||
(first build, clean, warm, or no-op), and **phase** (which tasks dominate the
|
||||
log). Then match the dominant symptom:
|
||||
|
||||
| Symptom in the build log | Likely cause | Read |
|
||||
|---|---|---|
|
||||
| `linkRelease*` or `*ReleaseXCFramework` tasks in a local development loop | Building distribution artifacts for development | [artifacts-and-targets](references/artifacts-and-targets.md) |
|
||||
| Kotlin/Native compiler distribution downloaded on every CI run | `~/.konan` not preserved between runs | [caching-and-gradle](references/caching-and-gradle.md) |
|
||||
| Long pause before the first task starts | Configuration phase, no configuration cache | [caching-and-gradle](references/caching-and-gradle.md) |
|
||||
| All iOS targets build when only one simulator is needed | Broad task (`build`, `assemble`, `assemble*XCFramework`) or unused targets | [artifacts-and-targets](references/artifacts-and-targets.md) |
|
||||
| `ksp*` tasks ahead of `compileKotlinIos*` | Generated-code work on the native path | [exports-and-generated-code](references/exports-and-generated-code.md) |
|
||||
| Small source edit recompiles and relinks everything | Compiler caches disabled, or missing incrementality | [caching-and-gradle](references/caching-and-gradle.md), [experimental](references/experimental.md) |
|
||||
| Machine overloaded while several `link*` tasks run at once | Parallel native linking | [caching-and-gradle](references/caching-and-gradle.md), worker-limit caveat |
|
||||
|
||||
## Step 1: Audit and Measure
|
||||
|
||||
1. Run the static audit from the project root:
|
||||
|
||||
```bash
|
||||
scripts/audit-native-build.sh /path/to/project
|
||||
```
|
||||
|
||||
It is read-only and prints `file:line` findings (disabled caches, broad
|
||||
local tasks, `transitiveExport`, broad KSP configuration, missing CI
|
||||
`.konan` cache), each pointing at the reference file with the fix.
|
||||
Findings are leads, not verdicts — confirm each against project policy.
|
||||
2. Find the command the user actually waits for: a script, a CI step, or the
|
||||
Gradle invocation inside an Xcode build phase. Optimize that command, not
|
||||
a task you picked yourself.
|
||||
3. Run it twice when practical. The first build downloads Kotlin/Native
|
||||
components and fills caches; only the second and later runs are
|
||||
representative. Attribute time per task before blaming the compiler:
|
||||
|
||||
```properties
|
||||
kotlin.build.report.output=file # writes build/reports/kotlin-build/
|
||||
```
|
||||
|
||||
Gradle's `--scan` or `--profile` work too.
|
||||
4. If you cannot run the build (no macOS host, no Xcode), analyze logs, build
|
||||
scans, or checked-in metrics instead — and state explicitly that the
|
||||
conclusion is static.
|
||||
|
||||
## Step 2: Fix in Safe Order
|
||||
|
||||
Apply fixes one at a time, re-measuring as you go:
|
||||
|
||||
1. **Restore healthy defaults** — remove cache/daemon workarounds, enable
|
||||
Gradle build and configuration caches, keep `~/.konan` warm in CI, update
|
||||
Kotlin: [references/caching-and-gradle.md](references/caching-and-gradle.md)
|
||||
2. **Build only what the feedback loop needs** — one specific task per loop,
|
||||
correct integration method, justified target matrix:
|
||||
[references/artifacts-and-targets.md](references/artifacts-and-targets.md)
|
||||
3. **Cut export and generated-code cost** — drop `transitiveExport`, narrow
|
||||
`export(...)`, scope KSP work to the native compilations that need it:
|
||||
[references/exports-and-generated-code.md](references/exports-and-generated-code.md)
|
||||
4. **Experimental switches last, with the user's agreement**:
|
||||
[references/experimental.md](references/experimental.md)
|
||||
|
||||
## Worked Example
|
||||
|
||||
A developer on an Apple Silicon Mac complains that "every shared-module
|
||||
change costs 12 minutes". Their loop runs `./gradlew :shared:assembleXCFramework`.
|
||||
A build scan of the second (warm) run shows:
|
||||
|
||||
```
|
||||
:shared:linkReleaseFrameworkIosArm64 348s
|
||||
:shared:linkReleaseFrameworkIosX64 341s
|
||||
:shared:compileKotlinIosX64 96s
|
||||
:shared:linkDebugFrameworkIosSimulatorArm64 41s
|
||||
:shared:compileKotlinIosSimulatorArm64 38s
|
||||
configuration phase 64s
|
||||
```
|
||||
|
||||
Reasoning chain:
|
||||
|
||||
- The loop is **local + debug + warm**, but ~690s goes to `linkRelease*` —
|
||||
release linking is an order of magnitude slower than debug and only CI
|
||||
needs it. Replace the local command with
|
||||
`:shared:linkDebugFrameworkIosSimulatorArm64` (or the Xcode embed task if
|
||||
Xcode drives the build). *(artifacts-and-targets)*
|
||||
- All `iosX64` work serves Intel simulators; ask whether the team still
|
||||
supports them before removing the target. *(artifacts-and-targets)*
|
||||
- 64s of configuration on every run disappears behind
|
||||
`org.gradle.configuration-cache=true` once trialed. *(caching-and-gradle)*
|
||||
- Expected loop after the change: ~40s compile + ~40s link on warm builds —
|
||||
confirm by re-running the new command twice and comparing.
|
||||
- CI keeps `assembleXCFramework` untouched; note that explicitly in the
|
||||
report.
|
||||
|
||||
## Verify
|
||||
|
||||
- [ ] Re-run the exact baseline command; compare warm build against warm
|
||||
build, not warm against cold.
|
||||
- [ ] Second run with the configuration cache reports it is being reused.
|
||||
- [ ] The local development log no longer contains `linkRelease*`,
|
||||
`*ReleaseXCFramework`, or removed generator tasks.
|
||||
- [ ] CI still produces every required release artifact, unchanged.
|
||||
- [ ] Tests pass and the app still runs from Xcode.
|
||||
- [ ] `scripts/audit-native-build.sh` reports no findings you have not
|
||||
consciously accepted and documented.
|
||||
|
||||
## Report Your Changes
|
||||
|
||||
Close with a short performance note:
|
||||
|
||||
- The slow scenario (local/CI, debug/release, cold/warm) and the measured
|
||||
evidence — or a statement that the analysis was static.
|
||||
- Each change, and why it is safe for release behavior.
|
||||
- The before/after commands the user can run to confirm the win.
|
||||
- Remaining tradeoffs: experimental flags enabled, targets removed under a
|
||||
policy assumption, worker limits, or generated-code work deferred.
|
||||
- Links to the relevant official documentation below.
|
||||
|
||||
## Official Documentation
|
||||
|
||||
| Topic | Link |
|
||||
|---|---|
|
||||
| Improving Kotlin/Native compilation time | https://kotlinlang.org/docs/native-improving-compilation-time.html |
|
||||
| Kotlin Gradle plugin compilation and caches | https://kotlinlang.org/docs/gradle-compilation-and-caches.html |
|
||||
| iOS integration methods | https://kotlinlang.org/docs/multiplatform-ios-integration-overview.html |
|
||||
| Direct integration with Xcode | https://kotlinlang.org/docs/multiplatform/multiplatform-direct-integration.html |
|
||||
| Building final native binaries and XCFrameworks | https://kotlinlang.org/docs/multiplatform/multiplatform-build-native-binaries.html |
|
||||
| Kotlin/Native binary options | https://kotlinlang.org/docs/native-binary-options.html |
|
||||
| KSP with Kotlin Multiplatform | https://kotlinlang.org/docs/ksp-multiplatform.html |
|
||||
@@ -0,0 +1,32 @@
|
||||
# Testing
|
||||
|
||||
This skill is A/B evaluated with the JetBrains [`skills-ab-eval`](https://github.com/JetBrains/skills-ab-eval-cookbook) tool.
|
||||
The suite lives at
|
||||
[`kotlin-tooling-native-build-performance`](https://github.com/JetBrains/skills-ab-eval-cookbook/tree/main/kotlin-tooling-native-build-performance)
|
||||
and contains two tasks:
|
||||
|
||||
- **`native-build-performance-audit-task`** — a synthetic KMP iOS fixture
|
||||
seeded with common Kotlin/Native build-performance mistakes.
|
||||
- **`kotlinproject-native-build-performance-task`** — a KotlinProject template
|
||||
copy with intentional cache, target, local-build, CI, and export regressions.
|
||||
|
||||
Each task runs the agent with and without the skill and scores the result on a
|
||||
weighted rubric (reward 0–1), requiring a `BUILD_PERFORMANCE_REPORT.md` that
|
||||
preserves production release behavior.
|
||||
|
||||
## Latest results (2026-07-06)
|
||||
|
||||
Run via `skills-ab-eval` on the `codex` agent, `openai/gpt-5.5` at low reasoning
|
||||
effort, n = 6 pairs per task:
|
||||
|
||||
| Task | Without skill | With skill | Δ | Significance |
|
||||
|---|---:|---:|---:|---|
|
||||
| Synthetic native build audit | 0.74 ± 0.05 | 0.99 ± 0.02 | +0.25 | p = 0.031 |
|
||||
| KotlinProject native build audit | 0.59 ± 0.05 | 0.90 ± 0.02 | +0.31 | p = 0.031 |
|
||||
|
||||
The with-skill arms are near-deterministic (σ ≤ 0.02): the diagnostic procedure
|
||||
lives in the skill, not in the model's reasoning budget. Additional
|
||||
`openai/gpt-5.4-mini` runs (high and low reasoning) are recorded per task.
|
||||
|
||||
See each task's `EVALUATION.md` in the cookbook for full per-trial reward
|
||||
breakdowns and token/cost metrics.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Build the Right Artifact for the Feedback Loop
|
||||
|
||||
A release binary takes roughly an order of magnitude longer to build than a
|
||||
debug binary, and umbrella tasks such as `build` and `assemble` compile the
|
||||
same code several times. Map each feedback loop to one specific task.
|
||||
|
||||
## Task table
|
||||
|
||||
| Feedback loop | Correct task |
|
||||
|---|---|
|
||||
| Xcode builds and runs the app (direct integration) | `:shared:embedAndSignAppleFrameworkForXcode` |
|
||||
| Gradle-only check of the Apple Silicon simulator framework | `:shared:linkDebugFrameworkIosSimulatorArm64` |
|
||||
| CocoaPods integration | `:shared:linkPodDebugFrameworkIosSimulatorArm64` |
|
||||
| Distribution or App Store validation | `assemble<Name>ReleaseXCFramework` — in CI, not in the local loop |
|
||||
| Debug XCFramework genuinely required | `assemble<Name>DebugXCFramework` |
|
||||
|
||||
Per-target link tasks follow the pattern
|
||||
`link<BuildType>Framework<Target>`; find the exact names with
|
||||
`./gradlew :shared:tasks` or in the build log.
|
||||
|
||||
## Rules
|
||||
|
||||
- `embedAndSignAppleFrameworkForXcode` builds only the slice Xcode asked for
|
||||
and must run from an Xcode build phase, not standalone. Direct integration
|
||||
uses the documented run-script phase; keep its
|
||||
`OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED` guard so the IDE does not trigger a
|
||||
second Gradle invocation.
|
||||
- Do not mix integration methods: a project either uses direct integration or
|
||||
the CocoaPods integration, and the local task must match the one in use.
|
||||
- Do not replace CI release artifacts with debug artifacts. If CI release
|
||||
builds are slow, fix caching, the target matrix, and exports instead.
|
||||
|
||||
## Target matrix
|
||||
|
||||
`*XCFramework` tasks build every declared target. Remove a target only when
|
||||
project policy confirms it is unused — the common case is dropping
|
||||
`iosX64()` when the team no longer supports Intel-based simulators. State the
|
||||
policy assumption in your report; if policy is unclear, ask instead of
|
||||
deleting.
|
||||
|
||||
Docs:
|
||||
https://kotlinlang.org/docs/multiplatform-ios-integration-overview.html,
|
||||
https://kotlinlang.org/docs/multiplatform/multiplatform-direct-integration.html,
|
||||
https://kotlinlang.org/docs/multiplatform/multiplatform-build-native-binaries.html
|
||||
@@ -0,0 +1,68 @@
|
||||
# Caching and Gradle Configuration
|
||||
|
||||
Safe for every scenario; apply these before anything else.
|
||||
|
||||
## Update Kotlin
|
||||
|
||||
The latest Kotlin version is the first official recommendation for
|
||||
Kotlin/Native compilation time — each release improves compiler performance.
|
||||
Check `gradle/libs.versions.toml` or the plugin block and propose an upgrade
|
||||
if the project is behind. Read the compatibility guide for the target release
|
||||
before upgrading; for example, use the
|
||||
[Kotlin 2.4 compatibility guide](https://kotlinlang.org/docs/compatibility-guide-24.html)
|
||||
when moving to Kotlin 2.4.x. Each target release has a corresponding
|
||||
compatibility guide. See the
|
||||
[Kotlin 2.3.20 release notes](https://kotlinlang.org/docs/whatsnew2320.html#new-dsl-for-disabling-compilation-cache)
|
||||
for the related cache change.
|
||||
|
||||
## Remove stale workarounds
|
||||
|
||||
Projects accumulate workarounds for long-fixed compiler issues. Upgrade Kotlin
|
||||
first, then inspect:
|
||||
|
||||
- `kotlin.native.disableCompilerDaemon=true`
|
||||
- `org.gradle.daemon=false`
|
||||
|
||||
Each disables a performance feature. Remove stale workarounds and check
|
||||
whether the build completes successfully.
|
||||
|
||||
## Enable Gradle caching
|
||||
|
||||
```properties
|
||||
# gradle.properties
|
||||
org.gradle.caching=true
|
||||
org.gradle.configuration-cache=true
|
||||
```
|
||||
|
||||
- Trial the configuration cache with the user's real task before committing
|
||||
it. If Gradle reports configuration-cache problems, fix the blockers listed
|
||||
in the HTML report instead of abandoning the cache.
|
||||
- The configuration cache implicitly enables parallel task execution, which
|
||||
can run several `link*` tasks at once and overload the machine (KT-70915).
|
||||
If that happens, bound it with `org.gradle.workers.max` in
|
||||
`gradle.properties` or `--max-workers` on the command line — do not turn
|
||||
the cache off for this reason alone.
|
||||
- Delete `org.gradle.configureondemand=true`. Kotlin Multiplatform does not
|
||||
support Configuration on Demand, and it is not the same feature as the
|
||||
configuration cache.
|
||||
- For CI, a remote Gradle build cache extends `org.gradle.caching` across
|
||||
machines.
|
||||
|
||||
## Keep `~/.konan` warm in CI
|
||||
|
||||
Kotlin/Native stores its compiler distribution and caches in `$HOME/.konan`.
|
||||
Ephemeral CI machines and containers that lose it pay the cold-start cost on
|
||||
every build. On GitHub Actions:
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.konan
|
||||
key: konan-${{ runner.os }}-${{ hashFiles('**/libs.versions.toml') }}
|
||||
```
|
||||
|
||||
Use the `konan.data.dir` Gradle property only when the project intentionally
|
||||
relocates that directory (for example, to a cacheable path on a CI runner).
|
||||
|
||||
Docs: https://kotlinlang.org/docs/native-improving-compilation-time.html and
|
||||
https://kotlinlang.org/docs/gradle-compilation-and-caches.html
|
||||
@@ -0,0 +1,32 @@
|
||||
# Experimental Switches
|
||||
|
||||
Offer these last, label them experimental in the report, and keep them out of
|
||||
the default recommendation set. Get the user's agreement before enabling any
|
||||
of them.
|
||||
|
||||
## Incremental compilation of klib artifacts
|
||||
|
||||
```properties
|
||||
# gradle.properties
|
||||
kotlin.incremental.native=true
|
||||
```
|
||||
|
||||
Recompiles only the changed part of a klib into the final binary, which helps
|
||||
warm rebuilds after small edits. If it causes broken or inconsistent builds,
|
||||
revert it and file a YouTrack issue with a minimized reproducer.
|
||||
|
||||
## smallBinary
|
||||
|
||||
The `smallBinary` binary option sets `-Oz` as the default LLVM optimization
|
||||
level to shrink release binaries and their link time. It can cost runtime
|
||||
performance, so verify hot paths before keeping it. It applies to release
|
||||
binaries — it is not a fix for slow debug loops.
|
||||
|
||||
## LLVM backend customization
|
||||
|
||||
Customizing the LLVM backend is a last resort when nothing else helps, and is
|
||||
out of scope for a routine performance pass — point the user at the official
|
||||
documentation instead of improvising compiler flags.
|
||||
|
||||
Docs: https://kotlinlang.org/docs/native-binary-options.html and
|
||||
https://kotlinlang.org/docs/native-improving-compilation-time.html
|
||||
@@ -0,0 +1,50 @@
|
||||
# Framework Exports and Generated Code
|
||||
|
||||
## Framework exports
|
||||
|
||||
Every exported module grows the API surface the compiler and linker must
|
||||
keep.
|
||||
|
||||
- Remove `transitiveExport = true`. It exports the entire transitive closure
|
||||
and disables dead code elimination in many cases — it is almost never what
|
||||
the project actually needs.
|
||||
- Keep an explicit `export(...)` only for modules whose API Swift or
|
||||
Objective-C code calls directly.
|
||||
|
||||
```kotlin
|
||||
// Before: exports everything analytics depends on, defeats DCE
|
||||
binaries.framework {
|
||||
export(project(":analytics"))
|
||||
transitiveExport = true
|
||||
}
|
||||
|
||||
// After: exports exactly the Swift-facing API
|
||||
binaries.framework {
|
||||
export(project(":analytics"))
|
||||
}
|
||||
```
|
||||
|
||||
If Swift code stops compiling after narrowing exports, add back only the
|
||||
specific modules it references — that is the export list the project really
|
||||
needs.
|
||||
|
||||
## Generated code
|
||||
|
||||
If `ksp*` tasks dominate the measured time, report the bottleneck as
|
||||
generated-code work — do not present a Kotlin/Native tweak as the fix.
|
||||
|
||||
- Scope KSP to the targets or source sets that need generated code instead of
|
||||
a broad `ksp(...)` dependency:
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
add("kspCommonMainMetadata", libs.myprocessor)
|
||||
add("kspIosSimulatorArm64", libs.myprocessor)
|
||||
}
|
||||
```
|
||||
|
||||
- Confirm the generated sources are consumed by the corresponding native
|
||||
compilation before adding another target-specific KSP configuration.
|
||||
|
||||
Docs: https://kotlinlang.org/docs/ksp-multiplatform.html and
|
||||
https://kotlinlang.org/docs/native-improving-compilation-time.html
|
||||
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env bash
|
||||
# Static audit for Kotlin/Native build performance in a KMP project.
|
||||
#
|
||||
# Read-only: scans Gradle properties, build scripts, shell scripts, and CI
|
||||
# workflows for configurations known to slow Kotlin/Native builds, and prints
|
||||
# findings as `[SEVERITY] file:line message -> reference`.
|
||||
#
|
||||
# Usage: audit-native-build.sh [project-root] (default: current directory)
|
||||
#
|
||||
# Exit code: 0 always (findings are advice, not errors), unless the root is
|
||||
# not a Gradle project at all.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
ROOT="${1:-.}"
|
||||
|
||||
if [ ! -e "$ROOT/settings.gradle.kts" ] && [ ! -e "$ROOT/settings.gradle" ] \
|
||||
&& [ ! -e "$ROOT/build.gradle.kts" ] && [ ! -e "$ROOT/build.gradle" ]; then
|
||||
echo "error: $ROOT does not look like a Gradle project root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FINDINGS=0
|
||||
EXCLUDES=(--exclude-dir=.git --exclude-dir=build --exclude-dir=.gradle --exclude-dir=.kotlin)
|
||||
|
||||
# scan <severity> <message> <reference> <grep -E pattern> <include glob>...
|
||||
scan() {
|
||||
local severity="$1" message="$2" reference="$3" pattern="$4"
|
||||
shift 4
|
||||
local includes=()
|
||||
for glob in "$@"; do includes+=(--include="$glob"); done
|
||||
local hits
|
||||
hits=$(grep -RInE "${EXCLUDES[@]}" "${includes[@]}" -e "$pattern" "$ROOT" 2>/dev/null \
|
||||
| grep -vE '^[^:]+:[0-9]+:[[:space:]]*(#|//)' || true)
|
||||
[ -z "$hits" ] && return 0
|
||||
while IFS= read -r hit; do
|
||||
FINDINGS=$((FINDINGS + 1))
|
||||
printf '[%s] %s\n %s\n -> %s\n' \
|
||||
"$severity" "${hit%%:*}:$(echo "$hit" | cut -d: -f2)" "$message" "$reference"
|
||||
done <<< "$hits"
|
||||
}
|
||||
|
||||
# require_property <message> <reference> <key> <value>
|
||||
# Reports when no gradle.properties sets key=value (commented lines ignored).
|
||||
require_property() {
|
||||
local message="$1" reference="$2" key="$3" value="$4"
|
||||
if ! grep -RInE "${EXCLUDES[@]}" --include='gradle.properties' \
|
||||
-e "^[[:space:]]*${key}[[:space:]]*=[[:space:]]*${value}[[:space:]]*$" \
|
||||
"$ROOT" >/dev/null 2>&1; then
|
||||
FINDINGS=$((FINDINGS + 1))
|
||||
printf '[%s] %s\n %s\n -> %s\n' \
|
||||
"MEDIUM" "gradle.properties" "$message" "$reference"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "== Kotlin/Native build performance audit: $ROOT =="
|
||||
echo
|
||||
|
||||
## 1. Disabled performance defaults (highest impact, safest to fix)
|
||||
|
||||
scan HIGH \
|
||||
"Kotlin/Native compiler daemon disabled" \
|
||||
"references/caching-and-gradle.md: remove stale workarounds" \
|
||||
'^[[:space:]]*kotlin\.native\.disableCompilerDaemon[[:space:]]*=[[:space:]]*true' \
|
||||
'gradle.properties'
|
||||
|
||||
scan HIGH \
|
||||
"Gradle daemon disabled" \
|
||||
"references/caching-and-gradle.md: remove stale workarounds" \
|
||||
'^[[:space:]]*org\.gradle\.daemon[[:space:]]*=[[:space:]]*false' \
|
||||
'gradle.properties'
|
||||
|
||||
scan MEDIUM \
|
||||
"Configuration on Demand is unsupported by KMP and is not the configuration cache" \
|
||||
"references/caching-and-gradle.md: enable Gradle caching" \
|
||||
'^[[:space:]]*org\.gradle\.configureondemand[[:space:]]*=[[:space:]]*true' \
|
||||
'gradle.properties'
|
||||
|
||||
scan MEDIUM \
|
||||
"Gradle build cache explicitly disabled" \
|
||||
"references/caching-and-gradle.md: enable Gradle caching" \
|
||||
'^[[:space:]]*org\.gradle\.caching[[:space:]]*=[[:space:]]*false' \
|
||||
'gradle.properties'
|
||||
|
||||
require_property \
|
||||
"org.gradle.caching=true is not set" \
|
||||
"references/caching-and-gradle.md: enable Gradle caching" \
|
||||
'org\.gradle\.caching' 'true'
|
||||
|
||||
require_property \
|
||||
"org.gradle.configuration-cache=true is not set (trial it with the real task first)" \
|
||||
"references/caching-and-gradle.md: enable Gradle caching" \
|
||||
'org\.gradle\.configuration-cache' 'true'
|
||||
|
||||
## 2. Framework exports
|
||||
|
||||
scan HIGH \
|
||||
"transitiveExport = true disables dead code elimination in many cases" \
|
||||
"references/exports-and-generated-code.md: framework exports" \
|
||||
'transitiveExport[[:space:]]*=[[:space:]]*true' \
|
||||
'*.gradle.kts' '*.gradle'
|
||||
|
||||
## 3. Generated code on the native path
|
||||
|
||||
scan INFO \
|
||||
"broad ksp(...) dependency; prefer per-target add(\"ksp<Target>\", ...) in KMP" \
|
||||
"references/exports-and-generated-code.md: generated code" \
|
||||
'^[[:space:]]*ksp\(' \
|
||||
'*.gradle.kts' '*.gradle'
|
||||
|
||||
## 4. Targets and local build scope
|
||||
|
||||
scan INFO \
|
||||
"iosX64 target declared; confirm Intel-based simulators are still supported" \
|
||||
"references/artifacts-and-targets.md: target matrix" \
|
||||
'iosX64[[:space:]]*\(' \
|
||||
'*.gradle.kts' '*.gradle'
|
||||
|
||||
scan MEDIUM \
|
||||
"broad or release Gradle task in a shell script; if this is the local loop, narrow it" \
|
||||
"references/artifacts-and-targets.md: task table" \
|
||||
'gradlew?[^#]*([[:space:]](clean|build|assemble)([[:space:]]|$)|XCFramework|linkRelease)' \
|
||||
'*.sh'
|
||||
|
||||
## 5. CI cold starts
|
||||
|
||||
WORKFLOW_HITS=$(grep -RIlE "${EXCLUDES[@]}" --include='*.yml' --include='*.yaml' \
|
||||
-e 'gradlew|gradle/actions|setup-gradle' "$ROOT/.github" 2>/dev/null || true)
|
||||
for wf in $WORKFLOW_HITS; do
|
||||
if ! grep -qE '\.konan' "$wf"; then
|
||||
FINDINGS=$((FINDINGS + 1))
|
||||
printf '[%s] %s\n %s\n -> %s\n' \
|
||||
"MEDIUM" "$wf" \
|
||||
"workflow runs Gradle but does not cache ~/.konan (cold Kotlin/Native toolchain every run)" \
|
||||
"references/caching-and-gradle.md: keep .konan warm in CI"
|
||||
fi
|
||||
done
|
||||
|
||||
## 6. Informational
|
||||
|
||||
scan INFO \
|
||||
"konan.data.dir relocates the Kotlin/Native cache; confirm the new location is preserved" \
|
||||
"references/caching-and-gradle.md: keep .konan warm in CI" \
|
||||
'^[[:space:]]*konan\.data\.dir[[:space:]]*=' \
|
||||
'gradle.properties'
|
||||
|
||||
scan INFO \
|
||||
"experimental kotlin.incremental.native is enabled; keep it labeled experimental in reports" \
|
||||
"references/experimental.md" \
|
||||
'^[[:space:]]*kotlin\.incremental\.native[[:space:]]*=[[:space:]]*true' \
|
||||
'gradle.properties'
|
||||
|
||||
echo
|
||||
if [ "$FINDINGS" -eq 0 ]; then
|
||||
echo "No static findings. Measure before concluding the build is healthy:"
|
||||
echo "run the user's real command twice and check per-task time with"
|
||||
echo "kotlin.build.report.output=file or --scan."
|
||||
else
|
||||
echo "$FINDINGS finding(s). Confirm each against the project's policy before fixing;"
|
||||
echo "measure before and after with the same command (see SKILL.md, Step 1)."
|
||||
fi
|
||||
exit 0
|
||||
Reference in New Issue
Block a user