diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts index 07b936eb186..5e28962011f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts @@ -311,6 +311,10 @@ tasks.named("check") { } tasks.withType { + // Disable KONAN_DATA_DIR env variable for all integration tests + // because we are using `konan.data.dir` gradle property instead + environment.remove("KONAN_DATA_DIR") + val noTestProperty = project.providers.gradleProperty("noTest") onlyIf { !noTestProperty.isPresent } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index 772bdad55d2..b74eeccdd61 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -28,10 +28,13 @@ import org.junit.Before import org.junit.runner.RunWith import java.io.File import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths import java.util.* import java.util.regex.Pattern import javax.xml.parsers.DocumentBuilderFactory import kotlin.collections.HashSet +import kotlin.io.path.absolutePathString import kotlin.io.path.isDirectory import kotlin.test.* @@ -273,6 +276,7 @@ abstract class BaseGradleIT { val useParsableDiagnosticsFormatting: Boolean = true, val showDiagnosticsStacktrace: Boolean? = false, // false by default to not clutter the testdata + stacktraces change often val stacktraceMode: String? = StacktraceOption.FULL_STACKTRACE_LONG_OPTION, + val konanDataDir: Path = Paths.get("build/.konan"), ) { val safeAndroidGradlePluginVersion: AGPVersion get() = androidGradlePluginVersion ?: error("AGP version is expected to be set") @@ -942,6 +946,8 @@ abstract class BaseGradleIT { add("-Pkotlin.internal.suppressGradlePluginErrors=PreHMPPFlagsError") } + add("-Pkonan.data.dir=${options.konanDataDir.absolutePathString()}") + // Workaround: override a console type set in the user machine gradle.properties (since Gradle 4.3): add("--console=plain") //The feature of failing the build on deprecation warnings is introduced in gradle 5.6 diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt index 676a01a43b9..dedc67a74ed 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt @@ -359,12 +359,14 @@ open class CommonizerIT : KGPBaseTest() { nativeProject("commonize-kt-48118-c-interop-in-common-main", gradleVersion) { reportSourceSetCommonizerDependencies { val upperMain = getCommonizerDependencies("upperMain") - upperMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy") - upperMain.onlyNativeDistributionDependencies().assertNotEmpty() + val konanDataDirProperty = buildOptions.konanDataDir + ?: error("konanDataDir must not be null in this test. Please set a custom konanDataDir property.") + upperMain.withoutNativeDistributionDependencies(konanDataDirProperty).assertDependencyFilesMatches(".*cinterop-dummy") + upperMain.onlyNativeDistributionDependencies(konanDataDirProperty).assertNotEmpty() val commonMain = getCommonizerDependencies("commonMain") - commonMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy") - commonMain.onlyNativeDistributionDependencies().assertNotEmpty() + commonMain.withoutNativeDistributionDependencies(konanDataDirProperty).assertDependencyFilesMatches(".*cinterop-dummy") + commonMain.onlyNativeDistributionDependencies(konanDataDirProperty).assertNotEmpty() } build(":compileCommonMainKotlinMetadata") @@ -407,13 +409,15 @@ open class CommonizerIT : KGPBaseTest() { nativeProject("commonize-kt-48138-nativeMain-nativeTest-different-targets", gradleVersion) { reportSourceSetCommonizerDependencies { val nativeMain = getCommonizerDependencies("nativeMain") - nativeMain.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy") - nativeMain.onlyNativeDistributionDependencies().assertNotEmpty() + val konanDataDirProperty = buildOptions.konanDataDir + ?: error("konanDataDir must not be null in this test. Please set a custom konanDataDir property.") + nativeMain.withoutNativeDistributionDependencies(konanDataDirProperty).assertDependencyFilesMatches(".*cinterop-dummy") + nativeMain.onlyNativeDistributionDependencies(konanDataDirProperty).assertNotEmpty() nativeMain.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64, MINGW_X64)) val nativeTest = getCommonizerDependencies("nativeTest") - nativeTest.onlyNativeDistributionDependencies().assertNotEmpty() - nativeTest.withoutNativeDistributionDependencies().assertDependencyFilesMatches(".*cinterop-dummy") + nativeTest.onlyNativeDistributionDependencies(konanDataDirProperty).assertNotEmpty() + nativeTest.withoutNativeDistributionDependencies(konanDataDirProperty).assertDependencyFilesMatches(".*cinterop-dummy") nativeTest.assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64)) } } @@ -523,36 +527,38 @@ open class CommonizerIT : KGPBaseTest() { getCommonizerDependencies("commonMain").assertEmpty() getCommonizerDependencies("commonTest").assertEmpty() - getCommonizerDependencies("nativeMain").withoutNativeDistributionDependencies().apply { + val konanDataDirProperty = buildOptions.konanDataDir + ?: error("konanDataDir must not be null in this test. Please set a custom konanDataDir property.") + getCommonizerDependencies("nativeMain").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper") assertTargetOnAllDependencies( CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64, MINGW_X64) ) } - getCommonizerDependencies("nativeTest").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("nativeTest").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*nativeTestHelper") assertTargetOnAllDependencies( CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64, MINGW_X64) ) } - getCommonizerDependencies("unixMain").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("unixMain").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper") assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64)) } - getCommonizerDependencies("unixTest").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("unixTest").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*nativeTestHelper") assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, LINUX_X64, LINUX_ARM64, MACOS_X64)) } - getCommonizerDependencies("linuxMain").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("linuxMain").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper") assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64)) } - getCommonizerDependencies("linuxTest").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("linuxTest").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*nativeTestHelper") assertTargetOnAllDependencies(CommonizerTarget(LINUX_X64, LINUX_ARM64)) } @@ -563,22 +569,22 @@ open class CommonizerIT : KGPBaseTest() { getCommonizerDependencies("linuxArm64Test").assertEmpty() if (isMac) { - getCommonizerDependencies("appleMain").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("appleMain").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*appleHelper") assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, MACOS_X64)) } - getCommonizerDependencies("appleTest").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("appleTest").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*appleHelper", ".*nativeTestHelper") assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64, MACOS_X64)) } - getCommonizerDependencies("iosMain").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("iosMain").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches(".*nativeHelper", ".*unixHelper", ".*appleHelper") assertTargetOnAllDependencies(CommonizerTarget(IOS_X64, IOS_ARM64)) } - getCommonizerDependencies("iosTest").withoutNativeDistributionDependencies().apply { + getCommonizerDependencies("iosTest").withoutNativeDistributionDependencies(konanDataDirProperty).apply { assertDependencyFilesMatches( ".*nativeHelper", ".*unixHelper", ".*appleHelper", ".*nativeTestHelper", ".*iosTestHelper" ) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt index 6a9e4c5c471..35cefc90a50 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt @@ -531,7 +531,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() { assertCompilerArguments(":compileCommonMainKotlinMetadata", "-language-version 1.7", "-api-version 1.7") } - build(":compileKotlinJvm", enableGradleDebug = true) { + build(":compileKotlinJvm") { assertCompilerArguments( ":compileKotlinJvm", "-language-version 1.8", diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt index e6270bfb600..bc4f61b9728 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ConfigurationCacheIT.kt @@ -97,7 +97,8 @@ class ConfigurationCacheIT : AbstractConfigurationCacheIT() { // Override kotlin native home location to be able to run clean native distribution commonization task // since by default it is global location on host val buildOptions = defaultBuildOptions.copy( - freeArgs = listOf("-Porg.jetbrains.kotlin.native.home=$konanHome") + freeArgs = listOf("-Porg.jetbrains.kotlin.native.home=$konanHome"), + konanDataDir = null ) build(":cleanNativeDistributionCommonization", buildOptions = buildOptions) { assertOutputContains("0 problems were found storing the configuration cache.") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppCInteropDependencyTransformationIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppCInteropDependencyTransformationIT.kt index f59bd50adec..968d4f9a796 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppCInteropDependencyTransformationIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppCInteropDependencyTransformationIT.kt @@ -136,7 +136,7 @@ abstract class MppCInteropDependencyTransformationIT : BaseGradleIT() { private fun WithSourceSetCommonizerDependencies.assertP2SourceSetDependencies() { listOf("nativeMain", "nativeTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies( CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64, MINGW_X64) @@ -145,26 +145,26 @@ abstract class MppCInteropDependencyTransformationIT : BaseGradleIT() { if (HostManager.hostIsMac) { listOf("appleAndLinuxMain", "appleAndLinuxTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies(CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64)) } listOf("appleMain", "appleTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies(CommonizerTarget(IOS_ARM64, IOS_X64, MACOS_X64)) } listOf("iosMain", "iosTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies(CommonizerTarget(IOS_ARM64, IOS_X64)) } } listOf("linuxMain", "linuxTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies(CommonizerTarget(LINUX_ARM64, LINUX_X64)) } @@ -176,7 +176,7 @@ abstract class MppCInteropDependencyTransformationIT : BaseGradleIT() { They will choose cinterops associated with 'nativeMain' */ listOf("nativeMain", "nativeTest", "windowsAndLinuxMain", "windowsAndLinuxTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies( CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64, MINGW_X64) @@ -185,13 +185,13 @@ abstract class MppCInteropDependencyTransformationIT : BaseGradleIT() { if (HostManager.hostIsMac) { listOf("appleAndLinuxMain", "appleAndLinuxTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies(CommonizerTarget(LINUX_ARM64, LINUX_X64, IOS_ARM64, IOS_X64, MACOS_X64)) } listOf("iosMain", "iosTest").forEach { sourceSetName -> - getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies() + getCommonizerDependencies(sourceSetName).withoutNativeDistributionDependencies(defaultBuildOptions().konanDataDir) .assertDependencyFilesMatches(".*cinterop-simple.*", ".*cinterop-withPosix.*") .assertTargetOnAllDependencies(CommonizerTarget(IOS_ARM64, IOS_X64)) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt index b536b63b0f4..9e45cca8d3f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/GeneralNativeIT.kt @@ -1121,7 +1121,7 @@ class GeneralNativeIT : BaseGradleIT() { "build", options = defaultBuildOptions().copy( forceOutputToStdout = true, - customEnvironmentVariables = mapOf("KONAN_DATA_DIR" to Files.createTempDirectory("konan-data-dir").absolutePathString()) + konanDataDir = Files.createTempDirectory("konan-data-dir").toAbsolutePath() ) ) { assertFailed() diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt index eee7136fbf0..9f09312f2af 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt @@ -1,133 +1,176 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.gradle.native -import org.jetbrains.kotlin.gradle.* -import org.jetbrains.kotlin.gradle.embedProject -import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.containsSequentially -import org.jetbrains.kotlin.gradle.native.GeneralNativeIT.Companion.withNativeCommandLineArguments -import org.jetbrains.kotlin.gradle.testbase.NativeToolKind -import org.jetbrains.kotlin.gradle.testbase.extractNativeCompilerCommandLineArguments -import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl -import org.jetbrains.kotlin.gradle.util.modify +import org.gradle.api.logging.LogLevel +import org.gradle.testkit.runner.BuildResult +import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.gradle.util.replaceFirst import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.Xcode -import org.jetbrains.kotlin.konan.target.XcodeVersion import org.jetbrains.kotlin.konan.target.presetName -import org.jetbrains.kotlin.konan.util.DependencyDirectories -import org.junit.Assume -import org.junit.BeforeClass -import org.junit.Test -import kotlin.test.assertTrue -import kotlin.test.BeforeTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assumptions +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.condition.OS +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path +import java.nio.file.Paths +import kotlin.io.path.absolutePathString +import kotlin.io.path.appendText +import kotlin.io.path.deleteRecursively -class NativeDownloadAndPlatformLibsIT : BaseGradleIT() { +// We temporarily disable it for windows until a proper fix is found for this issue: +// https://youtrack.jetbrains.com/issue/KT-60138/NativeDownloadAndPlatformLibsIT-fails-on-Windows-OS +@OsCondition( + supportedOn = [OS.MAC, OS.LINUX], enabledOnCI = [OS.MAC, OS.LINUX] +) +@DisplayName("Tests for K/N builds with native downloading and platform libs") +@NativeGradlePluginTests +class NativeDownloadAndPlatformLibsIT : KGPBaseTest() { companion object { - @BeforeClass - @JvmStatic - fun skipOnWindows() { - // This test class causes build timeouts on Windows CI machines. - // We temporarily disable it for windows until a proper fix is found. - Assume.assumeFalse(HostManager.hostIsMingw) - } - private const val KOTLIN_SPACE_DEV = "https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" private const val MAVEN_CENTRAL = "https://cache-redirector.jetbrains.com/maven-central" } - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.FOR_MPP_SUPPORT - + private val platformName: String = HostManager.platformName() private val currentCompilerVersion = NativeCompilerDownloader.DEFAULT_KONAN_VERSION - private fun platformLibrariesProject(vararg targets: String): Project = - transformProjectWithPluginsDsl("native-platform-libraries").apply { - setupWorkingDir() - gradleBuildScript().appendText( - targets.joinToString(prefix = "\n", separator = "\n") { - "kotlin.$it()" - } - ) - gradleProperties().apply { - configureJvmMemory() + override val defaultBuildOptions: BuildOptions + get() = super.defaultBuildOptions.copy( + // For each test in this class, we need to provide an isolated .konan directory, + // so we create it within each test project folder + konanDataDir = workingDir.resolve(".konan") + .toFile() + .apply { mkdirs() }.toPath() + ) + + @AfterEach + fun checkThatUserKonanDirIsEmptyAfterTest() { + val userHomeDir = System.getProperty("user.home") + assertFileNotExists(Paths.get("$userHomeDir/.konan/dependencies")) + assertFileNotExists(Paths.get("$userHomeDir/.konan/kotlin-native-prebuilt-$platformName-$currentCompilerVersion")) + } + + @DisplayName("Downloading K/N distribution in default .konan dir") + @GradleTest + fun testLibrariesGenerationInDefaultKonanDir(gradleVersion: GradleVersion) { + + checkThatUserKonanDirIsEmptyAfterTest() + + val userHomeDir = System.getProperty("user.home") + platformLibrariesProject("linuxX64", gradleVersion = gradleVersion) { + build("assemble", buildOptions = defaultBuildOptions.copy(konanDataDir = null)) { + assertOutputContains("Kotlin/Native distribution: .*kotlin-native-prebuilt-$platformName".toRegex()) + assertOutputDoesNotContain("Generate platform libraries for ") + + // checking that konan was downloaded and native dependencies were not downloaded into ~/.konan dir + assertDirectoryExists(Paths.get("$userHomeDir/.konan/dependencies")) + assertDirectoryExists(Paths.get("$userHomeDir/.konan/kotlin-native-prebuilt-$platformName-$currentCompilerVersion")) } } - private val platformName: String = HostManager.platformName() + // clean ~/.konan after test it should not be with all inheritors of KGPBaseTest + Paths.get("$userHomeDir/.konan/dependencies").deleteRecursively() + Paths.get("$userHomeDir/.konan/kotlin-native-prebuilt-$platformName-$currentCompilerVersion").deleteRecursively() - @BeforeTest - fun deleteInstalledCompilers() { - val currentCompilerDir = DependencyDirectories.localKonanDir - .resolve("kotlin-native-$platformName-$currentCompilerVersion") - val prebuiltDistDir = DependencyDirectories.localKonanDir - .resolve("kotlin-native-prebuilt-$platformName-$currentCompilerVersion") - - for (compilerDirectory in listOf(currentCompilerDir, prebuiltDistDir)) { - compilerDirectory.deleteRecursively() - } } - private fun Project.buildWithLightDist(vararg tasks: String, check: CompiledProject.() -> Unit) = - build(*tasks, "-Pkotlin.native.distribution.type=light", check = check) - - @Test - fun testNoGenerationByDefault() = with(platformLibrariesProject("linuxX64")) { - - - // Check that a prebuilt distribution is used by default. - build("assemble") { - assertSuccessful() - assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-prebuilt-$platformName".toRegex()) - assertNotContains("Generate platform libraries for ") - } - } - - @Test - fun testLibrariesGeneration() { - val rootProject = Project("native-platform-libraries").apply { - embedProject(Project("native-platform-libraries"), renameTo = "subproject") - gradleProperties().apply { - configureJvmMemory() + @OptIn(EnvironmentalVariablesOverride::class) + @DisplayName("K/N Gradle project build (on Linux or Mac) with a dependency from a Maven") + @GradleTest + fun testSetupCommonOptionsForCaches(gradleVersion: GradleVersion, @TempDir tempDir: Path) { + val anotherKonanDataDir = tempDir.resolve(".konan2") + nativeProject( + "native-with-maven-dependencies", + gradleVersion = gradleVersion, + environmentVariables = EnvironmentalVariables(Pair("KONAN_DATA_DIR", anotherKonanDataDir.absolutePathString())) + ) { + build( + "linkDebugExecutableNative", + buildOptions = defaultBuildOptions.copy( + nativeOptions = defaultBuildOptions.nativeOptions.copy( + cacheKind = null + ) + ) + ) { + assertOutputDoesNotContain("w: Failed to build cache") + assertTasksExecuted(":linkDebugExecutableNative") + assertDirectoryDoesNotExist(anotherKonanDataDir) } - gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl) - - gradleBuildScript().appendText("\nkotlin.linuxX64()\n") - gradleBuildScript("subproject").appendText("\nkotlin.linuxArm64()\n") } + } + + @DisplayName("Downloading K/N with custom konanDataDir property") + @GradleTest + fun testLibrariesGenerationInCustomKonanDir(gradleVersion: GradleVersion) { + platformLibrariesProject("linuxX64", gradleVersion = gradleVersion) { + build("assemble", buildOptions = defaultBuildOptions.copy(konanDataDir = workingDir.resolve(".konan"))) { + assertOutputContains("Kotlin/Native distribution: .*kotlin-native-prebuilt-$platformName".toRegex()) + assertOutputDoesNotContain("Generate platform libraries for ") + + // checking that konan was downloaded and native dependencies were not downloaded into ~/.konan dir + assertDirectoryExists(workingDir.resolve(".konan/dependencies")) + assertDirectoryExists(workingDir.resolve(".konan/kotlin-native-prebuilt-$platformName-$currentCompilerVersion")) + } + } + } + + @DisplayName("K/N distribution without platform libraries generation") + @GradleTest + fun testNoGenerationByDefault(gradleVersion: GradleVersion) { + platformLibrariesProject("linuxX64", gradleVersion = gradleVersion) { + build("assemble") { + assertOutputContains("Kotlin/Native distribution: .*kotlin-native-prebuilt-$platformName".toRegex()) + assertOutputDoesNotContain("Generate platform libraries for ") + } + } + } + + @DisplayName("K/N distribution with platform libraries generation") + @GradleTest + fun testLibrariesGeneration(gradleVersion: GradleVersion) { + nativeProject("native-platform-libraries", gradleVersion = gradleVersion) { + + includeOtherProjectAsSubmodule("native-platform-libraries", "", "subproject", true) + + buildGradleKts.appendText("\nkotlin.linuxX64()\n") + subProject("subproject").buildGradleKts.appendText("\nkotlin.linuxArm64()\n") - with(rootProject) { // Check that platform libraries are correctly generated for both root project and a subproject. buildWithLightDist("assemble") { - assertSuccessful() - assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-$platformName".toRegex()) - assertContains("Generate platform libraries for linux_x64") - assertContains("Generate platform libraries for linux_arm64") + assertOutputContains("Kotlin/Native distribution: .*kotlin-native-$platformName".toRegex()) + assertOutputContains("Generate platform libraries for linux_x64") + assertOutputContains("Generate platform libraries for linux_arm64") } // Check that we don't generate libraries during a second run. Don't clean to reduce execution time. buildWithLightDist("assemble") { - assertSuccessful() - assertNotContains("Generate platform libraries for ") + assertOutputDoesNotContain("Generate platform libraries for ") } } } - @Test - fun testLinkerArgsViaGradleProperties() { - with(Project("native-platform-libraries")) { - setupWorkingDir() - gradleProperties().apply { - configureJvmMemory() - appendText("\nkotlin.native.linkArgs=-Xfoo=bar -Xbaz=qux") - } - gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl) - gradleBuildScript().appendText( + @DisplayName("Link with args via gradle properties") + @GradleTest + fun testLinkerArgsViaGradleProperties(gradleVersion: GradleVersion) { + nativeProject("native-platform-libraries", gradleVersion = gradleVersion) { + + addPropertyToGradleProperties( + "kotlin.native.linkArgs", + mapOf( + "-Xfoo" to "-Xfoo=bar", + "-Xbaz" to "-Xbaz=qux" + ) + ) + + buildGradleKts.appendText( """ | |kotlin.linuxX64() { @@ -137,58 +180,165 @@ class NativeDownloadAndPlatformLibsIT : BaseGradleIT() { |} """.trimMargin() ) - build("linkDebugSharedLinuxX64") { - assertSuccessful() + + build("linkDebugSharedLinuxX64", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) { assertTasksExecuted( ":compileKotlinLinuxX64", ":linkDebugSharedLinuxX64" ) - withNativeCommandLineArguments(":linkDebugSharedLinuxX64") { - assertTrue(it.contains("-Xfoo=bar")) - assertTrue(it.contains("-Xbaz=qux")) - assertTrue(it.contains("-Xmen=pool")) + extractNativeTasksCommandLineArgumentsFromOutput(":linkDebugSharedLinuxX64") { + assertCommandLineArgumentsContain("-Xfoo=bar", "-Xbaz=qux", "-Xmen=pool") } - assertFileExists("/build/bin/linuxX64/debugShared/libnative_platform_libraries.so") - assertFileExists("/build/bin/linuxX64/debugShared/libnative_platform_libraries_api.h") + assertFileInProjectExists("build/bin/linuxX64/debugShared/libnative_platform_libraries.so") + assertFileInProjectExists("build/bin/linuxX64/debugShared/libnative_platform_libraries_api.h") } } } - @Test - fun testNoGenerationForUnsupportedHost() { - hostHaveUnsupportedTarget() - - platformLibrariesProject(KonanTarget.IOS_X64.presetName).buildWithLightDist("assemble") { - assertSuccessful() - assertNotContains("Generate platform libraries for ") + @OsCondition(supportedOn = [OS.LINUX], enabledOnCI = [OS.LINUX]) + @DisplayName("Assembling project generates no platform libraries for unsupported host") + @GradleTest + fun testNoGenerationForUnsupportedHost(gradleVersion: GradleVersion) { + platformLibrariesProject(KonanTarget.IOS_X64.presetName, gradleVersion = gradleVersion) { + buildWithLightDist("assemble") { + assertOutputDoesNotContain("Generate platform libraries for ") + } } } - @Test - fun testCanUsePrebuiltDistribution() = with(platformLibrariesProject("linuxX64")) { - build("assemble", "-Pkotlin.native.distribution.type=prebuilt") { - assertSuccessful() - assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-prebuilt-$platformName".toRegex()) - assertNotContains("Generate platform libraries for ") + @DisplayName("Build K/N project with prebuild type") + @GradleTest + fun testCanUsePrebuiltDistribution(gradleVersion: GradleVersion) { + platformLibrariesProject("linuxX64", gradleVersion = gradleVersion) { + build( + "assemble", buildOptions = defaultBuildOptions.copy( + nativeOptions = defaultBuildOptions.nativeOptions.copy( + distributionType = "prebuilt" + ) + ) + ) { + assertOutputContains("Kotlin/Native distribution: .*kotlin-native-prebuilt-$platformName".toRegex()) + assertOutputDoesNotContain("Generate platform libraries for ") + } } } - @Test - fun testCompilerReinstallation() = with(platformLibrariesProject("linuxX64")) { - // Install the compiler at the first time. Don't build to reduce execution time. - buildWithLightDist("tasks") { - assertSuccessful() - assertContains("Generate platform libraries for linux_x64") - } + @DisplayName("Build K/N project with compiler reinstallation") + @GradleTest + fun testCompilerReinstallation(gradleVersion: GradleVersion) { + platformLibrariesProject("linuxX64", gradleVersion = gradleVersion) { + // Install the compiler at the first time. Don't build to reduce execution time. + buildWithLightDist("tasks") { + assertOutputContains("Generate platform libraries for linux_x64") + } - // Reinstall the compiler. - buildWithLightDist("tasks", "-Pkotlin.native.reinstall=true") { - assertSuccessful() - assertContains("Unpack Kotlin/Native compiler to ") - assertContains("Generate platform libraries for linux_x64") + // Reinstall the compiler. + buildWithLightDist( + "tasks", + buildOptions = defaultBuildOptions.copy(nativeOptions = defaultBuildOptions.nativeOptions.copy(reinstall = true)) + ) { + assertOutputContains("Unpack Kotlin/Native compiler to ") + assertOutputContains("Generate platform libraries for linux_x64") + } } } + @DisplayName("Download prebuilt Native bundle with maven") + @GradleTest + fun shouldDownloadPrebuiltNativeBundleWithMaven(gradleVersion: GradleVersion) { + val maven = mavenUrl() + Assumptions.assumeTrue( + maven != MAVEN_CENTRAL, + "Don't run this test for build that are not yet published to central.\n" + + " We won't public K/N into Maven central until this task is completed: KTI-1067" + ) + + nativeProject("native-download-maven", gradleVersion = gradleVersion) { + + buildGradleKts.replaceFirst("// ", "maven(\"${maven}\")") + + build( + "assemble", + buildOptions = defaultBuildOptions.copy(nativeOptions = defaultBuildOptions.nativeOptions.copy(distributionDownloadFromMaven = true)) + ) { + assertOutputContains("Unpack Kotlin/Native compiler to ") + assertOutputDoesNotContain("Generate platform libraries for ") + } + } + } + + @DisplayName("Download light Native bundle with maven") + @RequiredXCodeVersion(minSupportedMajor = 14, minSupportedMinor = 1) + @GradleTest + fun shouldDownloadLightNativeBundleWithMaven(gradleVersion: GradleVersion) { + val maven = mavenUrl() + Assumptions.assumeTrue( + maven != MAVEN_CENTRAL, + "Don't run this test for build that are not yet published to central.\n" + + " We won't public K/N into Maven central until this task is completed: KTI-1067" + ) + + nativeProject("native-download-maven", gradleVersion = gradleVersion) { + buildGradleKts.replaceFirst("// ", "maven(\"${maven}\")") + val nativeOptions = defaultBuildOptions.nativeOptions.copy( + distributionType = "light", + distributionDownloadFromMaven = true + ) + build( + "assemble", + buildOptions = defaultBuildOptions.copy(nativeOptions = nativeOptions) + ) { + assertOutputContains("Unpack Kotlin/Native compiler to ") + assertOutputContains("Generate platform libraries for ") + } + } + } + + @DisplayName("Download from maven should fail if there is no such build in the default repos") + @GradleTest + fun shouldFailDownloadWithNoBuildInDefaultRepos(gradleVersion: GradleVersion) { + nativeProject("native-download-maven", gradleVersion = gradleVersion) { + val nativeOptions = BuildOptions.NativeOptions( + version = "1.8.0-dev-1234", + distributionDownloadFromMaven = true + ) + buildAndFail( + "assemble", + buildOptions = defaultBuildOptions.copy(nativeOptions = nativeOptions) + ) { + assertOutputContains("Could not find org.jetbrains.kotlin:kotlin-native") + } + } + } + + private fun platformLibrariesProject( + vararg targets: String, + gradleVersion: GradleVersion, + test: TestProject.() -> Unit = {}, + ) { + nativeProject("native-platform-libraries", gradleVersion) { + buildGradleKts.appendText( + targets.joinToString(prefix = "\n", separator = "\n") { + "kotlin.$it()" + } + ) + test() + } + } + + private fun TestProject.buildWithLightDist( + vararg tasks: String, + buildOptions: BuildOptions = defaultBuildOptions.copy(), + assertions: BuildResult.() -> Unit, + ) = + build( + *tasks, + buildOptions = buildOptions.copy( + nativeOptions = buildOptions.nativeOptions.copy(distributionType = "light") + ), + assertions = assertions + ) + private fun mavenUrl(): String { val versionPattern = "(\\d+)\\.(\\d+)(?:\\.(\\d+))?(?:-(\\p{Alpha}*\\p{Alnum}|[\\p{Alpha}-]*))?(?:-(\\d+))?".toRegex() val (_, _, _, metaString, build) = versionPattern.matchEntire(currentCompilerVersion)?.destructured @@ -200,68 +350,4 @@ class NativeDownloadAndPlatformLibsIT : BaseGradleIT() { } } - @Test - fun `download prebuilt Native bundle with maven`() { - val maven = mavenUrl() - // Don't run this test for build that are not yet published to central - Assume.assumeTrue(maven != MAVEN_CENTRAL) - - with(transformNativeTestProjectWithPluginDsl("native-download-maven")) { - gradleProperties().appendText( - "kotlin.native.distribution.downloadFromMaven=true" - ) - gradleBuildScript().let { - val text = it.readText().replaceFirst("// ", "maven(\"${maven}\")") - it.writeText(text) - } - build("assemble") { - assertSuccessful() - assertContains("Unpack Kotlin/Native compiler to ") - assertNotContains("Generate platform libraries for ") - } - } - } - - @Test - fun `download light Native bundle with maven`() { - val maven = mavenUrl() - // Don't run this test for build that are not yet published to central - Assume.assumeTrue(maven != MAVEN_CENTRAL) - - if (HostManager.hostIsMac) { - // Building platform libs require Xcode 14.1 - Assume.assumeTrue(Xcode.findCurrent().version >= XcodeVersion(14, 1)) - } - - with(transformNativeTestProjectWithPluginDsl("native-download-maven")) { - gradleProperties().appendText( - "kotlin.native.distribution.downloadFromMaven=true" - ) - gradleBuildScript().let { - val text = it.readText().replaceFirst("// ", "maven(\"${maven}\")") - it.writeText(text) - } - build("assemble", "-Pkotlin.native.distribution.type=light") { - assertSuccessful() - assertContains("Unpack Kotlin/Native compiler to ") - assertContains("Generate platform libraries for ") - } - } - } - - @Test - fun `download from maven should fail if there is no such build in the default repos`() { - with(transformNativeTestProjectWithPluginDsl("native-download-maven")) { - gradleProperties().appendText( - """ - kotlin.native.version=1.8.0-dev-1234 - kotlin.native.distribution.downloadFromMaven=true - """.trimIndent() - ) - build("assemble") { - assertContains("Could not find org.jetbrains.kotlin:kotlin-native") - assertFailed() - } - } - } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeWithСonfigurationCacheIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeWithСonfigurationCacheIT.kt index a53d1709ab0..59ae8e5f8bf 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeWithСonfigurationCacheIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeWithСonfigurationCacheIT.kt @@ -22,10 +22,14 @@ class NativeWithConfigurationCacheIT : KGPBaseTest() { @GradleTestVersions(minVersion = TestVersions.Gradle.G_8_1) // Since 8.1 Gradle on configuration cache it detects when the build logic accesses the "outside world" more strict https://docs.gradle.org/8.1.1/release-notes.html#configuration-inputs-detection-improvements @GradleTest fun testConfigurationCacheReusedSecondTime(gradleVersion: GradleVersion) { - nativeProject("native-with-configuration-cache", gradleVersion, enableGradleDebug = true) { + nativeProject("native-with-configuration-cache", gradleVersion) { // we need to download compiler on the first build, that is why we are setting custom konan home dir without any compiler inside val localKonan = workingDir.resolve(".konan") - build("help", "-Pkonan.data.dir=$localKonan") { + build( + "help", buildOptions = defaultBuildOptions.copy( + konanDataDir = localKonan + ) + ) { assertOutputContains("Configure project") assertOutputContains("Unpack Kotlin/Native compiler to") } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt index 10c6b07c351..f1e0c7703ed 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/BuildOptions.kt @@ -16,7 +16,10 @@ import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy import org.jetbrains.kotlin.gradle.report.BuildReportType import org.junit.jupiter.api.condition.OS +import java.nio.file.Path +import java.nio.file.Paths import java.util.* +import kotlin.io.path.absolutePathString data class BuildOptions( val logLevel: LogLevel = LogLevel.INFO, @@ -51,6 +54,7 @@ data class BuildOptions( val nativeOptions: NativeOptions = NativeOptions(), val compilerExecutionStrategy: KotlinCompilerExecutionStrategy? = null, val runViaBuildToolsApi: Boolean? = null, + val konanDataDir: Path? = konanDir, ) { val isK2ByDefault get() = KotlinVersion.DEFAULT >= KotlinVersion.KOTLIN_2_0 @@ -68,7 +72,7 @@ data class BuildOptions( val verbose: Boolean = false, val incrementalKapt: Boolean = false, val includeCompileClasspath: Boolean = false, - val classLoadersCacheSize: Int? = null + val classLoadersCacheSize: Int? = null, ) data class JsOptions( @@ -78,7 +82,7 @@ data class BuildOptions( ) data class NativeOptions( - val cacheKind: NativeCacheKind = NativeCacheKind.NONE, + val cacheKind: NativeCacheKind? = NativeCacheKind.NONE, val cocoapodsGenerateWrapper: Boolean? = null, val cocoapodsPlatform: String? = null, val cocoapodsConfiguration: String? = null, @@ -93,7 +97,7 @@ data class BuildOptions( ) fun toArguments( - gradleVersion: GradleVersion + gradleVersion: GradleVersion, ): List { val arguments = mutableListOf() when (logLevel) { @@ -209,6 +213,10 @@ data class BuildOptions( arguments.add("--$stacktraceMode") } + konanDataDir?.let { + arguments.add("-Pkonan.data.dir=${konanDataDir.absolutePathString()}") + } + arguments.addAll(freeArgs) return arguments.toList() @@ -218,7 +226,9 @@ data class BuildOptions( arguments: MutableList, ) { - arguments.add("-Pkotlin.native.cacheKind=${nativeOptions.cacheKind.name.lowercase()}") + nativeOptions.cacheKind?.let { + arguments.add("-Pkotlin.native.cacheKind=${nativeOptions.cacheKind.name.lowercase()}") + } nativeOptions.cocoapodsGenerateWrapper?.let { arguments.add("-Pkotlin.native.cocoapods.generate.wrapper=${it}") @@ -260,7 +270,7 @@ data class BuildOptions( fun BuildOptions.suppressDeprecationWarningsOn( @Suppress("UNUSED_PARAMETER") reason: String, // just to require specifying a reason for suppressing - predicate: (BuildOptions) -> Boolean + predicate: (BuildOptions) -> Boolean, ) = if (predicate(this)) { copy(warningMode = WarningMode.Summary) } else { @@ -270,7 +280,7 @@ fun BuildOptions.suppressDeprecationWarningsOn( fun BuildOptions.suppressDeprecationWarningsSinceGradleVersion( gradleVersion: String, currentGradleVersion: GradleVersion, - reason: String + reason: String, ) = suppressDeprecationWarningsOn(reason) { currentGradleVersion >= GradleVersion.version(gradleVersion) -} +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt index 9761ebb728a..e191fa8fbc4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt @@ -12,7 +12,6 @@ import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.ExtensionContext import org.junit.platform.commons.logging.LoggerFactory import java.lang.reflect.AnnotatedElement -import java.util.* /** * An annotation that enables tests to be executed on a specific operating system within a specific environment. @@ -45,9 +44,9 @@ internal class ExecutionOnOsCondition : ExecutionCondition { private val isUnderTeamcity = System.getenv("TEAMCITY_VERSION") != null - private val enabledOnCurrentOs = "Enabled on operating system: " + System.getProperty("os.name") - private val notSupportedOnCurrentOs = "Test is not supported on operating system: " + System.getProperty("os.name") - private val disabledForCI = "Disabled for operating system: " + System.getProperty("os.name") + " on CI" + private val enabledOnCurrentOs = "Enabled on operating system: ${System.getProperty("os.name")}" + private val notSupportedOnCurrentOs = "Test is not supported on operating system: ${System.getProperty("os.name")}" + private val disabledForCI = "Disabled for operating system: ${System.getProperty("os.name")} on CI" override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult { val annotation = findAnnotation(context) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt index 3206d411021..5e7367c9702 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt @@ -445,6 +445,8 @@ private fun TestProject.withBuildSummary( } } +val konanDir get() = Paths.get(".").resolve("build").resolve(".konan") + /** * On changing test kit dir location update related location in 'cleanTestKitCache' task. */ diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/xCodeVersion.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/xCodeVersion.kt new file mode 100644 index 00000000000..ebe5b1167ef --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/xCodeVersion.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.testbase + +import org.jetbrains.kotlin.konan.target.Xcode +import org.jetbrains.kotlin.konan.target.XcodeVersion +import org.jetbrains.kotlin.konan.target.HostManager +import org.junit.jupiter.api.extension.ConditionEvaluationResult +import org.junit.jupiter.api.extension.ExecutionCondition +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.ExtensionContext +import org.junit.platform.commons.logging.LoggerFactory + +/** + * Represents a custom annotation that specifies the minimum required XCode version for executing annotated code. + * NOTE: If the target platform is not Mac OS this annotation will be ignored. + * + * This annotation can be applied to functions, annotation classes, and classes. + * + * @param minSupportedMajor min supported XCode version's major part. XCode versions pattern: . + * @param minSupportedMinor min supported XCode version's major part. XCode versions pattern: . + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +@ExtendWith(RequiredXCodeExecutionCondition::class) +annotation class RequiredXCodeVersion( + val minSupportedMajor: Int, + val minSupportedMinor: Int, +) + +/** + * An implementation of the ExecutionCondition interface that checks if the test should be executed + * based on the current XCode version. + */ +internal class RequiredXCodeExecutionCondition : ExecutionCondition { + + private val logger = LoggerFactory.getLogger(ExecutionOnOsCondition::class.java) + + override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult { + val annotation = findAnnotation(context) + + return if (HostManager.hostIsMac) { + val minSupportedVersion = XcodeVersion(annotation.minSupportedMajor, annotation.minSupportedMinor) + val currentVersion = Xcode.findCurrent().version + if (currentVersion < minSupportedVersion) { + logger.info { generateUnsupportedVersionMessage(minSupportedVersion, currentVersion) } + ConditionEvaluationResult.disabled( + generateUnsupportedVersionMessage(minSupportedVersion, currentVersion) + ) + } else { + ConditionEvaluationResult.enabled(enabledOnCurrentVersionMessage(currentVersion)) + } + } else { + ConditionEvaluationResult.enabled("Test enabled because target OS is non MAC: ${System.getProperty("os.name")}") + } + } + + private fun enabledOnCurrentVersionMessage(currentVersion: Any?) = + "Enabled on XCode version: $currentVersion" + + private fun generateUnsupportedVersionMessage(minVersion: Any?, currentVersion: Any?) = + "Test is not supported with XCode older than $minVersion, but current is $currentVersion" + +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/reportSourceSetCommonizerDependencies.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/reportSourceSetCommonizerDependencies.kt index 94112b304da..4d1f060144f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/reportSourceSetCommonizerDependencies.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/reportSourceSetCommonizerDependencies.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.library.commonizerTarget import org.jetbrains.kotlin.library.resolveSingleFileKlib import org.jetbrains.kotlin.tooling.core.linearClosure import java.io.File +import java.nio.file.Path import javax.annotation.RegEx import kotlin.io.path.appendText import kotlin.test.fail @@ -35,22 +36,22 @@ data class SourceSetCommonizerDependencies( val dependencies: Set, ) { - fun withoutNativeDistributionDependencies(): SourceSetCommonizerDependencies { + fun withoutNativeDistributionDependencies(konanDataDirProperty: Path): SourceSetCommonizerDependencies { return SourceSetCommonizerDependencies( sourceSetName, - dependencies.filter { dependency -> !dependency.isFromNativeDistribution() }.toSet() + dependencies.filter { dependency -> !dependency.isFromNativeDistribution(konanDataDirProperty) }.toSet() ) } - fun onlyNativeDistributionDependencies(): SourceSetCommonizerDependencies { + fun onlyNativeDistributionDependencies(konanDataDirProperty: Path): SourceSetCommonizerDependencies { return SourceSetCommonizerDependencies( sourceSetName, - dependencies.filter { dependency -> dependency.isFromNativeDistribution() }.toSet() + dependencies.filter { dependency -> dependency.isFromNativeDistribution(konanDataDirProperty) }.toSet() ) } - private fun SourceSetCommonizerDependency.isFromNativeDistribution(): Boolean { - val konanDataDir = System.getenv("KONAN_DATA_DIR")?.let(::File) + private fun SourceSetCommonizerDependency.isFromNativeDistribution(konanDataDirProperty: Path?): Boolean { + val konanDataDir = konanDataDirProperty?.toRealPath()?.toFile() ?: System.getenv("KONAN_DATA_DIR")?.let(::File) if (konanDataDir != null) { return file.startsWith(konanDataDir) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-download-maven/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-download-maven/build.gradle.kts index 0f9adcece6a..91948d85f7a 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-download-maven/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-download-maven/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { - kotlin("multiplatform").version("") + kotlin("multiplatform") } repositories { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-platform-libraries/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-platform-libraries/build.gradle.kts index c7708c7a134..86870d98c8b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-platform-libraries/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-platform-libraries/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { - kotlin("multiplatform").version("") + kotlin("multiplatform") } repositories { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-with-maven-dependencies/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-with-maven-dependencies/build.gradle.kts new file mode 100644 index 00000000000..a7e6762f538 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-with-maven-dependencies/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + kotlin("multiplatform") +} + +repositories { + mavenLocal() + mavenCentral() +} + +kotlin { + ("native") { + binaries.executable() + } + + sourceSets.commonMain { + dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2") + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-with-maven-dependencies/src/nativeMain/kotlin/main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-with-maven-dependencies/src/nativeMain/kotlin/main.kt new file mode 100644 index 00000000000..c6e0437accf --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-with-maven-dependencies/src/nativeMain/kotlin/main.kt @@ -0,0 +1,3 @@ +fun main() { + println("Hello") +} \ No newline at end of file