From eabbebd458142b2f9b832201b0a5f1bf6dcd0dfa Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Tue, 5 Dec 2017 16:15:49 +0100 Subject: [PATCH] Prepare intellij sdk deps in buildSrc --- buildSrc/build.gradle.kts | 4 + buildSrc/prepare-deps/dx/build.gradle.kts | 81 ++++++++++++++ .../intellij-sdk/build.gradle.kts | 104 ++++++++++++++++++ buildSrc/settings.gradle | 3 + compiler/tests-common/build.gradle.kts | 8 +- .../android-sdk/build.gradle.kts | 53 ++++----- 6 files changed, 223 insertions(+), 30 deletions(-) create mode 100644 buildSrc/prepare-deps/dx/build.gradle.kts create mode 100644 buildSrc/prepare-deps/intellij-sdk/build.gradle.kts create mode 100644 buildSrc/settings.gradle diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 2b634deb7ab..8316317ef9c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -31,6 +31,8 @@ plugins { `kotlin-dsl` } +extra["versions.intellij"] = "172.4343.14" + repositories { extra["buildSrcKotlinRepo"]?.let { maven(url = it) @@ -60,3 +62,5 @@ samWithReceiver { fun Project.`samWithReceiver`(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit = extensions.configure("samWithReceiver", configure) + +tasks["build"].dependsOn(":prepare-deps:dx:build") diff --git a/buildSrc/prepare-deps/dx/build.gradle.kts b/buildSrc/prepare-deps/dx/build.gradle.kts new file mode 100644 index 00000000000..d989c1ed56b --- /dev/null +++ b/buildSrc/prepare-deps/dx/build.gradle.kts @@ -0,0 +1,81 @@ + +import java.io.File +import org.gradle.internal.os.OperatingSystem +import org.gradle.jvm.tasks.Jar + +val toolsOs by lazy { + when { + OperatingSystem.current().isWindows -> "windows" + OperatingSystem.current().isMacOsX -> "macosx" + OperatingSystem.current().isLinux -> "linux" + else -> { + logger.error("Unknown operating system for android tools: ${OperatingSystem.current().name}") + "" + } + } +} + +val buildToolsVersion = "r23.0.1" + +repositories { + ivy { + artifactPattern("https://dl-ssl.google.com/android/repository/[artifact]_[revision](-[classifier]).[ext]") + artifactPattern("https://android.googlesource.com/platform/dalvik/+archive/android-5.0.0_r2/[artifact].[ext]") + } +} + +val buildToolsZip by configurations.creating +val dxSourcesTar by configurations.creating + +dependencies { + buildToolsZip("google:build-tools:$buildToolsVersion:$toolsOs@zip") + dxSourcesTar("google:dx:0@tar.gz") +} + +val unzipDxJar by tasks.creating { + dependsOn(buildToolsZip) + inputs.files(buildToolsZip) + val targetFile = File(buildDir, "dx.jar") + outputs.files(targetFile) + outputs.upToDateWhen { targetFile.exists() } // TODO: consider more precise check, e.g. hash-based + doFirst { + project.copy { + from(zipTree(buildToolsZip.singleFile).files) + include("**/dx.jar") + into(buildDir) + } + } +} + +val dxSourcesTargetDir = File(buildDir, "dx_src") + +val untarDxSources by tasks.creating { + dependsOn(dxSourcesTar) + inputs.files(dxSourcesTar) + outputs.files(dxSourcesTargetDir) + outputs.upToDateWhen { dxSourcesTargetDir.isDirectory } // TODO: consider more precise check, e.g. hash-based + doFirst { + project.copy { + from(tarTree(dxSourcesTar.singleFile)) + include("src/**") + includeEmptyDirs = false + into(dxSourcesTargetDir) + } + } +} + +val prepareDxSourcesJar by tasks.creating(Jar::class) { + dependsOn(untarDxSources) + from("$dxSourcesTargetDir/src") + destinationDir = buildDir + baseName = "dx" + classifier = "sources" +} + +val build by tasks.creating { + dependsOn(unzipDxJar, prepareDxSourcesJar) +} + +val clean by tasks.creating(Delete::class) { + delete(buildDir) +} diff --git a/buildSrc/prepare-deps/intellij-sdk/build.gradle.kts b/buildSrc/prepare-deps/intellij-sdk/build.gradle.kts new file mode 100644 index 00000000000..05dd76222c5 --- /dev/null +++ b/buildSrc/prepare-deps/intellij-sdk/build.gradle.kts @@ -0,0 +1,104 @@ + +import org.gradle.api.publish.ivy.internal.artifact.DefaultIvyArtifact +import org.gradle.api.publish.ivy.internal.publication.DefaultIvyConfiguration +import org.gradle.api.publish.ivy.internal.publication.DefaultIvyPublicationIdentity +import org.gradle.api.publish.ivy.internal.publisher.IvyDescriptorFileGenerator +import java.io.File +import org.gradle.internal.os.OperatingSystem + +val intellijRepo = "https://www.jetbrains.com/intellij-repository" +val intellijReleaseType = "releases" // or "snapshots" +val intellijSdkDependencyName = "ideaIC" // or "ideaIU" +val intellijVersion = rootProject.extra["versions.intellij"] as String + +repositories { + maven { setUrl("$intellijRepo/$intellijReleaseType") } +} + +val intellijSdk by configurations.creating +val intellijSources by configurations.creating +val jpsStandalone by configurations.creating +val jpsBuildTest by configurations.creating +val intellijCore by configurations.creating + +val repoDir = File(buildDir, "repo") + +dependencies { + intellijSdk("com.jetbrains.intellij.idea:$intellijSdkDependencyName:$intellijVersion") + intellijSources("com.jetbrains.intellij.idea:ideaIC:$intellijVersion:sources@jar") + jpsStandalone("com.jetbrains.intellij.idea:jps-standalone:$intellijVersion") + jpsBuildTest("com.jetbrains.intellij.idea:jps-build-test:$intellijVersion") + intellijCore("com.jetbrains.intellij.idea:intellij-core:$intellijVersion") +} + +fun Task.configureExtractFromConfigurationTask(sourceConfig: Configuration, extractor: (Configuration) -> Any) { + dependsOn(sourceConfig) + inputs.files(sourceConfig) + val targetDir = File(repoDir, sourceConfig.name) + outputs.dirs(targetDir) + doFirst { + project.copy { + from(extractor(sourceConfig)) + into(targetDir) + } + } +} + +val unzipIntellijSdk by tasks.creating { configureExtractFromConfigurationTask(intellijSdk) { zipTree(it.singleFile) } } + +val unzipIntellijCore by tasks.creating { configureExtractFromConfigurationTask(intellijCore) { zipTree(it.singleFile) } } + +val unzipJpsStandalone by tasks.creating { configureExtractFromConfigurationTask(jpsStandalone) { zipTree(it.singleFile) } } + +val copyIntellijSdkSources by tasks.creating { configureExtractFromConfigurationTask(intellijSources) { it.singleFile } } + +val copyJpsBuildTest by tasks.creating { configureExtractFromConfigurationTask(jpsBuildTest) { it.singleFile } } + +fun createIvyDependency(baseDir: File, file: File, configuration: String, extension: String?, type: String) : DefaultIvyArtifact { + val relativePath = baseDir.toURI().relativize(file.toURI()).path + val name = if (extension != null) relativePath.removeSuffix(".$extension") else relativePath + val artifact = DefaultIvyArtifact(file, name, extension, type, null) + artifact.conf = configuration + return artifact +} + +fun makeIvyXml(name: String, ivyFile: File, jarFiles: FileCollection, baseDir: File, sourcesJar: File): File { + val generator = IvyDescriptorFileGenerator(DefaultIvyPublicationIdentity("com.jetbrains", name, intellijVersion)) + generator.addConfiguration(DefaultIvyConfiguration("default")) + generator.addConfiguration(DefaultIvyConfiguration("compile")) + generator.addConfiguration(DefaultIvyConfiguration("sources")) + jarFiles.forEach { + generator.addArtifact(createIvyDependency(baseDir, it, "compile", "jar", "jar")) + } + val relativeSourcesPath = baseDir.toURI().relativize(sourcesJar.parentFile.toURI()).path + val sourcesArtifactName = sourcesJar.name.removeSuffix(".jar").substringBefore("-") + val artifact = DefaultIvyArtifact(sourcesJar, "$relativeSourcesPath/$sourcesArtifactName", "jar", "sources", "sources") + artifact.conf = "sources" + generator.addArtifact(artifact) + generator.writeTo(ivyFile) + return ivyFile +} + +val prepareIvyXml by tasks.creating { + dependsOn(unzipIntellijSdk, unzipIntellijCore, unzipJpsStandalone, copyIntellijSdkSources, copyJpsBuildTest) + inputs.dir(File(repoDir, intellijSdk.name)) + val flatDeps = listOf(intellijCore, jpsStandalone, jpsBuildTest) + flatDeps.forEach { + inputs.dir(File(repoDir, it.name)) + } + inputs.dir(File(repoDir, intellijSources.name)) + val ivyXml = File(repoDir, "ivy.xml") + outputs.files(ivyXml) + val sourcesFile = File(repoDir, "${intellijSources.name}/${intellijSources.singleFile.name}") + doFirst { + makeIvyXml(intellijSdk.name, File(repoDir, "${intellijSdk.name}.ivy.xml"), + files("$repoDir/${intellijSdk.name}/lib").filter { !it.name.startsWith("kotlin-") }, + repoDir, sourcesFile) + File(repoDir, "${intellijSdk.name}/plugins").listFiles { it: File -> it.isDirectory }.forEach { + makeIvyXml(it.name, File(repoDir, "intellij.plugin.${it.name}.ivy.xml"), files("$it/lib"), repoDir, sourcesFile) + } + flatDeps.forEach { + makeIvyXml(it.name, File(repoDir, "${it.name}.ivy.xml"), files("$repoDir/${it.name}"), repoDir, sourcesFile) + } + } +} \ No newline at end of file diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle new file mode 100644 index 00000000000..1675a57a972 --- /dev/null +++ b/buildSrc/settings.gradle @@ -0,0 +1,3 @@ + +include "prepare-deps:dx", + "prepare-deps:intellij-sdk" diff --git a/compiler/tests-common/build.gradle.kts b/compiler/tests-common/build.gradle.kts index 3f58b9b59b4..deba642dc5c 100644 --- a/compiler/tests-common/build.gradle.kts +++ b/compiler/tests-common/build.gradle.kts @@ -5,6 +5,12 @@ configureIntellijPlugin { setExtraDependencies("intellij-core") } +repositories { + ivy { + artifactPattern("${rootDir.absoluteFile.toURI().toURL()}/buildSrc/prepare-deps/dx/build/[artifact](-[classifier]).jar") + } +} + dependencies { testCompile(project(":core:descriptors")) testCompile(project(":core:descriptors.jvm")) @@ -29,7 +35,7 @@ dependencies { testCompile(projectTests(":compiler:tests-common-jvm6")) testCompileOnly(project(":kotlin-reflect-api")) testCompile(commonDep("junit:junit")) - testCompile(project(":custom-dependencies:android-sdk", configuration = "dxJar")) + testCompile("my-custom-deps:dx:0") } afterEvaluate { diff --git a/custom-dependencies/android-sdk/build.gradle.kts b/custom-dependencies/android-sdk/build.gradle.kts index 2ed1ff42aa8..91e0e568850 100644 --- a/custom-dependencies/android-sdk/build.gradle.kts +++ b/custom-dependencies/android-sdk/build.gradle.kts @@ -1,4 +1,5 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import java.io.File import org.gradle.internal.os.OperatingSystem @@ -17,13 +18,15 @@ val androidSdk by configurations.creating val androidJar by configurations.creating val dxJar by configurations.creating val androidPlatform by configurations.creating +val dxSources by configurations.creating val buildTools by configurations.creating val libsDestDir = File(buildDir, "libs") val sdkDestDir = File(buildDir, "androidSdk") data class LocMap(val name: String, val ver: String, val dest: String, val suffix: String, - val additionalConfig: Configuration? = null, val dirLevelsToSkit: Int = 0) + val additionalConfig: Configuration? = null, val dirLevelsToSkit: Int = 0, val ext: String = "zip", + val filter: CopySpec.() -> Unit = {}) val toolsOs = when { OperatingSystem.current().isWindows -> "windows" @@ -48,37 +51,46 @@ val prepareSdk by task { } fun LocMap.toDependency(): String = - "google:$name:$ver${suffix?.takeIf{ it.isNotEmpty() }?.let { ":$it" } ?: ""}@zip" + "google:$name:$ver${suffix?.takeIf{ it.isNotEmpty() }?.let { ":$it" } ?: ""}@$ext" -sdkLocMaps.forEach { - val id = "${it.name}_${it.ver}" +sdkLocMaps.forEach { locMap -> + val id = "${locMap.name}_${locMap.ver}" val cfg = configurations.create(id) - val dependency = it.toDependency() + val dependency = locMap.toDependency() dependencies.add(cfg.name, dependency) - val t = task("unzip_$id") { + val unzipTask = task("unzip_$id") { dependsOn(cfg) inputs.files(cfg) - val targetDir = file("$sdkDestDir/${it.dest}") + val targetDir = file("$sdkDestDir/${locMap.dest}") val targetFlagFile = File(targetDir, "$id.prepared") outputs.files(targetFlagFile) outputs.upToDateWhen { targetFlagFile.exists() } // TODO: consider more precise check, e.g. hash-based doFirst { project.copy { - from(zipTree(cfg.singleFile)) - if (it.dirLevelsToSkit > 0) { + when (locMap.ext) { + "zip" -> from(zipTree(cfg.singleFile)) + "tar.gz" -> from(tarTree(resources.gzip(cfg.singleFile))) + else -> throw GradleException("Don't know how to handle the extension \"${locMap.ext}\"") + } + locMap.filter.invoke(this) + if (locMap.dirLevelsToSkit > 0) { eachFile { - path = path.split("/").drop(it.dirLevelsToSkit).joinToString("/") + path = path.split("/").drop(locMap.dirLevelsToSkit).joinToString("/") + if (path.isBlank()) { + exclude() + } } } into(targetDir) } + targetFlagFile.writeText("prepared") } } - prepareSdk.dependsOn(t) + prepareSdk.dependsOn(unzipTask) - it.additionalConfig?.also { + locMap.additionalConfig?.also { dependencies.add(it.name, dependency) } } @@ -101,20 +113,6 @@ val extractAndroidJar by tasks.creating { } } -val extractDxJar by tasks.creating { - dependsOn(buildTools) - inputs.files(buildTools) - val targetFile = File(libsDestDir, "dx.jar") - outputs.files(targetFile) - outputs.upToDateWhen { targetFile.exists() } // TODO: consider more precise check, e.g. hash-based - doFirst { - project.copy { - from(zipTree(buildTools.singleFile).matching { include("**/dx.jar") }.files.first()) - into(libsDestDir) - } - } -} - artifacts.add(androidSdk.name, file("$sdkDestDir")) { builtBy(prepareSdk) } @@ -123,6 +121,3 @@ artifacts.add(androidJar.name, file("$libsDestDir/android.jar")) { builtBy(extractAndroidJar) } -artifacts.add(dxJar.name, file("$libsDestDir/dx.jar")) { - builtBy(extractDxJar) -}