Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,33 @@ class NativeDownloadAndPlatformLibsIT : KGPBaseTest() {
}
}

@DisplayName("Toolchain leaves a distribution installed by the legacy downloader alone (KT-86251)")
@GradleTest
fun testToolchainDoesNotReinstallOverLegacyInstallation(gradleVersion: GradleVersion) {
platformLibrariesProject("linuxX64", gradleVersion = gradleVersion) {
val konanDataDir = workingDir.resolve(".konan")

// this path has to write 'provisioned.ok' as well, that is the marker the toolchain looks for
build("tasks", buildOptions = defaultBuildOptions.copy(konanDataDir = konanDataDir)) {
assertOutputContains("Unpack Kotlin/Native compiler to ")
}

// the toolchain has to leave that installation alone. Unpacking on top of it happens in place, so
// anything reading the distribution at the same time sees half-written files.
build(
"downloadKotlinNativeDistribution",
buildOptions = defaultBuildOptions.copy(
konanDataDir = konanDataDir,
freeArgs = listOf("-Pkotlin.native.toolchain.enabled=true"),
),
) {
assertTasksExecuted(":downloadKotlinNativeDistribution")
assertOutputDoesNotContain("Native bundle files will be overwritten")
assertOutputDoesNotContain("Moving Kotlin/Native bundle from")
}
}
}

@DisplayName("K/N distribution with platform libraries generation")
@GradleTest
fun testLibrariesGeneration(gradleVersion: GradleVersion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter
import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionTypeProvider
import org.jetbrains.kotlin.gradle.targets.native.internal.PlatformLibrariesGenerator
import org.jetbrains.kotlin.gradle.targets.native.konanPropertiesBuildService
import org.jetbrains.kotlin.gradle.targets.native.toolchain.NativeVersionValueSource
import org.jetbrains.kotlin.internal.compilerRunner.native.nativeCompilerClasspath
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
Expand Down Expand Up @@ -202,13 +203,24 @@ class NativeCompilerDownloader(
it.into(tmpDir)
}
val compilerTmp = tmpDir.resolve(dependencyNameWithOsAndVersion)
if (!compilerTmp.renameTo(compilerDirectory)) {
project.copy {
it.from(compilerTmp)
it.into(compilerDirectory)
val installed = when {
compilerTmp.renameTo(compilerDirectory) -> true
!compilerDirectory.exists() -> {
project.copy {
it.from(compilerTmp)
it.into(compilerDirectory)
}
true
}
// another build got there first, copying on top would rewrite files it is reading (KT-86251)
else -> false
}
logger.debug("Moved Kotlin/Native compiler from $tmpDir to $compilerDirectory")
if (installed) {
// without the marker a toolchain build sharing this konan data dir unpacks the archive over the
// distribution again (KT-86251). Keep it the last thing written.
compilerDirectory.resolve(NativeVersionValueSource.MARKER_FILE).createNewFile()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I think the non-Gradle provisioner should also create such a file upon successful provisioning. And ideally, we should have only one provisioner implementation, which could be a BTA-X library.

}
} finally {
tmpDir.deleteRecursively()
}
Expand Down