-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.gradle.kts
More file actions
207 lines (187 loc) · 8.32 KB
/
Copy pathbuild.gradle.kts
File metadata and controls
207 lines (187 loc) · 8.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// SPDX-License-Identifier: GPL-3.0-or-later
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.vanniktech.publish)
alias(libs.plugins.dokka)
alias(libs.plugins.binary.compat)
alias(libs.plugins.kover)
alias(libs.plugins.spotless)
alias(libs.plugins.detekt)
}
// GROUP / VERSION_NAME come from gradle.properties — the single coordinate source
// the vanniktech plugin reads; mirrored onto the project for non-publish tasks.
group = providers.gradleProperty("GROUP").getOrElse("org.meshtastic")
version = providers.gradleProperty("VERSION_NAME").getOrElse("0.1.0")
repositories {
mavenCentral()
}
kotlin {
jvmToolchain(21)
explicitApi()
compilerOptions {
// Treat compiler warnings as errors across all targets (main + test) and
// opt into progressive mode so deprecations/ambiguities surface early.
// The whole tree compiles warning-clean under this. (No -Xexpect-actual-
// classes: kzstd has a single commonMain implementation, no expect/actual.)
allWarningsAsErrors.set(true)
progressiveMode.set(true)
}
jvm()
// The codec is pure-Kotlin in commonMain on EVERY target, so js / wasmJs /
// wasmWasi need NO JS dependency: compress AND decompress run through the
// pure-Kotlin PureZstdEncoder / PureZstdDecoder. IR is the only Kotlin/JS
// compiler in 2.4+, so plain `js {}` selects it.
js {
browser()
nodejs()
}
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
browser()
nodejs()
}
@OptIn(ExperimentalWasmDsl::class)
wasmWasi {
nodejs()
}
// The nine native targets. They compile the SAME pure-Kotlin codec as every
// other target — no cinterop, no vendored libzstd. applyDefaultHierarchy-
// Template() gives a shared nativeMain/nativeTest; the codec lives entirely
// in commonMain.
iosArm64()
iosSimulatorArm64()
iosX64()
macosArm64()
tvosArm64()
tvosSimulatorArm64()
linuxX64()
linuxArm64()
mingwX64()
applyDefaultHierarchyTemplate()
sourceSets {
// kzstd has ZERO runtime dependencies: the pure-Kotlin codec uses only the
// Kotlin stdlib. (The dictionary/match-index caches that once needed an
// atomicfu lock are gone — a ZstdDictionary digests its dictionary once in
// its constructor and is immutable thereafter, so no shared mutable state
// and no lock remain.)
commonTest.dependencies {
implementation(kotlin("test"))
}
jvmTest.dependencies {
implementation(libs.junit.jupiter)
runtimeOnly(libs.junit.platform.launcher)
// zstd-jni here is a TEST-ONLY oracle (not a runtime dep): the interop
// tests cross-check that kzstd's pure-Kotlin frames are decodable by
// real libzstd and vice versa — the both-directions interop gate.
// (The committed test dictionary is generated by scripts/train_test_dict.py.)
implementation(libs.zstd.jni)
}
}
}
// Validate the full cross-platform ABI (klib/native + common), not JVM only.
// With klib enabled, `apiDump` writes api/kzstd.klib.api (all 12 non-JVM
// targets) next to the JVM api/kzstd.api, and `apiCheck` validates both.
// Targets a CI host can't build (the Apple targets on the Linux/Windows
// runners) are skipped by BCV and trusted from the committed dump; regenerate
// the full dump on a macOS host via `./gradlew apiDump`.
apiValidation {
@OptIn(kotlinx.validation.ExperimentalBCVApi::class)
klib {
enabled = true
}
}
// Reproducible archives: stable file order + zeroed timestamps so published
// artifacts are byte-deterministic across builds.
tasks.withType<AbstractArchiveTask>().configureEach {
isReproducibleFileOrder = true
isPreserveFileTimestamps = false
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
// ─────────────────────────────────────────────────────────────────────────────
// Code quality: Spotless (ktlint formatting) + detekt (static analysis).
// ktlint honors the repo `.editorconfig`, so the two stay in one style source of
// truth. `spotlessApply` reformats; `spotlessCheck` + `detekt` gate CI.
spotless {
kotlin {
target("src/**/*.kt")
ktlint(libs.versions.ktlint.get())
}
kotlinGradle {
target("*.gradle.kts")
ktlint(libs.versions.ktlint.get())
}
}
detekt {
buildUponDefaultConfig = true
config.setFrom(files("$rootDir/config/detekt/detekt.yml"))
// Pre-existing findings in the RFC 8878 engine (lifted verbatim from
// TAKPacket-SDK) are captured in a baseline so the gate blocks NEW issues
// while the engine is cleaned up incrementally. Regenerate: ./gradlew detektBaseline
baseline = file("$rootDir/config/detekt/baseline.xml")
// KMP has no `main`/`test` source sets, so point detekt at the source tree
// directly (it recurses for *.kt/*.kts).
source.setFrom(files("src"))
}
// ─────────────────────────────────────────────────────────────────────────────
// Maven Central publishing via the Vanniktech maven-publish plugin.
// Coordinates are read from gradle.properties: GROUP, POM_ARTIFACT_ID, VERSION_NAME.
// Signing is conditional — only applied when CI provides the key via Gradle properties.
mavenPublishing {
// automaticRelease = true makes the Sonatype Central Portal publish the
// upload directly to Maven Central instead of leaving it pending manual
// approval.
publishToMavenCentral(automaticRelease = true)
if (providers.gradleProperty("signingInMemoryKey").isPresent) {
signAllPublications()
}
pom {
name.set("kzstd")
description.set(
"Pure-Kotlin multiplatform Zstandard (zstd) codec with dictionary support — " +
"interoperable with libzstd, zero runtime dependencies.",
)
inceptionYear.set("2026")
url.set("https://github.com/meshtastic/kzstd")
licenses {
license {
name.set("GNU General Public License, Version 3.0")
url.set("https://www.gnu.org/licenses/gpl-3.0.html")
distribution.set("repo")
}
}
developers {
developer {
id.set("meshtastic")
name.set("Meshtastic")
url.set("https://meshtastic.org")
}
}
scm {
url.set("https://github.com/meshtastic/kzstd")
connection.set("scm:git:git://github.com/meshtastic/kzstd.git")
developerConnection.set("scm:git:ssh://git@github.com/meshtastic/kzstd.git")
}
}
}
// Security floors for the Kotlin/JS test harness (karma/webpack/mocha stack in
// kotlin-js-store/yarn.lock). Dev-time only — nothing here ships in published
// artifacts. Each pin clears an open Dependabot alert; drop a resolution once
// the transitive tree requires at least that version on its own.
// After changing these, regenerate the lock: ./gradlew kotlinUpgradeYarnLock
plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().apply {
resolution("ws", "8.21.0") // GHSA memory-exhaustion DoS (< 8.21.0)
resolution("serialize-javascript", "7.0.5") // RCE (< 7.0.3) + CPU-exhaustion DoS (< 7.0.5)
resolution("webpack", "5.104.1") // buildHttp allow-list bypasses (< 5.104.1)
resolution("diff", "8.0.3") // parsePatch/applyPatch DoS (< 8.0.3)
resolution("brace-expansion", "2.1.4") // Dependabot HIGH ReDoS + OOM DoS (< 2.1.4)
resolution("fast-uri", "3.1.5") // Dependabot HIGH host confusion (< 3.1.5)
resolution("js-yaml", "4.3.1") // Dependabot HIGH quadratic CPU in !!omap (< 4.3.1)
resolution("body-parser", "1.20.6") // Dependabot LOW (< 1.20.6)
resolution("socket.io-parser", "4.2.7") // Dependabot HIGH memory-exhaustion DoS (< 4.2.7)
}
}