import org.gradle.api.* import org.jetbrains.compose.internal.publishing.* plugins { signing } fun Task.dependsOnComposeTask(name: String) { dependsOn(project.composeBuild?.task(name) ?: return) } open class ComposePublishingTask : AbstractComposePublishingTask() { override fun dependsOnComposeTask(task: String) { dependsOn(project.composeBuild?.task(task) ?: return) } } val composeProperties = ComposeProperties(project) val isWebExist = project.composeBuild?.run { projectDir.resolve(".jbWebExistsMarker").exists() } ?: false val mainComponents = listOf( ComposeComponent(":compose:animation:animation"), ComposeComponent(":compose:animation:animation-core"), ComposeComponent(":compose:animation:animation-graphics", supportedPlatforms = ComposePlatforms.JVM_BASED), ComposeComponent(":compose:foundation:foundation"), ComposeComponent(":compose:foundation:foundation-layout"), ComposeComponent(":compose:material:material"), ComposeComponent(":compose:material3:material3", supportedPlatforms = ComposePlatforms.JVM_BASED), ComposeComponent(":compose:material:material-icons-core"), ComposeComponent(":compose:material:material-ripple"), ComposeComponent(":compose:runtime:runtime"), ComposeComponent(":compose:runtime:runtime-saveable"), ComposeComponent(":compose:ui:ui"), ComposeComponent(":compose:ui:ui-geometry"), ComposeComponent(":compose:ui:ui-graphics"), ComposeComponent(":compose:ui:ui-test", supportedPlatforms = ComposePlatforms.JVM_BASED), ComposeComponent(":compose:ui:ui-test-junit4", supportedPlatforms = ComposePlatforms.JVM_BASED), ComposeComponent(":compose:ui:ui-text"), ComposeComponent(":compose:ui:ui-tooling", supportedPlatforms = ComposePlatforms.JVM_BASED), ComposeComponent(":compose:ui:ui-tooling-preview", supportedPlatforms = ComposePlatforms.JVM_BASED), ComposeComponent(":compose:ui:ui-unit"), ComposeComponent(":compose:ui:ui-util", supportedPlatforms = ComposePlatforms.ALL), ) val iconsComponents = listOf( ComposeComponent(":compose:material:material-icons-extended", supportedPlatforms = ComposePlatforms.JVM_BASED), ) fun ComposePublishingTask.mainPublications() { publish(":compose:compiler:compiler", publications = listOf("Maven")) publish(":compose:compiler:compiler-hosted", publications = listOf("Maven")) publish( ":compose:ui:ui-tooling-data", onlyWithPlatforms = setOf(ComposePlatforms.AndroidRelease, ComposePlatforms.AndroidDebug), publications = listOf("Maven") ) publish( ":compose:desktop:desktop", onlyWithPlatforms = setOf(ComposePlatforms.Desktop), publications = listOf( "KotlinMultiplatform", "Jvm", "Jvmlinux-x64", "Jvmlinux-arm64", "Jvmmacos-x64", "Jvmmacos-arm64", "Jvmwindows-x64" ) ) mainComponents.forEach { publishMultiplatform(it) } } fun ComposePublishingTask.iconsPublications() { iconsComponents.forEach { publishMultiplatform(it) } } // To show all projects which use `xxx` task, run: // ./gradlew -p frameworks/support help --task xxx tasks.register("publishComposeJb", ComposePublishingTask::class) { repository = "MavenRepository" mainPublications() } tasks.register("publishComposeJbToMavenLocal", ComposePublishingTask::class) { repository = "MavenLocal" mainPublications() } // separate task that cannot be built in parallel (because it requires too much RAM). // should be run with "--max-workers=1" tasks.register("publishComposeJbExtendedIcons", ComposePublishingTask::class) { repository = "MavenRepository" iconsPublications() } tasks.register("publishComposeJbExtendedIconsToMavenLocal", ComposePublishingTask::class) { repository = "MavenLocal" iconsPublications() } tasks.register("testComposeJbDesktop") { dependsOnComposeTask(":compose:desktop:desktop:jvmTest") dependsOnComposeTask(":compose:animation:animation:desktopTest") dependsOnComposeTask(":compose:animation:animation-core:desktopTest") dependsOnComposeTask(":compose:ui:ui:desktopTest") dependsOnComposeTask(":compose:ui:ui-graphics:desktopTest") dependsOnComposeTask(":compose:ui:ui-text:desktopTest") dependsOnComposeTask(":compose:foundation:foundation:desktopTest") dependsOnComposeTask(":compose:foundation:foundation-layout:desktopTest") dependsOnComposeTask(":compose:material:material:desktopTest") dependsOnComposeTask(":compose:material:material-ripple:desktopTest") dependsOnComposeTask(":compose:runtime:runtime:desktopTest") dependsOnComposeTask(":compose:runtime:runtime-saveable:desktopTest") } if (isWebExist) { tasks.register("testComposeJbWeb") { dependsOnComposeTask(":compose:runtime:runtime:jsTest") dependsOnComposeTask(":compose:runtime:runtime:test") } } tasks.register("buildNativeDemo") { dependsOnComposeTask(":compose:native:demo:assemble") } tasks.register("testRuntimeNative") { dependsOnComposeTask(":compose:runtime:runtime:macosX64Test") } tasks.register("testComposeModules") { // used in https://github.com/JetBrains/androidx/tree/jb-main/.github/workflows // TODO: download robolectrict to run ui:ui:test // dependsOnComposeTask(":compose:ui:ui:test") dependsOnComposeTask(":compose:ui:ui-graphics:test") dependsOnComposeTask(":compose:ui:ui-geometry:test") dependsOnComposeTask(":compose:ui:ui-unit:test") dependsOnComposeTask(":compose:ui:ui-util:test") dependsOnComposeTask(":compose:runtime:runtime:test") dependsOnComposeTask(":compose:runtime:runtime-saveable:test") dependsOnComposeTask(":compose:material:material:test") dependsOnComposeTask(":compose:material:material-ripple:test") dependsOnComposeTask(":compose:foundation:foundation:test") dependsOnComposeTask(":compose:animation:animation:test") dependsOnComposeTask(":compose:animation:animation-core:test") dependsOnComposeTask(":compose:animation:animation-core:test") // TODO: enable ui:ui-text:test // dependsOnComposeTask(":compose:ui:ui-text:test") // compose/out/androidx/compose/ui/ui-text/build/intermediates/tmp/manifest/test/debug/tempFile1ProcessTestManifest10207049054096217572.xml Error: // android:exported needs to be explicitly specified for . Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. } tasks.register("run") { dependsOnComposeTask(":compose:desktop:desktop:desktop-samples:run") } val mavenCentral = MavenCentralProperties(project) if (mavenCentral.signArtifacts) { signing.useInMemoryPgpKeys( mavenCentral.signArtifactsKey.get(), mavenCentral.signArtifactsPassword.get() ) } val publishingDir = project.layout.buildDirectory.dir("publishing") val originalArtifactsRoot = publishingDir.map { it.dir("original") } val preparedArtifactsRoot = publishingDir.map { it.dir("prepared") } val modulesFile = publishingDir.map { it.file("modules.txt") } val findComposeModules by tasks.registering(FindModulesInSpaceTask::class) { requestedGroupId.set("org.jetbrains.compose") requestedVersion.set(mavenCentral.version) spaceInstanceUrl.set("https://public.jetbrains.space") spaceClientId.set(System.getenv("COMPOSE_REPO_USERNAME") ?: "") spaceClientSecret.set(System.getenv("COMPOSE_REPO_KEY") ?: "") spaceProjectId.set(System.getenv("COMPOSE_DEV_REPO_PROJECT_ID") ?: "") spaceRepoId.set(System.getenv("COMPOSE_DEV_REPO_REPO_ID") ?: "") modulesTxtFile.set(modulesFile) } val downloadArtifactsFromComposeDev by tasks.registering(DownloadFromSpaceMavenRepoTask::class) { dependsOn(findComposeModules) modulesToDownload.set(project.provider { readComposeModules(modulesFile, originalArtifactsRoot) }) spaceRepoUrl.set("https://maven.pkg.jetbrains.space/public/p/compose/dev") } val fixModulesBeforePublishing by tasks.registering(FixModulesBeforePublishingTask::class) { dependsOn(downloadArtifactsFromComposeDev) inputRepoDir.set(originalArtifactsRoot) outputRepoDir.set(preparedArtifactsRoot) } val reuploadArtifactsToMavenCentral by tasks.registering(UploadToSonatypeTask::class) { dependsOn(fixModulesBeforePublishing) version.set(mavenCentral.version) modulesToUpload.set(project.provider { readComposeModules(modulesFile, preparedArtifactsRoot) }) sonatypeServer.set("https://oss.sonatype.org") user.set(mavenCentral.user) password.set(mavenCentral.password) autoCommitOnSuccess.set(mavenCentral.autoCommitOnSuccess) stagingProfileName.set("org.jetbrains.compose") } fun readComposeModules( modulesFile: Provider, repoRoot: Provider ): List = modulesFile.get().asFile.readLines() .filter { it.isNotBlank() } .map { line -> val (group, artifact, version) = line.split(":") ModuleToUpload( groupId = group, artifactId = artifact, version = version, localDir = repoRoot.get().asFile.resolve("$group/$artifact/$version") ) }