Sweep of every pin the project owns. Only these two moved: - coil: COIL_REF bumped with it and the vendored sources re-synced (no local edits needed) - ktor: plain Maven dep, apidemo's HTTP client Already latest, left alone: SDL3 (release-3.4.16), koin 4.2.2, okio 3.18.2, coroutines 1.11.0, kotlinx-io-okio 0.9.1. Deliberately not bumped: kotlinx-serialization (latest is 1.12.0-RC, a prerelease) and everything under policy 1, which CMP 1.12.1 still pins where we are. The pulse group rename also lands in the klib dumps here - the unique name embeds the group, and BCV infers the macOS dumps from the checked-in files on Windows, so those headers had to be rewritten for apiDump to run.
compose-fork - vendored Compose sources
This directory is the tooling that vendors byte-for-byte verbatim source
files from JetBrains/compose-multiplatform-core
into the repo. See ../../CLAUDE.md → "Compose API Fidelity"
for the three fix strategies (pull-verbatim / surface-match / intentional-custom).
The vendored files are NOT committed
<module>/src/vendor/ is gitignored - it is a generated artifact, not
source. Only the tooling here and the per-module manifests are tracked:
| File | Purpose |
|---|---|
sync.sh |
Idempotent script that canonicalizes the selected manifest(s) then copies each active entry verbatim from the pinned upstream ref. |
format-manifest.py |
Canonicalizes a compose-fork.txt in place (see "Manifest layout"). Run by sync.sh; also runnable standalone. |
compose.properties |
NAME=value variable declarations - the pinned upstream refs, tagged in one place. Manifests reference them as <NAME> in SET_REPO=<url>@<NAME>. |
README.md |
This file. |
../../<module>/compose-fork.txt |
Per-module manifest - lives alongside the module's build.gradle.kts. Today only :core has one; a future :material3 module would add its own. |
Manifest layout - per module, co-located with build.gradle.kts
Each Gradle module that vendors upstream code carries its own compose-fork.txt
next to its build.gradle.kts. That file lists every upstream file the module
vendors:
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt src/vendor/common/kotlin/androidx/compose/ui/Modifier.kt
The destination is relative to the manifest's own directory (so core/
paths don't have a core/ prefix - the manifest already lives in core/).
Entries are grouped by androidx package in hierarchy (alphabetical) order under
# ── androidx.compose.<pkg> ── headers. Within each package the vendored
(uncommented) entries come first, then the not-yet-vendored (commented)
candidates below.
format-manifest.py regenerates exactly this layout - deduping by dest (last
active line wins, matching sync.sh's copy order) and dropping stray comments.
It is idempotent and a pure re-layout: the set of active upstream → dest
pairs is preserved, so the vendored tree is byte-identical. sync.sh runs it
automatically before copying; run it yourself after hand-editing:
python3 scripts/compose-fork/format-manifest.py # rewrite EVERY <module>/compose-fork.txt
python3 scripts/compose-fork/format-manifest.py --manifest core/compose-fork.txt # single manifest
python3 scripts/compose-fork/format-manifest.py --check # exit 1 if any manifest is not canonical
python3 scripts/compose-fork/format-manifest.py --discover PATH # + surface new upstream files
Discovering new upstream files
--discover <clone> (or $CMP_REF) scans, for each manifest, every
compose/<area>/<module> upstream module the manifest already references, and
adds any .kt not already listed as a commented candidate under its
package section, with a best-guess dest (refine when you vendor it; only the
upstream path is deduped, so curated entries keep their dests). sync.sh runs
--discover $CMP_REF automatically after cloning per manifest, so a
compose.properties bump surfaces newly-added upstream files as candidates.
Source sets mirrored: commonMain, nonJvmMain, nativeMain, nonAndroidMain,
skikoMain. JVM / Android / JS / test are intentionally skipped.
Because the copies are verbatim, provenance lives entirely in
<module>/compose-fork.txt + compose.properties. Never hand-edit a file under
<module>/src/vendor/ - change the manifest or the ref and re-run sync.sh
instead. Hand-written glue (shims, expect/actual actuals, project-specific
code) lives outside the vendor tree and IS committed.
Bootstrapping a fresh checkout
The build needs the vendored files present on disk. After cloning this repo
you must populate <module>/src/vendor/ once before building:
# Clones/updates the sparse upstream checkout at $CMP_REF (default ../cmp-ref)
# to the ref in compose.properties, then copies every manifest entry verbatim.
CMP_REF=../cmp-ref bash scripts/compose-fork/sync.sh
Syncing selectively - per-module
sync.sh accepts one or more arguments identifying which manifests to run:
bash scripts/compose-fork/sync.sh # every <module>/compose-fork.txt in the repo
bash scripts/compose-fork/sync.sh :core # Gradle path
bash scripts/compose-fork/sync.sh core # module name (same thing)
bash scripts/compose-fork/sync.sh :material-symbols:outlined # nested Gradle path
bash scripts/compose-fork/sync.sh core/compose-fork.txt # direct path to a manifest
bash scripts/compose-fork/sync.sh :core :material # multiple
Argument resolution:
| Form | Resolves to |
|---|---|
:foo:bar |
foo/bar/compose-fork.txt |
foo/bar |
foo/bar/compose-fork.txt |
foo |
foo/compose-fork.txt |
path/to/file.txt |
that path |
Re-run any time after editing a manifest or bumping compose.properties.
The script is idempotent.
Adding an upstream module
If you want to vendor a Compose module we don't yet cover (e.g. material3):
- Create the module in the repo if needed (
material3/build.gradle.ktsetc.), and add itsinclude(":compose:material3:material3")tosettings.gradle.kts. - Create
material3/compose-fork.txtwith the standard header (any comment;format-manifest.pywill fix the layout). Populate it either by hand or by letting--discoverseed it:# Add ONE commented candidate to seed the upstream module reference, then # let discover fill in the rest: printf '# compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Placeholder.kt src/vendor/common/kotlin/androidx/compose/material3/Placeholder.kt\n' > material3/compose-fork.txt CMP_REF=../cmp-ref bash scripts/compose-fork/sync.sh :material3 - Uncomment the entries you actually want to vendor, then re-run
sync.sh :material3.
Adding a file to an existing module's vendor set
- Find the upstream path in the module's
compose-fork.txt- it may already be listed, commented out. - Add / uncomment its
<upstream-path> <dest>line under the matching# ── androidx.compose.<pkg> ──section. Destinations are relative to the module dir:commonMain→src/vendor/common/,nonJvmMain/nativeMain/skikoMain→src/vendor/native/. Exact placement / ordering doesn't matter -sync.shre-canonicalizes. - Run
sync.sh :<module>(canonicalizes the manifest, then copies). - Build and add any hand-written glue the new file needs (shims / actuals) outside the vendor tree.
Bumping the upstream ref
Edit the ref variable (e.g. COMPOSE_CORE_REF) in compose.properties, re-run
sync.sh, then rebuild. A
verbatim re-sync makes git status of a temporary tracked copy show exactly
what upstream changed between refs.