diff --git a/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/JdkDownloader.kt b/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/JdkDownloader.kt index b8d46fdc1936..5599ce9d4a91 100644 --- a/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/JdkDownloader.kt +++ b/platform/build-scripts/downloader/src/org/jetbrains/intellij/build/dependencies/JdkDownloader.kt @@ -1,7 +1,9 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.intellij.build.dependencies -import org.jetbrains.intellij.build.downloadFileToCacheLocationSync +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import org.jetbrains.intellij.build.downloadFileToCacheLocation import java.net.URI import java.nio.file.Files import java.nio.file.Path @@ -11,7 +13,13 @@ import java.util.logging.Logger * Provides a current JBR SDK */ object JdkDownloader { - fun getJdkHome(communityRoot: BuildDependenciesCommunityRoot, infoLog: (String) -> Unit): Path { + fun blockingGetJdkHome(communityRoot: BuildDependenciesCommunityRoot, infoLog: (String) -> Unit): Path { + return runBlocking(Dispatchers.IO) { + getJdkHome(communityRoot, infoLog) + } + } + + suspend fun getJdkHome(communityRoot: BuildDependenciesCommunityRoot, infoLog: (String) -> Unit): Path { val os = OS.current val arch = Arch.current return getJdkHome(communityRoot = communityRoot, os = os, arch = arch, infoLog = infoLog) @@ -19,14 +27,14 @@ object JdkDownloader { @JvmStatic fun getJdkHome(communityRoot: BuildDependenciesCommunityRoot): Path { - return getJdkHome(communityRoot) { + return blockingGetJdkHome(communityRoot) { Logger.getLogger(JdkDownloader::class.java.name).info(it) } } - fun getJdkHome(communityRoot: BuildDependenciesCommunityRoot, os: OS, arch: Arch, infoLog: (String) -> Unit): Path { - val jdkUrl = getUrl(communityRoot, os, arch) - val jdkArchive = downloadFileToCacheLocationSync(url = jdkUrl.toString(), communityRoot = communityRoot) + suspend fun getJdkHome(communityRoot: BuildDependenciesCommunityRoot, os: OS, arch: Arch, infoLog: (String) -> Unit): Path { + val jdkUrl = getUrl(communityRoot = communityRoot, os = os, arch = arch) + val jdkArchive = downloadFileToCacheLocation(url = jdkUrl.toString(), communityRoot = communityRoot) val jdkExtracted = BuildDependenciesDownloader.extractFileToCacheLocation(communityRoot = communityRoot, archiveFile = jdkArchive, BuildDependenciesExtractOptions.STRIP_ROOT) diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/CompilationContext.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/CompilationContext.kt index d58ba768cbe5..be1d71c2d65a 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/CompilationContext.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/CompilationContext.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.intellij.build import org.jetbrains.intellij.build.dependencies.DependenciesProperties @@ -23,16 +23,15 @@ interface CompilationContext { fun isStepSkipped(step: String): Boolean = options.buildStepsToSkip.contains(step) /** - * Stable java executable from Java SDK used to compile project and do other stuff, - * not a JBR to assert compatibility with a standard Java Runtime + * Stable java executable from Java SDK used to compile a project and do other stuff, + * not a JBR to assert compatibility with a standard Java Runtime. */ val stableJavaExecutable: Path /** - * Stable JDK used to compile project and run utilities, - * not a JBR to assert compatibility with a standard Java Runtime + * Stable JDK used to compile a project and run utilities, not a JBR to assert compatibility with a standard Java Runtime. */ - val stableJdkHome: Path + suspend fun getStableJdkHome(): Path /** * @return directory with compiled project classes, 'url' attribute value of 'output' tag from .idea/misc.xml by default diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/GradleRunner.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/GradleRunner.kt index 4789049a1983..395df7ba393e 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/GradleRunner.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/GradleRunner.kt @@ -91,7 +91,7 @@ class GradleRunner( command.addAll(tasks) val gradleCall = { val processBuilder = ProcessBuilder(command).directory(gradleProjectDir.toFile()) - processBuilder.environment().put("JAVA_HOME", JdkDownloader.getJdkHome(communityRoot, Span.current()::addEvent).toString()) + processBuilder.environment().put("JAVA_HOME", JdkDownloader.blockingGetJdkHome(communityRoot, Span.current()::addEvent).toString()) processBuilder.inheritIO() synchronized(gradleProjectDir.toString().intern()) { processBuilder.start().waitFor() == 0 diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/CompilationContextImpl.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/CompilationContextImpl.kt index 083dd3b6bfd8..0b1d9d465d2a 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/CompilationContextImpl.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/CompilationContextImpl.kt @@ -105,12 +105,26 @@ class CompilationContextImpl private constructor( override val bundledRuntime: BundledRuntime override lateinit var compilationData: JpsCompilationData - override val stableJdkHome: Path by lazy { - JdkDownloader.getJdkHome(communityHome, Span.current()::addEvent) + @Volatile + private var cachedJdkHome: Path? = null + + override suspend fun getStableJdkHome(): Path { + var jdkHome = cachedJdkHome + if (jdkHome == null) { + jdkHome = JdkDownloader.getJdkHome(communityHome, Span.current()::addEvent) + cachedJdkHome = jdkHome + } + return jdkHome } override val stableJavaExecutable: Path by lazy { - JdkDownloader.getJavaExecutable(stableJdkHome) + var jdkHome = cachedJdkHome + if (jdkHome == null) { + // blocking doesn't matter, getStableJdkHome is mostly always called before + jdkHome = JdkDownloader.blockingGetJdkHome(communityHome, Span.current()::addEvent) + cachedJdkHome = jdkHome + } + JdkDownloader.getJavaExecutable(jdkHome) } init { @@ -350,8 +364,8 @@ private class BuildPathsImpl(communityHome: BuildDependenciesCommunityRoot, proj } } -private fun defineJavaSdk(context: CompilationContext) { - val homePath = context.stableJdkHome +private suspend fun defineJavaSdk(context: CompilationContext) { + val homePath = context.getStableJdkHome() val jbrVersionName = "jbr-17" defineJdk(global = context.projectModel.global, jdkName = jbrVersionName, homeDir = homePath) readModulesFromReleaseFile(model = context.projectModel, sdkName = jbrVersionName, sdkHome = homePath) @@ -373,8 +387,8 @@ private fun defineJavaSdk(context: CompilationContext) { } if (context.projectModel.global.libraryCollection.findLibrary(sdkName) == null) { - defineJdk(context.projectModel.global, sdkName, homePath) - readModulesFromReleaseFile(context.projectModel, sdkName, homePath) + defineJdk(global = context.projectModel.global, jdkName = sdkName, homeDir = homePath) + readModulesFromReleaseFile(model = context.projectModel, sdkName = sdkName, sdkHome = homePath) } } } diff --git a/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/dependencies/JdkDownloaderTest.kt b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/dependencies/JdkDownloaderTest.kt index d9acab21c498..6e523c14ba71 100644 --- a/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/dependencies/JdkDownloaderTest.kt +++ b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/dependencies/JdkDownloaderTest.kt @@ -1,6 +1,8 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.intellij.build.dependencies +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking import org.jetbrains.intellij.build.dependencies.BuildDependenciesManualRunOnly.communityRootFromWorkingDirectory import org.jetbrains.intellij.build.dependencies.JdkDownloader.getJavaExecutable import org.jetbrains.intellij.build.dependencies.JdkDownloader.getJdkHome @@ -12,14 +14,14 @@ class JdkDownloaderTest { @Test fun allJdkVariantsCouldBeDownloaded() { val communityRoot = communityRootFromWorkingDirectory - for (os in JdkDownloader.OS.values()) { + for (os in JdkDownloader.OS.entries) { for (arch in listOf(JdkDownloader.Arch.X86_64, JdkDownloader.Arch.ARM64)) { if (os === JdkDownloader.OS.WINDOWS && arch === JdkDownloader.Arch.ARM64) { // Not supported yet continue } - val jdkHome = getJdkHome(communityRoot, os, arch) { } + val jdkHome = runBlocking(Dispatchers.IO) { getJdkHome(communityRoot = communityRoot, os = os, arch = arch) { } } val javaExecutable = getJavaExecutable(jdkHome) Assert.assertTrue(Files.exists(javaExecutable)) }