Gradle, native: Allow user to force old behaviour of link tasks
We leave an ability to build final native binaries directly from sources instead of building them from a klib. Thus we allow a user to workaround possible bugs related to building a final binary from a klib (-Xinclude compiler flag).
This commit is contained in:
+39
-15
@@ -934,20 +934,20 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
@Test
|
@Test
|
||||||
fun testNativeBinaryGroovyDSL() = doTestNativeBinaryDSL("groovy-dsl")
|
fun testNativeBinaryGroovyDSL() = doTestNativeBinaryDSL("groovy-dsl")
|
||||||
|
|
||||||
|
private fun CompiledProject.checkNativeCommandLineFor(vararg taskPaths: String, check: (String) -> Unit) = taskPaths.forEach { taskPath ->
|
||||||
|
val commandLine = output.lineSequence().dropWhile {
|
||||||
|
!it.contains("Executing actions for task '$taskPath'")
|
||||||
|
}.first {
|
||||||
|
it.contains("Run tool: konanc")
|
||||||
|
}
|
||||||
|
check(commandLine)
|
||||||
|
}
|
||||||
|
|
||||||
private fun doTestNativeBinaryDSL(
|
private fun doTestNativeBinaryDSL(
|
||||||
projectName: String,
|
projectName: String,
|
||||||
gradleVersionRequired: GradleVersionRequired = gradleVersion
|
gradleVersionRequired: GradleVersionRequired = gradleVersion
|
||||||
) = with(transformProjectWithPluginsDsl(projectName, gradleVersionRequired, "new-mpp-native-binaries")) {
|
) = with(transformProjectWithPluginsDsl(projectName, gradleVersionRequired, "new-mpp-native-binaries")) {
|
||||||
|
|
||||||
fun CompiledProject.checkCommandLineFor(vararg taskPaths: String, check: (String) -> Unit) = taskPaths.forEach { taskPath ->
|
|
||||||
val commandLine = output.lineSequence().dropWhile {
|
|
||||||
!it.contains("Executing actions for task '$taskPath'")
|
|
||||||
}.first {
|
|
||||||
it.contains("Run tool: konanc")
|
|
||||||
}
|
|
||||||
check(commandLine)
|
|
||||||
}
|
|
||||||
|
|
||||||
val hostSuffix = nativeHostTargetName.capitalize()
|
val hostSuffix = nativeHostTargetName.capitalize()
|
||||||
val binaries = mutableListOf(
|
val binaries = mutableListOf(
|
||||||
"debugExecutable" to "native-binary",
|
"debugExecutable" to "native-binary",
|
||||||
@@ -1013,7 +1013,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
// Check that kotlinOptions work fine for a compilation.
|
// Check that kotlinOptions work fine for a compilation.
|
||||||
build(compileTask) {
|
build(compileTask) {
|
||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
checkCommandLineFor(":$compileTask") {
|
checkNativeCommandLineFor(":$compileTask") {
|
||||||
assertTrue(it.contains("-verbose"))
|
assertTrue(it.contains("-verbose"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1032,7 +1032,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
build("runTest2ReleaseExecutable$hostSuffix") {
|
build("runTest2ReleaseExecutable$hostSuffix") {
|
||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
assertTasksExecuted(":$compileTestTask")
|
assertTasksExecuted(":$compileTestTask")
|
||||||
checkCommandLineFor(":linkTest2ReleaseExecutable$hostSuffix") {
|
checkNativeCommandLineFor(":linkTest2ReleaseExecutable$hostSuffix") {
|
||||||
assertTrue(it.contains("-tr"))
|
assertTrue(it.contains("-tr"))
|
||||||
assertTrue(it.contains("-Xtime"))
|
assertTrue(it.contains("-Xtime"))
|
||||||
// Check that kotlinOptions of the compilation don't affect the binary.
|
// Check that kotlinOptions of the compilation don't affect the binary.
|
||||||
@@ -1057,7 +1057,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
fileInWorkingDir("build/bin/ios/releaseFramework/native_binary.framework/Headers/native_binary.h")
|
fileInWorkingDir("build/bin/ios/releaseFramework/native_binary.framework/Headers/native_binary.h")
|
||||||
.readText().contains("+ (int32_t)exported")
|
.readText().contains("+ (int32_t)exported")
|
||||||
// Check that by default release frameworks have bitcode embedded.
|
// Check that by default release frameworks have bitcode embedded.
|
||||||
checkCommandLineFor(":linkReleaseFrameworkIos") {
|
checkNativeCommandLineFor(":linkReleaseFrameworkIos") {
|
||||||
assertTrue(it.contains("-Xembed-bitcode"))
|
assertTrue(it.contains("-Xembed-bitcode"))
|
||||||
assertTrue(it.contains("-opt"))
|
assertTrue(it.contains("-opt"))
|
||||||
}
|
}
|
||||||
@@ -1070,7 +1070,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
fileInWorkingDir("build/bin/ios/debugFramework/native_binary.framework/Headers/native_binary.h")
|
fileInWorkingDir("build/bin/ios/debugFramework/native_binary.framework/Headers/native_binary.h")
|
||||||
.readText().contains("+ (int32_t)exported")
|
.readText().contains("+ (int32_t)exported")
|
||||||
// Check that by default debug frameworks have bitcode marker embedded.
|
// Check that by default debug frameworks have bitcode marker embedded.
|
||||||
checkCommandLineFor(":linkDebugFrameworkIos") {
|
checkNativeCommandLineFor(":linkDebugFrameworkIos") {
|
||||||
assertTrue(it.contains("-Xembed-bitcode-marker"))
|
assertTrue(it.contains("-Xembed-bitcode-marker"))
|
||||||
assertTrue(it.contains("-g"))
|
assertTrue(it.contains("-g"))
|
||||||
}
|
}
|
||||||
@@ -1079,7 +1079,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
// Check manual disabling bitcode embedding, custom command line args and building a static framework.
|
// Check manual disabling bitcode embedding, custom command line args and building a static framework.
|
||||||
build("linkCustomReleaseFrameworkIos") {
|
build("linkCustomReleaseFrameworkIos") {
|
||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
checkCommandLineFor(":linkCustomReleaseFrameworkIos") {
|
checkNativeCommandLineFor(":linkCustomReleaseFrameworkIos") {
|
||||||
assertTrue(it.contains("-linker-option -L."))
|
assertTrue(it.contains("-linker-option -L."))
|
||||||
assertTrue(it.contains("-Xtime"))
|
assertTrue(it.contains("-Xtime"))
|
||||||
assertTrue(it.contains("-Xstatic-framework"))
|
assertTrue(it.contains("-Xstatic-framework"))
|
||||||
@@ -1093,7 +1093,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
assertFileExists("build/bin/iosSim/releaseFramework/native_binary.framework")
|
assertFileExists("build/bin/iosSim/releaseFramework/native_binary.framework")
|
||||||
assertFileExists("build/bin/iosSim/debugFramework/native_binary.framework")
|
assertFileExists("build/bin/iosSim/debugFramework/native_binary.framework")
|
||||||
checkCommandLineFor(":linkReleaseFrameworkIosSim", ":linkDebugFrameworkIosSim") {
|
checkNativeCommandLineFor(":linkReleaseFrameworkIosSim", ":linkDebugFrameworkIosSim") {
|
||||||
assertFalse(it.contains("-Xembed-bitcode"))
|
assertFalse(it.contains("-Xembed-bitcode"))
|
||||||
assertFalse(it.contains("-Xembed-bitcode-marker"))
|
assertFalse(it.contains("-Xembed-bitcode-marker"))
|
||||||
}
|
}
|
||||||
@@ -1117,6 +1117,30 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that we still can build binaries from sources if the corresponding property is specified.
|
||||||
|
// TODO: Drop in 1.3.70.
|
||||||
|
@Test
|
||||||
|
fun testLinkNativeBinaryFromSources() = with(
|
||||||
|
transformProjectWithPluginsDsl("groovy-dsl", gradleVersion, "new-mpp-native-binaries")
|
||||||
|
) {
|
||||||
|
val linkTask = ":linkDebugExecutable${nativeHostTargetName.capitalize()}"
|
||||||
|
|
||||||
|
val prefix = CompilerOutputKind.PROGRAM.prefix(HostManager.host)
|
||||||
|
val suffix = CompilerOutputKind.PROGRAM.suffix(HostManager.host)
|
||||||
|
val fileName = "${prefix}native-binary$suffix"
|
||||||
|
val outputFile = "build/bin/$nativeHostTargetName/debugExecutable/$fileName"
|
||||||
|
|
||||||
|
build(linkTask, "-Pkotlin.native.linkFromSources") {
|
||||||
|
assertSuccessful()
|
||||||
|
assertTasksExecuted(linkTask)
|
||||||
|
assertFileExists(outputFile)
|
||||||
|
checkNativeCommandLineFor(linkTask) {
|
||||||
|
assertTrue(it.contains("-Xcommon-sources="))
|
||||||
|
assertTrue(it.contains(projectDir.resolve("src/commonMain/kotlin/RootMain.kt").absolutePath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNativeFreeArgsWarning() = with(transformProjectWithPluginsDsl("kotlin-dsl", gradleVersion, "new-mpp-native-binaries")) {
|
fun testNativeFreeArgsWarning() = with(transformProjectWithPluginsDsl("kotlin-dsl", gradleVersion, "new-mpp-native-binaries")) {
|
||||||
gradleBuildScript().appendText(
|
gradleBuildScript().appendText(
|
||||||
|
|||||||
+44
-4
@@ -360,7 +360,9 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
|
|||||||
open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOptions>() {
|
open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOptions>() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
dependsOn(project.provider { compilation.compileKotlinTask })
|
if (!linkFromSources) {
|
||||||
|
dependsOn(project.provider { compilation.compileKotlinTask })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Internal
|
@Internal
|
||||||
@@ -370,12 +372,21 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
override val compilation: KotlinNativeCompilation
|
override val compilation: KotlinNativeCompilation
|
||||||
get() = binary.compilation
|
get() = binary.compilation
|
||||||
|
|
||||||
@InputFile
|
@Internal // Taken into account by getSources().
|
||||||
val intermediateLibrary: Provider<File> = project.provider {
|
val intermediateLibrary: Provider<File> = project.provider {
|
||||||
compilation.compileKotlinTask.outputFile.get()
|
compilation.compileKotlinTask.outputFile.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSource(): FileTree = project.files(intermediateLibrary.get()).asFileTree
|
@InputFiles
|
||||||
|
@SkipWhenEmpty
|
||||||
|
override fun getSource(): FileTree =
|
||||||
|
if (linkFromSources) {
|
||||||
|
// Allow a user to force the old behaviour of a link task.
|
||||||
|
// TODO: Remove in 1.3.70.
|
||||||
|
project.files(compilation.allSources).asFileTree
|
||||||
|
} else {
|
||||||
|
project.files(intermediateLibrary.get()).asFileTree
|
||||||
|
}
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
override val outputKind: CompilerOutputKind
|
override val outputKind: CompilerOutputKind
|
||||||
@@ -443,6 +454,13 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
val embedBitcode: Framework.BitcodeEmbeddingMode
|
val embedBitcode: Framework.BitcodeEmbeddingMode
|
||||||
get() = (binary as? Framework)?.embedBitcode ?: Framework.BitcodeEmbeddingMode.DISABLE
|
get() = (binary as? Framework)?.embedBitcode ?: Framework.BitcodeEmbeddingMode.DISABLE
|
||||||
|
|
||||||
|
// This property allows a user to force the old behaviour of a link task
|
||||||
|
// to workaround issues that may occur after switching to the two-stage linking.
|
||||||
|
// If it is specified, the final binary is built directly from sources instead of a klib.
|
||||||
|
// TODO: Remove it in 1.3.70.
|
||||||
|
private val linkFromSources: Boolean
|
||||||
|
get() = project.hasProperty(LINK_FROM_SOURCES_PROPERTY)
|
||||||
|
|
||||||
override fun buildCompilerArgs(): List<String> = mutableListOf<String>().apply {
|
override fun buildCompilerArgs(): List<String> = mutableListOf<String>().apply {
|
||||||
addAll(super.buildCompilerArgs())
|
addAll(super.buildCompilerArgs())
|
||||||
|
|
||||||
@@ -462,7 +480,25 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
addKey("-Xstatic-framework", isStaticFramework)
|
addKey("-Xstatic-framework", isStaticFramework)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun buildSourceArgs(): List<String> = listOf("-Xinclude=${intermediateLibrary.get().absolutePath}")
|
override fun buildSourceArgs(): List<String> {
|
||||||
|
return if (!linkFromSources) {
|
||||||
|
listOf("-Xinclude=${intermediateLibrary.get().absolutePath}")
|
||||||
|
} else {
|
||||||
|
// Allow a user to force the old behaviour of a link task.
|
||||||
|
// TODO: Remove in 1.3.70.
|
||||||
|
mutableListOf<String>().apply {
|
||||||
|
val friends = compilation.friendCompilation?.output?.allOutputs?.files
|
||||||
|
if (friends != null && friends.isNotEmpty()) {
|
||||||
|
addArg("-friend-modules", friends.joinToString(File.pathSeparator) { it.absolutePath })
|
||||||
|
}
|
||||||
|
|
||||||
|
addAll(project.files(compilation.allSources).map { it.absolutePath })
|
||||||
|
if (!compilation.commonSources.isEmpty) {
|
||||||
|
add("-Xcommon-sources=${compilation.commonSources.joinToString(separator = ",") { it.absolutePath }}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun validatedExportedLibraries() {
|
private fun validatedExportedLibraries() {
|
||||||
val exportConfiguration = exportLibraries as? Configuration ?: return
|
val exportConfiguration = exportLibraries as? Configuration ?: return
|
||||||
@@ -500,6 +536,10 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
validatedExportedLibraries()
|
validatedExportedLibraries()
|
||||||
super.compile()
|
super.compile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val LINK_FROM_SOURCES_PROPERTY = "kotlin.native.linkFromSources"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class CInteropProcess : DefaultTask() {
|
open class CInteropProcess : DefaultTask() {
|
||||||
|
|||||||
Reference in New Issue
Block a user