Skip to content

Commit d994595

Browse files
committed
wip trying to get klib validation working for supported/unsupported targets...
1 parent 7d5c4ca commit d994595

File tree

3 files changed

+141
-59
lines changed

3 files changed

+141
-59
lines changed

Diff for: modules/bcv-gradle-plugin/src/main/kotlin/tasks/BCVApiGenerateTask.kt

+77-52
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import dev.adamko.kotlin.binary_compatibility_validator.internal.*
44
import dev.adamko.kotlin.binary_compatibility_validator.targets.BCVJvmTarget
55
import dev.adamko.kotlin.binary_compatibility_validator.targets.BCVKLibTarget
66
import dev.adamko.kotlin.binary_compatibility_validator.targets.BCVTarget
7-
import dev.adamko.kotlin.binary_compatibility_validator.workers.*
7+
import dev.adamko.kotlin.binary_compatibility_validator.workers.JvmSignaturesWorker
8+
import dev.adamko.kotlin.binary_compatibility_validator.workers.KLibInferSignaturesWorker
9+
import dev.adamko.kotlin.binary_compatibility_validator.workers.KLibMergeWorker
10+
import dev.adamko.kotlin.binary_compatibility_validator.workers.KLibSignaturesWorker
811
import java.io.File
912
import javax.inject.Inject
1013
import org.gradle.api.NamedDomainObjectContainer
@@ -71,17 +74,18 @@ constructor(
7174

7275
@TaskAction
7376
fun generate() {
74-
val workQueue = prepareWorkQueue()
75-
7677
prepareDirectories()
7778

78-
logger.lifecycle("[$path] got ${targets.size} targets : ${targets.joinToString { it.name }}")
79+
val workQueue = prepareWorkQueue()
7980

8081
val enabledTargets = targets.matching { it.enabled.getOrElse(true) }
8182

83+
logger.lifecycle("[$path] got ${targets.size} targets (${enabledTargets.size} enabled) : ${targets.joinToString { it.name }}")
84+
85+
val jvmTargets = enabledTargets.withType<BCVJvmTarget>().sorted()
8286
generateJvmTargets(
8387
workQueue = workQueue,
84-
jvmTargets = enabledTargets.withType<BCVJvmTarget>().sorted(),
88+
jvmTargets = jvmTargets,
8589
outputApiBuildDir = outputApiBuildDir.get().asFile,
8690
)
8791

@@ -90,7 +94,6 @@ constructor(
9094
val klibTargets = enabledTargets.withType<BCVKLibTarget>()
9195
.filter { it.klibFile.singleOrNull()?.exists() == true }
9296
.sorted()
93-
9497
generateKLibTargets(
9598
workQueue = workQueue,
9699
klibTargets = klibTargets,
@@ -103,26 +106,19 @@ constructor(
103106

104107

105108
private fun prepareWorkQueue(): WorkQueue {
106-
fs.delete { delete(temporaryDir) }
107-
temporaryDir.mkdirs()
108-
109109
return workers.classLoaderIsolation {
110110
classpath.from(runtimeClasspath)
111111
}
112112
}
113113

114114
private fun prepareDirectories() {
115-
val outputApiBuildDir = outputApiBuildDir.get()
116115
fs.delete { delete(outputApiBuildDir) }
117-
outputApiBuildDir.asFile.mkdirs()
116+
outputApiBuildDir.get().asFile.mkdirs()
118117

119-
fs.delete { delete(klibTargetsDir.supported) }
118+
fs.delete { delete(workDir) }
119+
workDir.mkdirs()
120120
klibTargetsDir.supported.mkdirs()
121-
122-
fs.delete { delete(klibTargetsDir.unsupported) }
123121
klibTargetsDir.unsupported.mkdirs()
124-
125-
fs.delete { delete(klibTargetsDir.extracted) }
126122
klibTargetsDir.extracted.mkdirs()
127123
}
128124

@@ -187,7 +183,7 @@ constructor(
187183
private fun generateKLibTargets(
188184
workQueue: WorkQueue,
189185
outputApiBuildDir: File,
190-
klibTargets: Collection<BCVKLibTarget>,
186+
klibTargets: List<BCVKLibTarget>,
191187
) {
192188
if (klibTargets.isEmpty()) {
193189
logger.info("[$path] No enabled KLib targets")
@@ -201,19 +197,30 @@ constructor(
201197
generateSupportedKLibTargets(workQueue, supportedKLibTargets)
202198
generateUnsupportedKLibTargets(workQueue, unsupportedKLibTargets)
203199

204-
workQueue.await()
200+
val allTargetDumpFiles = buildSet {
201+
addAll(klibTargetsDir.supported.walk().filter { it.isFile })
202+
addAll(klibTargetsDir.unsupported.walk().filter { it.isFile })
203+
}
205204

206-
val allTargetDumpFiles =
207-
klibTargetsDir.supported.walk().filter { it.isFile }.toSet() union
208-
klibTargetsDir.unsupported.walk().filter { it.isFile }.toSet()
205+
mergeDumpFiles(
206+
workQueue = workQueue,
207+
allTargetDumpFiles = allTargetDumpFiles,
208+
outputApiBuildDir = outputApiBuildDir,
209+
targets = klibTargets,
210+
strictValidation = strictKLibTargetValidation.get(),
211+
)
209212

210-
mergeDumpFiles(workQueue, allTargetDumpFiles, outputApiBuildDir)
213+
// workQueue.extract()
211214
}
212215

213216
private fun generateSupportedKLibTargets(
214217
workQueue: WorkQueue,
215218
supportedKLibTargets: List<BCVKLibTarget>
216219
) {
220+
if (supportedKLibTargets.isEmpty()) {
221+
logger.info("[$path] No supported enabled KLib targets")
222+
return
223+
}
217224
logger.lifecycle("[$path] generating ${supportedKLibTargets.size} supported KLib targets : ${supportedKLibTargets.joinToString { it.name }}")
218225

219226
val duration = measureTime {
@@ -233,6 +240,10 @@ constructor(
233240
workQueue: WorkQueue,
234241
unsupportedKLibTargets: List<BCVKLibTarget>
235242
) {
243+
if (unsupportedKLibTargets.isEmpty()) {
244+
logger.info("[$path] No unsupported enabled KLib targets")
245+
return
246+
}
236247
logger.lifecycle("[$path] generating ${unsupportedKLibTargets.size} unsupported KLib targets : ${unsupportedKLibTargets.joinToString { it.name }}")
237248

238249
val duration = measureTime {
@@ -245,6 +256,7 @@ constructor(
245256
outputDir = klibTargetsDir.unsupported,
246257
)
247258
}
259+
workQueue.await()
248260
}
249261

250262
logger.lifecycle("[$path] finished generating unsupported KLib targets in $duration")
@@ -254,20 +266,26 @@ constructor(
254266
private fun mergeDumpFiles(
255267
workQueue: WorkQueue,
256268
allTargetDumpFiles: Set<File>,
257-
outputApiBuildDir: File
269+
outputApiBuildDir: File,
270+
targets: List<BCVKLibTarget>,
271+
strictValidation: Boolean,
258272
) {
259273
logger.lifecycle("[$path] merging ${allTargetDumpFiles.size} dump files : ${allTargetDumpFiles.joinToString { it.name }}")
260274

261-
workQueue.merge(
262-
projectName.get(),
263-
targetDumpFiles = allTargetDumpFiles,
264-
outputDir = outputApiBuildDir,
265-
)
266-
workQueue.await()
275+
val duration = measureTime {
276+
workQueue.merge(
277+
projectName.get(),
278+
targetDumpFiles = allTargetDumpFiles,
279+
outputDir = outputApiBuildDir,
280+
supportedTargets = targets.filter { it.supportedByCurrentHost.get() }.map { it.targetName },
281+
strictValidation = strictValidation,
282+
)
283+
workQueue.await()
284+
}
267285

268286
if (logger.isLifecycleEnabled) {
269287
val fileNames = outputApiBuildDir.walk().filter { it.isFile }.toList()
270-
logger.lifecycle("[$path] merged ${allTargetDumpFiles.size} dump files : $fileNames")
288+
logger.lifecycle("[$path] merged ${allTargetDumpFiles.size} dump files in $duration : $fileNames")
271289
}
272290
}
273291

@@ -288,8 +306,7 @@ constructor(
288306

289307
this@worker.klib.set(target.klibFile.singleFile)
290308
this@worker.signatureVersion.set(target.signatureVersion)
291-
this@worker.strictValidation.set(target.strictValidation)
292-
// [email protected](target.supportedByCurrentHost)
309+
// [email protected](target.strictValidation)
293310

294311
// [email protected](klibTargets)
295312

@@ -325,37 +342,45 @@ constructor(
325342
projectName: String,
326343
targetDumpFiles: Set<File>,
327344
outputDir: File,
345+
supportedTargets: List<String>,
346+
strictValidation: Boolean,
328347
) {
329348
val task = this@BCVApiGenerateTask
330349

331350
@OptIn(BCVInternalApi::class)
332351
submit(KLibMergeWorker::class) worker@{
333-
this@worker.projectName.set(projectName)
352+
// [email protected](projectName)
334353
this@worker.taskPath.set(task.path)
335354

336-
this@worker.outputApiDir.set(outputDir)
355+
// [email protected](outputDir)
356+
this@worker.outputApiFile.set(
357+
outputDir.resolve("$projectName.klib.api")
358+
)
359+
360+
this@worker.strictValidation.set(strictValidation)
361+
this@worker.supportedTargets.set(supportedTargets)
337362

338363
this@worker.targetDumpFiles.from(targetDumpFiles)
339364
}
340365
}
341366

342-
@OptIn(BCVExperimentalApi::class)
343-
private fun WorkQueue.extract(
344-
target: BCVKLibTarget,
345-
targetDumpFiles: Set<File>,
346-
outputDir: File,
347-
) {
348-
val task = this@BCVApiGenerateTask
349-
350-
@OptIn(BCVInternalApi::class)
351-
submit(KLibExtractWorker::class) worker@{
352-
this@worker.taskPath.set(task.path)
353-
this@worker.strictValidation.set(target.strictValidation)
354-
355-
356-
357-
358-
}
359-
}
367+
// @OptIn(BCVExperimentalApi::class)
368+
// private fun WorkQueue.extract(
369+
// target: BCVKLibTarget,
370+
// targetDumpFiles: Set<File>,
371+
// outputDir: File,
372+
// ) {
373+
// val task = this@BCVApiGenerateTask
374+
//
375+
// @OptIn(BCVInternalApi::class)
376+
// submit(KLibExtractWorker::class) worker@{
377+
// [email protected](task.path)
378+
// [email protected](target.strictValidation)
379+
//
380+
381+
382+
383+
// }
384+
// }
360385
//endregion
361386
}

Diff for: modules/bcv-gradle-plugin/src/main/kotlin/workers/KLibMergeWorker.kt

+32-5
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,74 @@ import dev.adamko.kotlin.binary_compatibility_validator.internal.BCVExperimental
44
import dev.adamko.kotlin.binary_compatibility_validator.internal.BCVInternalApi
55
import java.io.Serializable
66
import kotlinx.validation.ExperimentalBCVApi
7+
import kotlinx.validation.KlibValidationSettings
78
import kotlinx.validation.api.klib.KlibDump
9+
import kotlinx.validation.api.klib.KlibTarget
810
import kotlinx.validation.api.klib.saveTo
911
import org.gradle.api.file.ConfigurableFileCollection
10-
import org.gradle.api.file.DirectoryProperty
12+
import org.gradle.api.file.RegularFileProperty
1113
import org.gradle.api.logging.Logger
1214
import org.gradle.api.logging.Logging
1315
import org.gradle.api.provider.Property
16+
import org.gradle.api.provider.SetProperty
1417
import org.gradle.workers.WorkAction
1518
import org.gradle.workers.WorkParameters
1619

1720
@BCVInternalApi
1821
@BCVExperimentalApi
1922
@OptIn(ExperimentalBCVApi::class)
2023
abstract class KLibMergeWorker : WorkAction<KLibMergeWorker.Parameters> {
24+
// TODO rename 'Merge' to something that represents 'Merge' and 'Extract'... 'MergeSupported'?
2125

2226
@BCVInternalApi
2327
interface Parameters : WorkParameters, Serializable {
24-
val projectName: Property<String>
28+
// val projectName: Property<String>
2529

26-
val outputApiDir: DirectoryProperty
30+
val outputApiFile: RegularFileProperty
2731

2832
val targetDumpFiles: ConfigurableFileCollection
2933

34+
/** Provider returning targets supported by the host compiler. */
35+
val supportedTargets: SetProperty<String>
36+
37+
/** Refer to [KlibValidationSettings.strictValidation] for details. */
38+
val strictValidation: Property<Boolean>
39+
3040
/**
3141
* [Task path][org.gradle.api.Task.getPath] of the task that invoked this worker,
3242
* for log messages
3343
*/
3444
val taskPath: Property<String>
3545
}
3646

47+
private val taskPath: String get() = parameters.taskPath.get()
48+
3749
override fun execute() {
50+
logger.info("[${taskPath}] merging dump files ${parameters.targetDumpFiles} ")
51+
3852
val sourceFiles = parameters.targetDumpFiles.asFileTree
39-
val outputFile = parameters.outputApiDir.get().asFile.resolve(parameters.projectName.get() + ".klib.api")
53+
// val outputFile = parameters.outputApiDir.get().asFile.resolve(parameters.projectName.get() + ".klib.api")
54+
val outputApiFile = parameters.outputApiFile.get().asFile
55+
56+
57+
val supportedTargets = parameters.supportedTargets.get().map { KlibTarget.parse(it).targetName }
4058

4159
val dump = KlibDump()
4260

4361
sourceFiles.forEach { dumpFile ->
4462
dump.merge(dumpFile, dumpFile.name.substringBefore(".klib.api"))
4563
}
4664

47-
dump.saveTo(outputFile)
65+
// // Filter out only unsupported files.
66+
// // That ensures that target renaming will be caught and reported as a change.
67+
// val unsupportedTargets = dump.targets.filter { it.targetName !in supportedTargets }
68+
//
69+
//// if (targetsToRemove.isNotEmpty() && parameters.strictValidation.get()) {
70+
//// error("Validation could not be performed as some targets are not available and strictValidation mode is enabled")
71+
//// }
72+
// dump.remove(unsupportedTargets)
73+
74+
dump.saveTo(outputApiFile)
4875
}
4976

5077
@BCVInternalApi

Diff for: modules/bcv-gradle-plugin/src/main/kotlin/workers/KLibSignaturesWorker.kt

+32-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dev.adamko.kotlin.binary_compatibility_validator.workers
33
import dev.adamko.kotlin.binary_compatibility_validator.internal.BCVExperimentalApi
44
import dev.adamko.kotlin.binary_compatibility_validator.internal.BCVInternalApi
55
import dev.adamko.kotlin.binary_compatibility_validator.targets.KLibSignatureVersion
6+
import java.io.File
67
import java.io.Serializable
78
import kotlinx.validation.ExperimentalBCVApi
89
import kotlinx.validation.api.klib.*
@@ -32,7 +33,8 @@ abstract class KLibSignaturesWorker : WorkAction<KLibSignaturesWorker.Parameters
3233
val ignoredClasses: SetProperty<String>
3334

3435
val signatureVersion: Property<KLibSignatureVersion>
35-
val strictValidation: Property<Boolean>
36+
// val strictValidation: Property<Boolean>
37+
val supportedByCurrentHost: Property<Boolean>
3638

3739
/**
3840
* [Task path][org.gradle.api.Task.getPath] of the task that invoked this worker,
@@ -45,6 +47,14 @@ abstract class KLibSignaturesWorker : WorkAction<KLibSignaturesWorker.Parameters
4547
val outputFile = parameters.outputApiDir.asFile.get()
4648
.resolve("${parameters.targetName.get()}.klib.api")
4749

50+
dump(outputFile)
51+
52+
// extract(outputFile)
53+
}
54+
55+
private fun dump(
56+
outputAbiFile: File,
57+
) {
4858
val filters = KLibDumpFilters {
4959
ignoredClasses += parameters.ignoredClasses.get()
5060
ignoredPackages += parameters.ignoredPackages.get()
@@ -59,8 +69,28 @@ abstract class KLibSignaturesWorker : WorkAction<KLibSignaturesWorker.Parameters
5969
configurableTargetName = parameters.targetName.get(),
6070
filters = filters,
6171
)
72+
dump.saveTo(outputAbiFile)
73+
}
74+
75+
private fun extract(
76+
abiFile: File,
77+
) {
78+
// val supportedTargets = parameters.supportedTargets.get()
79+
// val strictValidation = parameters.strictValidation.getOrElse(false)
6280

63-
dump.saveTo(outputFile)
81+
if (abiFile.length() == 0L) {
82+
error("Project ABI file $abiFile is empty")
83+
}
84+
val dump = KlibDump.from(abiFile)
85+
val enabledTarget = KlibTarget.parse(parameters.targetName.get())
86+
// Filter out only unsupported files.
87+
// That ensures that target renaming will be caught and reported as a change.
88+
// val targetsToRemove = dump.targets.filter { it.targetName !in enabledTargets }
89+
// if (targetsToRemove.isNotEmpty() && strictValidation) {
90+
// error("Validation could not be performed as some targets are not available and strictValidation mode is enabled")
91+
// }
92+
// dump.remove(targetsToRemove)
93+
dump.saveTo(abiFile)
6494
}
6595

6696
@BCVInternalApi

0 commit comments

Comments
 (0)