Skip to content

Commit

Permalink
Improved build performance by pre-creating Ivy XML files in the extra…
Browse files Browse the repository at this point in the history
…cted IDE location.
  • Loading branch information
AlexanderBartash committed Oct 6, 2024
1 parent ba7fec0 commit f65a70d
Show file tree
Hide file tree
Showing 10 changed files with 666 additions and 274 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Changed

- Improved build performance by pre-creating Ivy XML files in the extracted IDE location.
- Improved build performance by making the local Ivy repository first in the list and prefixing all "fake" artifact groups with "com.jetbrains.localhost-only" and excluding that group from already declared remote repositories.

### Fixed
Expand Down
25 changes: 24 additions & 1 deletion api/IntelliJPlatformGradlePlugin.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public final class org/jetbrains/intellij/platform/gradle/BuildException : org/g
public final class org/jetbrains/intellij/platform/gradle/Constants {
public static final field CACHE_DIRECTORY Ljava/lang/String;
public static final field INSTANCE Lorg/jetbrains/intellij/platform/gradle/Constants;
public static final field IVY_FILES_DIRECTORY Ljava/lang/String;
}

public final class org/jetbrains/intellij/platform/gradle/Constants$Components {
Expand Down Expand Up @@ -167,6 +168,20 @@ public final class org/jetbrains/intellij/platform/gradle/Constants$Plugins$Exte
public static final field KOTLIN Ljava/lang/String;
}

public final class org/jetbrains/intellij/platform/gradle/Constants$Repositories {
public static final field ANDROID_STUDIO_INSTALLERS Ljava/lang/String;
public static final field INSTANCE Lorg/jetbrains/intellij/platform/gradle/Constants$Repositories;
public static final field INTELLI_J_PLATFORM_CUSTOM_PLUGIN Ljava/lang/String;
public static final field INTELLI_J_PLATFORM_DEPENDENCIES Ljava/lang/String;
public static final field INTELLI_J_REPOSITORY_NIGHTLY Ljava/lang/String;
public static final field INTELLI_J_REPOSITORY_RELEASES Ljava/lang/String;
public static final field INTELLI_J_REPOSITORY_SNAPSHOTS Ljava/lang/String;
public static final field JET_BRAINS_IDE_INSTALLERS Ljava/lang/String;
public static final field JET_BRAINS_MARKETPLACE Ljava/lang/String;
public static final field JET_BRAINS_RUNTIME Ljava/lang/String;
public static final field LOCAL_INTELLI_J_PLATFORM_ARTIFACTS Ljava/lang/String;
}

public final class org/jetbrains/intellij/platform/gradle/Constants$Sandbox {
public static final field CONFIG Ljava/lang/String;
public static final field CONTAINER Ljava/lang/String;
Expand Down Expand Up @@ -432,7 +447,7 @@ public abstract interface class org/jetbrains/intellij/platform/gradle/artifacts

public abstract class org/jetbrains/intellij/platform/gradle/artifacts/transform/ExtractorTransformer : org/gradle/api/artifacts/transform/TransformAction {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/artifacts/transform/ExtractorTransformer$Companion;
public fun <init> (Lorg/gradle/api/file/ArchiveOperations;Lorg/gradle/process/ExecOperations;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/file/FileSystemOperations;)V
public fun <init> (Lorg/gradle/api/file/ArchiveOperations;Lorg/gradle/process/ExecOperations;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/file/FileSystemOperations;)V
public abstract fun getInputArtifact ()Lorg/gradle/api/provider/Provider;
public fun transform (Lorg/gradle/api/artifacts/transform/TransformOutputs;)V
}
Expand Down Expand Up @@ -688,9 +703,13 @@ public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPla
}

public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformDependenciesHelper {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformDependenciesHelper$Companion;
public fun <init> (Lorg/gradle/api/artifacts/dsl/RepositoryHandler;Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/artifacts/dsl/DependencyHandler;Lorg/gradle/api/file/ProjectLayout;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/resources/ResourceHandler;Ljava/nio/file/Path;)V
}

public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformDependenciesHelper$Companion {
}

public abstract class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformExtension : org/gradle/api/plugins/ExtensionAware {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformExtension$Companion;
public fun <init> (Lorg/gradle/api/artifacts/ConfigurationContainer;Lorg/gradle/api/provider/ProviderFactory;Ljava/nio/file/Path;)V
Expand Down Expand Up @@ -955,9 +974,13 @@ public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPla
}

public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformRepositoriesHelper {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformRepositoriesHelper$Companion;
public fun <init> (Lorg/gradle/api/artifacts/dsl/RepositoryHandler;Lorg/gradle/api/provider/ProviderFactory;Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/flow/FlowScope;Lorg/gradle/api/flow/FlowProviders;Lorg/gradle/api/invocation/Gradle;Ljava/nio/file/Path;)V
}

public final class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformRepositoriesHelper$Companion {
}

public abstract class org/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformTestingExtension : org/gradle/api/plugins/ExtensionAware {
public static final field Companion Lorg/jetbrains/intellij/platform/gradle/extensions/IntelliJPlatformTestingExtension$Companion;
public fun <init> (Lorg/gradle/api/Project;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.jetbrains.intellij.platform.gradle.utils.toVersion

object Constants {
const val CACHE_DIRECTORY = ".intellijPlatform"
const val IVY_FILES_DIRECTORY = "localPlatformArtifacts"

object Plugin {
const val ID = "org.jetbrains.intellij.platform"
Expand Down Expand Up @@ -57,6 +58,19 @@ object Constants {
const val INTELLIJ_PLATFORM = "intellijPlatform"
}

object Repositories {
const val LOCAL_INTELLI_J_PLATFORM_ARTIFACTS = "Local IntelliJ Platform Artifacts Repository"
const val INTELLI_J_PLATFORM_CUSTOM_PLUGIN = "IntelliJ Platform Custom Plugin Repository"
const val JET_BRAINS_MARKETPLACE = "JetBrains Marketplace Repository"
const val INTELLI_J_PLATFORM_DEPENDENCIES = "IntelliJ Platform Dependencies Repository"
const val INTELLI_J_REPOSITORY_NIGHTLY = "IntelliJ Repository (Nightly)"
const val INTELLI_J_REPOSITORY_SNAPSHOTS = "IntelliJ Repository (Snapshots)"
const val INTELLI_J_REPOSITORY_RELEASES = "IntelliJ Repository (Releases)"
const val JET_BRAINS_RUNTIME = "JetBrains Runtime"
const val JET_BRAINS_IDE_INSTALLERS = "JetBrains IDE Installers"
const val ANDROID_STUDIO_INSTALLERS = "Android Studio Installers"
}

object Configurations {
const val INTELLIJ_PLATFORM_COMPOSED_JAR = "intellijPlatformComposedJar"
const val INTELLIJ_PLATFORM_DEPENDENCY_ARCHIVE = "intellijPlatformDependencyArchive"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ abstract class CollectorTransformer : TransformAction<CollectorTransformer.Param
// https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html#non-bundled-plugin
// For other plugins, we never (usually?) get into this block, because their Ivy artifacts already
// list jars, instead of pointing to a directory, see:
// See also org.jetbrains.intellij.platform.gradle.models.IvyModuleKt.explodeIntoIvyJarsArtifacts
// See also org.jetbrains.intellij.platform.gradle.models.IvyModuleKt.explodeIntoIvyJarsArtifactsRelativeTo
plugin.originalFile?.let { pluginPath ->
val jars = collectJars(pluginPath)
jars.forEach {
Expand All @@ -110,7 +110,7 @@ abstract class CollectorTransformer : TransformAction<CollectorTransformer.Param
companion object {
internal fun collectJars(path: Path): List<Path> {
val libPath = path.resolve("lib")
val libModulesPath = path.resolve("lib/modules")
val libModulesPath = libPath.resolve("modules")

return listOf(libPath, libModulesPath)
.mapNotNull { it.takeIfExists() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package org.jetbrains.intellij.platform.gradle.artifacts.transform

import com.jetbrains.plugin.structure.intellij.plugin.IdePluginManager
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.transform.InputArtifact
Expand All @@ -14,11 +15,20 @@ import org.gradle.api.file.FileSystemOperations
import org.gradle.api.file.FileTree
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Provider
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.tasks.Classpath
import org.gradle.kotlin.dsl.registerTransform
import org.gradle.process.ExecOperations
import org.gradle.work.DisableCachingByDefault
import org.jetbrains.intellij.platform.gradle.Constants
import org.jetbrains.intellij.platform.gradle.Constants.Configurations.Attributes
import org.jetbrains.intellij.platform.gradle.Constants.IVY_FILES_DIRECTORY
import org.jetbrains.intellij.platform.gradle.extensions.IntelliJPlatformDependenciesHelper
import org.jetbrains.intellij.platform.gradle.extensions.IntelliJPlatformDependenciesHelper.Companion.collectBundledPluginDependencies
import org.jetbrains.intellij.platform.gradle.extensions.IntelliJPlatformDependenciesHelper.Companion.getBundledPlugins
import org.jetbrains.intellij.platform.gradle.models.IvyModule
import org.jetbrains.intellij.platform.gradle.models.productInfo
import org.jetbrains.intellij.platform.gradle.models.toBundledIvyArtifactsRelativeTo
import org.jetbrains.intellij.platform.gradle.utils.Logger
import org.jetbrains.intellij.platform.gradle.utils.asPath
import org.jetbrains.intellij.platform.gradle.utils.resolvePlatformPath
Expand All @@ -36,6 +46,7 @@ abstract class ExtractorTransformer @Inject constructor(
private val archiveOperations: ArchiveOperations,
private val execOperations: ExecOperations,
private val objectFactory: ObjectFactory,
private val providerFactory: ProviderFactory,
private val fileSystemOperations: FileSystemOperations,
) : TransformAction<TransformParameters.None> {

Expand Down Expand Up @@ -106,16 +117,66 @@ abstract class ExtractorTransformer @Inject constructor(
commandLine("hdiutil", "detach", "-force", "-quiet", tempDirectory)
}
}

else -> {}
}

log.info("Extracting to '$targetDirectory' completed.")

createIvyXmls(targetDirectory.resolvePlatformPath())
}.onFailure {
log.error("${javaClass.canonicalName} execution failed.", it)
}
}

/**
* Pre-create Ivy XML files so that later this directory can be used as an Ivy repository without having to discover
* modules & plugins each time the build is run.
*/
private fun createIvyXmls(platformPath: Path) {
val isIde = platformPath.listDirectoryEntries().map { it.name }.containsAll(
listOf("bin", "lib", "plugins")
)
if (!isIde) {
log.info("The directory '$platformPath' is not an IDE, Ivy repository is not needed there.")
return
}

log.info("Creating an Ivy repository in '$platformPath'.")

val writtenIvyModules = HashSet<String>()
val productInfo = platformPath.productInfo()
val version = productInfo.buildNumber

val pluginManager = IdePluginManager.createManager(createTempDirectory())
val bundledPlugins = platformPath.getBundledPlugins(pluginManager)

for (plugin in bundledPlugins.values) {
val pluginId = plugin.pluginId
val pluginVersion = plugin.pluginVersion
val pluginPath = plugin.originalFile
if (null == pluginId || null == pluginVersion || null == pluginPath) {
continue
}

val group = Constants.Configurations.Dependencies.BUNDLED_PLUGIN_GROUP

val ivyDirPath = platformPath.resolve(IVY_FILES_DIRECTORY).absolute().normalize()
IntelliJPlatformDependenciesHelper.writeIvyModule(group, pluginId, version, writtenIvyModules, ivyDirPath) {
val publications = pluginPath.toBundledIvyArtifactsRelativeTo(platformPath)
val dependencies = plugin.collectBundledPluginDependencies(
emptyList(), productInfo, platformPath, bundledPlugins, writtenIvyModules, providerFactory, ivyDirPath
)
IvyModule(
info = IvyModule.Info(group, pluginId, version),
publications = publications,
dependencies = dependencies,
)
}
}

log.info("Creation of an Ivy repository in '$platformPath' finished.")
}

private fun dmgTree(path: Path): FileTree {
log.info("Extracting DMG archive '$path' to temporary directory.")

Expand Down Expand Up @@ -153,7 +214,7 @@ abstract class ExtractorTransformer @Inject constructor(
// such as `.background` meta-directory we have to exclude.
it.file.run {
(name == "Applications" && Files.isSymbolicLink(toPath()))
|| it.relativePath.startsWith('.')
|| it.relativePath.startsWith('.')
}
}
}
Expand All @@ -167,8 +228,7 @@ abstract class ExtractorTransformer @Inject constructor(
intellijPlatformTestClasspath: Configuration,
) {
Attributes.ArtifactType.Archives.forEach {
dependencies.artifactTypes.maybeCreate(it.toString())
.attributes.attribute(Attributes.extracted, false)
dependencies.artifactTypes.maybeCreate(it.toString()).attributes.attribute(Attributes.extracted, false)
}

listOf(compileClasspathConfiguration, testCompileClasspathConfiguration, intellijPlatformTestClasspath).forEach {
Expand Down
Loading

0 comments on commit f65a70d

Please sign in to comment.