Skip to content

Commit 15af543

Browse files
committed
Updated dev docs
1 parent 39dc6dd commit 15af543

File tree

1 file changed

+90
-59
lines changed

1 file changed

+90
-59
lines changed

docs/environment.md

Lines changed: 90 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -166,47 +166,72 @@ Here goes all heavy lifting codegen
166166

167167
#### Compiler Specific Modules
168168

169-
> [!NOTE] Has its drawbacks, maybe we'll redesign later.
170-
171169
We have a problem when developing a Kotlin compiler plugin:
172170
Compiler API is not stable (not won't be for a while). So how can one develop a plugin that works stably?
173171

174172
We compile for multiple Kotlin versions at once!
175173

176174
We use an in-house ✨technology✨ for this: CSM or Compiler Specific Modules.
177-
The idea is to substitute source sets depending on the current kotlin compiler version
175+
This is a templating engine, which resolution is based on the current kotlin compiler version
178176
(`kotlin-compiler` in [libs.versions.toml](../versions-root/libs.versions.toml)).
179177

180-
There is always a `core` source set (like this: [core](../compiler-plugin/compiler-plugin-k2/src/main/core))
178+
There is always a core source set (like this: [kotlin](../compiler-plugin/compiler-plugin-k2/src/main/kotlin))
181179
that compiles nicely on all Kotlin versions. It is the majority of the code.
182-
And then we have source sets that are swapped for a specific version
183-
(check other directories in the [main](../compiler-plugin/compiler-plugin-k2/src/main)).
180+
And then we have a template set, which is processed before compilation for a specific version.
181+
([templates](../compiler-plugin/compiler-plugin-k2/src/main/templates)).
184182

185-
The code that swaps them is in [compiler-specific-module.gradle.kts](../gradle-conventions/src/main/kotlin/compiler-specific-module.gradle.kts).
183+
The code that swaps them is in [template.kt](../gradle-conventions/src/main/kotlin/util/csm/template.kt).
186184

187185
The rules are the following:
188-
- Check all source sets that start with `v_` (for example, `v_2_2`, `v_2_1`, `v_2_2_2`).
189-
It matches the most specific like a tree (so for `2.2.20` it will be `v_2_2_2`, for `2.2.10` - `v_2_2` and for `2.3.0` none).
190-
If found one - its taken.
191-
- If none, then check all that start with `pre_` (for example, `pre_2_0_10`, `pre_2_1_0`, `pre_2_2_0`).
192-
Again, it matches the most specific inclusively, but chronologically
193-
(for `2.1.0` it will be `pre_2_1_0`, for `2.0.0` - `pre_2_0_10`, for `2.3.0` none)
194-
- Take `latest` otherwise
195-
- Suffixes don't matter (`2.2.0` and `2.2.0-RC` are considered the same)
196-
197-
It allows supporting some past and future Kotlin versions
186+
- We enclose code dependent on a version in `##csm` tags.
187+
- Every such block must:
188+
- Start with `//##csm <block_name>`
189+
- End with `//##csm /<block_name>`
190+
- Specify inside zero of more of the code blocks:
191+
- `//##csm default` + `//##csm /default`
192+
- `//##csm specific=[<version_patten>]` + `//##csm /specific`
193+
194+
Example code:
195+
```kotlin
196+
fun functionAvailableInAllVersions() {
197+
198+
}
199+
fun csmFunction() {
200+
//##csm my-block
201+
//##csm default
202+
return 1
203+
//##csm /default
204+
//##csm specific=[2.0.0...2.1.0, 2.1.0-ij-*]
205+
return 2
206+
//##csm /specific
207+
//##csm /my-block
208+
}
209+
```
210+
211+
Templates matches `specific` versions greedy, so with multiple `specific` blocks - first one matched will be chosen,
212+
or `default` if none, or nothing if there is no `default`.
213+
214+
`<version_pattern>` works like this:
215+
- It's a comma-separated array of versions matchers
216+
- Version matcher is either:
217+
- Range — consists of `from` and `to` version separated by `...`.
218+
`From` must be an exact version without a suffix.
219+
`To` must be a version without a suffix, where `*` can be used for any part: `2.2.*`, `2.*` but not `2.2.2*`.
220+
- Prefix matcher — matches a version by prefix: `2.2.0-*`, `2.2.2*`, `2.3.0-dev-*`
221+
222+
This allows us to support some past and future Kotlin versions
198223
(including versions for IDE, which are not in the stable list nor generally public) simultaneously.
199224

200-
Rule for complier API breaking changes:
225+
Rules for complier API breaking changes:
201226
- If some function or property changed signature or was replaced by another -
202-
use `VersionSpecificApi` interface in `core` to declare functionality
203-
and write the implementation in **all** other source sets
204-
(see [FirVersionSpecificApi.kt](../compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirVersionSpecificApi.kt)
205-
and [VersionSpecificApi.kt](../compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/VersionSpecificApi.kt)).
227+
use `VersionSpecificApi` interface in core to declare functionality
228+
(see [FirVersionSpecificApi.kt](../compiler-plugin/compiler-plugin-k2/src/main/kotlin/kotlinx/rpc/codegen/FirVersionSpecificApi.kt)
229+
and [VersionSpecificApi.kt](../compiler-plugin/compiler-plugin-backend/src/main/kotlin/kotlinx/rpc/codegen/VersionSpecificApi.kt)).
206230
- If some class differs in signature,
207-
write a proxy in `core` and implementation in source sets. FQ name must match exactly
208-
(see [FirRpcCheckersVS.kt](../compiler-plugin/compiler-plugin-k2/src/main/v_2_3/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt))
209-
as an example, and all classes with the same names in other source sets.
231+
write a proxy in core and implementation in the template.
232+
FQ name must match exactly.
233+
(see [FirRpcCheckersVS.kt](../compiler-plugin/compiler-plugin-k2/src/main/templates/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt)
234+
as an example)
210235

211236
TeamCity is set up to work with multiple Kotlin versions for testing and releases.
212237

@@ -365,14 +390,14 @@ Here is a 'simple' guide for solving problems:
365390
- `Cannot connect to the Docker daemon` - open `Docker Desktop`
366391
- Kotlin/Js or Kotlin/Wasm
367392
- `kotlinUpgradePackageLock` or `kotlinWasmUpgradePackageLock` (and also `kotlinNpmInstall` or `kotlinWasmNpmInstall`)
368-
have a funny tendency to fail sometimes, and you don't know why.
369-
<br/>
370-
I'll tell you!
371-
<br/>
372-
We use proxy repos, and sometimes dependencies get downloaded from the wrong source.
373-
Make sure ALL urls in `package-lock.json` files start with `https://packages.jetbrains.team/npm/p/krpc/build-deps/`.
374-
<br/>
375-
If something doesn't work, your steps are:
393+
have a funny tendency to fail sometimes, and you don't know why.
394+
395+
I'll tell you!
396+
397+
We use proxy repos, and sometimes dependencies get downloaded from the wrong source.
398+
Make sure ALL urls in `package-lock.json` files start with `https://packages.jetbrains.team/npm/p/krpc/build-deps/`.
399+
400+
If something doesn't work, your steps are:
376401
- Delete `package-lock.json` file
377402
- Delete `<REPO_ROOT>/build/js` / `<REPO_ROOT>/build/wasm`
378403
- Run `kotlinUpgradePackageLock` / `kotlinWasmUpgradePackageLock`
@@ -384,13 +409,13 @@ If something doesn't work, your steps are:
384409
- `always-auth=true`
385410
- `save-exact=true`
386411
- `//packages.jetbrains.team/npm/p/krpc/build-deps/:_authToken=<your_auth_token>`,
387-
where `<your_auth_token>` is from the [proxy-repositories.md](proxy-repositories.md) guide.
412+
where `<your_auth_token>` is from the [proxy-repositories.md](proxy-repositories.md) guide.
388413
- Check that `<USER_HOME>/.npmrc` / `<USER_HOME>/.yarnrc` don't interfere
389-
command to debug. Replace versions of tools if needed.
414+
command to debug. Replace versions of tools if needed.
390415
- When you get the following error — `puppeteer` failed to run the installation script.
391-
Reasons vary, try updating the version to a newer one,
392-
check the [.puppeteerrc.cjs](../.puppeteerrc.cjs) and [chrome_bin.js](../karma/chrome_bin.js) files if they are valid js.
393-
416+
Reasons vary, try updating the version to a newer one,
417+
check the [.puppeteerrc.cjs](../.puppeteerrc.cjs) and [chrome_bin.js](../karma/chrome_bin.js) files if they are valid js.
418+
394419
For (2), check out our guide on configuring puppeteer at https://pptr.dev/guides/configuration.
395420
at ChromeLauncher.resolveExecutablePath (/rpc/build/js/packages/kotlinx-rpc-utils-test/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ProductLauncher.js:295:27)
396421

@@ -410,27 +435,33 @@ check the [.puppeteerrc.cjs](../.puppeteerrc.cjs) and [chrome_bin.js](../karma/c
410435
}
411436
}
412437
This means the `puppeteer` failed to locate Chrome.
413-
Either the cache dir is wrong (check [.puppeteerrc.cjs](../.puppeteerrc.cjs) file) or it really isn't there.
414-
<br/>
415-
Reasons again vary.
416-
When `npm` installs `puppeteer`, it should execute script to install the browser too
417-
(On CI to the `<ROOT_DIR>/.puppeteer/browsers` directory).
418-
This absence may be caused by the `--ignore-scripts` flag.
419-
Check the clean installation (`rm -rf build && ./gradlew clean cleanJsBrowserTest`) with `--debug` flag.
420-
(Something like `./gradlew jsBrowserTest --debug`).
421-
**IMPORTANT: run in docker with `TEAMCITY_VERSION` env var set, if you are chasing a CI fail**.
422-
<br/>
423-
The property is set in [npm.kt](../gradle-conventions/src/main/kotlin/util/tasks/npm.kt), see `ignoreScripts`,
424-
it should be `false`.
425-
<br/>
426-
If this is not the case, check the debug log for other `node`-related issues.
427-
Try installing browsers manually: `~/.gradle/nodejs/node-v22.0.0-linux-x64/bin/node build/js/node_modules/puppeteer/install.mjs`
428-
If this works — problem is somewhere in KGP and probably your configs.
429-
Check that your config (like ones with `ignoreScript`) are actually applied,
430-
as they use on demand execution and may target wrong plugin or extension and never be executed.
431-
<br/>
432-
**Bonus**: it may not be installed, because npm install doesn't do this.
433-
See the long comment in [npm.kt](../gradle-conventions/src/main/kotlin/util/tasks/npm.kt).
438+
Either the cache dir is wrong (check [.puppeteerrc.cjs](../.puppeteerrc.cjs) file) or it really isn't there.
439+
440+
Reasons again vary.
441+
442+
- When `npm` installs `puppeteer`, it should execute script to install the browser too
443+
(On CI to the `<ROOT_DIR>/.puppeteer/browsers` directory).
444+
This absence may be caused by the `--ignore-scripts` flag.
445+
446+
Check the clean installation (`rm -rf build && ./gradlew clean cleanJsBrowserTest`) with `--debug` flag.
447+
(Something like `./gradlew jsBrowserTest --debug`).
448+
449+
The property is set in [npm.kt](../gradle-conventions/src/main/kotlin/util/tasks/npm.kt), see `ignoreScripts`,
450+
it should be `false`.
451+
452+
**IMPORTANT: run in docker with `TEAMCITY_VERSION` env var set, if you are chasing a CI fail**.
453+
454+
- If this is not the case, check the debug log for other `node`-related issues.
455+
Try installing browsers manually:
456+
457+
~/.gradle/nodejs/node-v22.0.0-linux-x64/bin/node build/js/node_modules/puppeteer/install.mjs
458+
459+
If this works — problem is somewhere in KGP and probably your configs.
460+
Check that your config (like ones with `ignoreScript`) are actually applied,
461+
as they use on demand execution and may target wrong plugin or extension and never be executed.
462+
463+
**Bonus**: it may not be installed, because npm install doesn't do this.
464+
See the long comment in [npm.kt](../gradle-conventions/src/main/kotlin/util/tasks/npm.kt).
434465

435466
Something doesn't work, and you are sure it's not your fault? Report it appropriately! Don't be lazy.
436467

0 commit comments

Comments
 (0)