From 5a80eafec31455ff6d978782afd09a36787e6116 Mon Sep 17 00:00:00 2001 From: LepilkinaElena Date: Tue, 2 Apr 2019 16:56:01 +0300 Subject: [PATCH] Rework cinterop linkerOpts/compilerOpts (KT-29970) (#2841) --- .../native/interop/gen/jvm/CommandLine.kt | 18 ++++++++--- .../kotlin/native/interop/gen/jvm/main.kt | 14 +++++--- .../org/jetbrains/kotlin/cli/bc/K2Native.kt | 4 +-- .../cli/bc/K2NativeCompilerArguments.kt | 3 ++ backend.native/tests/build.gradle | 32 +++++++++++++++++++ .../interop/basics/custom headers/custom.h | 7 ++++ .../tests/interop/basics/withSpaces.kt | 12 +++++++ .../kotlin/NativeInteropPlugin.groovy | 4 +-- gradle.properties | 4 +-- performance/videoplayer/build.gradle | 10 +++--- .../plugin/experimental/tasks/CInteropTask.kt | 6 ++-- .../experimental/tasks/KotlinNativeCompile.kt | 4 ++- .../kotlin/gradle/plugin/konan/KonanPlugin.kt | 6 ---- .../plugin/konan/tasks/KonanCompileTask.kt | 5 +-- .../plugin/konan/tasks/KonanInteropTask.kt | 4 +-- 15 files changed, 99 insertions(+), 34 deletions(-) create mode 100644 backend.native/tests/interop/basics/custom headers/custom.h create mode 100644 backend.native/tests/interop/basics/withSpaces.kt diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt index 1499b126217..47d80935083 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt @@ -59,10 +59,20 @@ fun getCInteropArguments(): List { isMultiple = true, delimiter = ",", deprecatedWarning = "Option -h is deprecated. Please use -header."), OptionDescriptor(ArgType.String(), HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX, "hfasp", "header file to produce kotlin bindings for", isMultiple = true, delimiter = ","), - OptionDescriptor(ArgType.String(), "compilerOpts", "copt", - "additional compiler options", isMultiple = true, delimiter = " "), - OptionDescriptor(ArgType.String(), "linkerOpts", "lopt", - "additional linker options", isMultiple = true, delimiter = " "), + OptionDescriptor(ArgType.String(), "compilerOpts", + description = "additional compiler options (allows to add several options separated by spaces)", + isMultiple = true, delimiter = " "), + OptionDescriptor(ArgType.String(), "linkerOpts", + description = "additional linker options (allows to add several options separated by spaces)", + isMultiple = true, delimiter = " "), + OptionDescriptor(ArgType.String(), "compilerOpt", + description = "additional compiler option", isMultiple = true), + OptionDescriptor(ArgType.String(), "linkerOpt", + description = "additional linker option", isMultiple = true), + OptionDescriptor(ArgType.String(), "copt", description = "additional compiler options (allows to add several options separated by spaces)", + isMultiple = true, delimiter = " ", deprecatedWarning = "Option -copt is deprecated. Please use -compilerOpts."), + OptionDescriptor(ArgType.String(), "lopt", description = "additional linker options (allows to add several options separated by spaces)", + isMultiple = true, delimiter = " ", deprecatedWarning = "Option -lopt is deprecated. Please use -linkerOpts."), OptionDescriptor(ArgType.String(), "linker", description = "use specified linker") ) return (options + getCommonInteropArguments()) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt index 4aa94b7e902..6205935db8b 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt @@ -176,12 +176,15 @@ private fun processCLib(args: Array, additionalArgs: Map = val tool = prepareTool(argParser.get("target"), flavor) val def = DefFile(defFile, tool.substitutions) - - if (flavorName == "native" && argParser.getOrigin("linkerOpts") == ArgParser.ValueOrigin.SET_BY_USER) { - warn("-linkerOpts/-lopt option is not supported by cinterop. Please add linker options to .def file or binary compilation instead.") + val isLinkerOptsSetByUser = (argParser.getOrigin("linkerOpts") == ArgParser.ValueOrigin.SET_BY_USER) || + (argParser.getOrigin("linkerOpt") == ArgParser.ValueOrigin.SET_BY_USER) || + (argParser.getOrigin("lopt") == ArgParser.ValueOrigin.SET_BY_USER) + if (flavorName == "native" && isLinkerOptsSetByUser) { + warn("-linkerOpt(s)/-lopt option is not supported by cinterop. Please add linker options to .def file or binary compilation instead.") } - val additionalLinkerOpts = argParser.getValuesAsArray("linkerOpts") + val additionalLinkerOpts = argParser.getValuesAsArray("linkerOpts") + argParser.getValuesAsArray("linkerOpt") + + argParser.getValuesAsArray("lopt") val verbose = argParser.get("verbose")!! val language = selectNativeLanguage(def.config) @@ -302,7 +305,8 @@ internal fun buildNativeLibrary( imports: ImportsImpl ): NativeLibrary { val additionalHeaders = arguments.getValuesAsArray("header") + arguments.getValuesAsArray("h") - val additionalCompilerOpts = arguments.getValuesAsArray("compilerOpts") + val additionalCompilerOpts = arguments.getValuesAsArray("compilerOpts") + arguments.getValuesAsArray("compilerOpt") + + arguments.getValuesAsArray("copt") val headerFiles = def.config.headers + additionalHeaders val language = selectNativeLanguage(def.config) diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index fa5e8c88f9e..72d0de64273 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -121,8 +121,8 @@ class K2Native : CLICompiler() { put(NOMAIN, arguments.nomain) put(LIBRARY_FILES, arguments.libraries.toNonNullList()) - - put(LINKER_ARGS, arguments.linkerArguments.toNonNullList()) + put(LINKER_ARGS, arguments.linkerArguments.toNonNullList() + + arguments.singleLinkerArguments.toNonNullList()) arguments.moduleName ?. let{ put(MODULE_NAME, it) } arguments.target ?.let{ put(TARGET, it) } diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt index 3927a073fdd..052eae1c515 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt @@ -66,6 +66,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value="-linker-options", deprecatedName = "-linkerOpts", valueDescription = "", description = "Pass arguments to linker", delimiter = " ") var linkerArguments: Array? = null + @Argument(value="-linker-option", valueDescription = "", description = "Pass argument to linker", delimiter = "") + var singleLinkerArguments: Array? = null + @Argument(value = "-nostdlib", description = "Don't link with stdlib") var nostdlib: Boolean = false diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index d2bc0d26e22..2fc84852e89 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -2894,6 +2894,20 @@ task inline_defaultArgs_linkTest(type: LinkKonanTest) { lib = "codegen/inline/defaultArgs_linkTest_lib.kt" } +def generateWithSpaceDefFile() { + def file = new File("${buildDir}/withSpaces.def") + file.write """ +headers = stdio.h "${projectDir}/interop/basics/custom headers/custom.h" +linkerOpts = -map "${buildDir}/cutom map.map" +--- + +int customCompare(const char* str1, const char* str2) { + return custom_strcmp(str1, str2); +} +""" + return file.absolutePath +} + kotlinNativeInterop { target project.testTarget ?: 'host' flavor 'native' @@ -3050,6 +3064,24 @@ task interop_callbacksAndVarargs(type: RunInteropKonanTest) { interop = 'ccallbacksAndVarargs' } +task interop_withSpaces() { + dependsOn 'build' + konanArtifacts { + interop('withSpacesInterop') { + defFile generateWithSpaceDefFile() + } + program("withSpaces") { + srcDir "interop/basics/withSpaces.kt" + libraries { + artifact 'withSpacesInterop' + } + } + } + doLast { + assert file("${buildDir}/cutom map.map").exists() + } +} + task interop_echo_server(type: RunInteropKonanTest) { disabled = isWasmTarget(project) || isWindowsTarget(project) run = false diff --git a/backend.native/tests/interop/basics/custom headers/custom.h b/backend.native/tests/interop/basics/custom headers/custom.h new file mode 100644 index 00000000000..1e9e547aca7 --- /dev/null +++ b/backend.native/tests/interop/basics/custom headers/custom.h @@ -0,0 +1,7 @@ +#include +#include +#include + +int custom_strcmp(const char* str1, const char* str2) { + return strcmp(str1, str2); +} \ No newline at end of file diff --git a/backend.native/tests/interop/basics/withSpaces.kt b/backend.native/tests/interop/basics/withSpaces.kt new file mode 100644 index 00000000000..71d8bee4a17 --- /dev/null +++ b/backend.native/tests/interop/basics/withSpaces.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* +import kotlinx.cinterop.* +import withSpaces.* + +fun main(args: Array) { + customCompare("first", "second") +} diff --git a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy index 11b49d466d3..834ddff17bb 100644 --- a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy +++ b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy @@ -247,8 +247,8 @@ class NamedNativeInteropConfig implements Named { environment['PATH'] = project.files(project.hostPlatform.clang.clangPaths).asPath + File.pathSeparator + environment['PATH'] - args compilerOpts.collectMany { ['-copt', it] } - args linkerOpts.collectMany { ['-lopt', it] } + args compilerOpts.collectMany { ['-compilerOpt', it] } + args linkerOpts.collectMany { ['-linkerOpt', it] } headers.each { args '-header', it diff --git a/gradle.properties b/gradle.properties index b7f4f871eae..d659ac2ea05 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,8 +21,8 @@ remoteRoot=konan_tests kotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_dev_Compiler),number:1.3.40-dev-1234,branch:default:true,pinned:true/artifacts/content/maven kotlinVersion=1.3.40-dev-1234 testKotlinVersion=1.3.40-dev-1234 -sharedRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinNativeShared_BuildAndTest),number:1.0-dev-23,branch:default:true,pinned:true/artifacts/content/maven -sharedVersion=1.0-dev-23 +sharedRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinNativeShared_BuildAndTest),number:1.0-dev-28,branch:default:true,pinned:true/artifacts/content/maven +sharedVersion=1.0-dev-28 konanVersion=1.3.0 org.gradle.jvmargs='-Dfile.encoding=UTF-8' org.gradle.workers.max=4 diff --git a/performance/videoplayer/build.gradle b/performance/videoplayer/build.gradle index 96ddd6d5f37..bcb0a751848 100644 --- a/performance/videoplayer/build.gradle +++ b/performance/videoplayer/build.gradle @@ -21,17 +21,17 @@ if (MPPTools.isMacos()) { '-headerFilterAdditionalSearchPrefix', '/usr/include/x86_64-linux-gnu', '-headerFilterAdditionalSearchPrefix', '/usr/include/ffmpeg'] } else if (MPPTools.isWindows()) { - includeDirsFfmpeg += ['-copt', "-I${MPPTools.mingwPath()}/include"] + includeDirsFfmpeg += ['-compilerOpt', "-I${MPPTools.mingwPath()}/include"] } def includeDirsSdl = [] if (MPPTools.isMacos()) { - includeDirsSdl += ['-copt', '-I/opt/local/include/SDL2', - '-copt', '-I/usr/local/include/SDL2'] + includeDirsSdl += ['-compilerOpt', '-I/opt/local/include/SDL2', + '-compilerOpt', '-I/usr/local/include/SDL2'] } else if (MPPTools.isLinux()) { - includeDirsSdl += ['-copt', '-I/usr/include/SDL2'] + includeDirsSdl += ['-compilerOpt', '-I/usr/include/SDL2'] } else if (MPPTools.isWindows()) { - includeDirsSdl += ['-copt', "-I${MPPTools.mingwPath()}/include/SDL2"] + includeDirsSdl += ['-compilerOpt', "-I${MPPTools.mingwPath()}/include/SDL2"] } project.ext { diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt index 39450dad0e7..1c5e86fc0df 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt @@ -98,14 +98,14 @@ open class CInteropTask @Inject constructor(val settings: CInteropSettingsImpl): addFileArgs("-header", headers) compilerOpts.forEach { - addArg("-copt", it) + addArg("-compilerOpt", it) } linkerOpts.forEach { - addArg("-lopt", it) + addArg("-linkerOpt", it) } - addArgs("-copt", allHeadersDirs.map { "-I${it.absolutePath}" }) + addArgs("-compilerOpt", allHeadersDirs.map { "-I${it.absolutePath}" }) addArgs("-headerFilterAdditionalSearchPrefix", headerFilterDirs.map { it.absolutePath }) libraries.files.filter { diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt index 36eb8a1d9dd..5e0301ea407 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt @@ -196,7 +196,9 @@ open class KotlinNativeCompile @Inject constructor(internal val binary: Abstract else -> { /* Do nothing. */ } } - addListArg("-linker-options", linkerOpts) + linkerOpts.forEach { + addArg("-linker-option", it) + } addAll(sources.files.map { it.absolutePath }) commonSources.files.mapTo(this) { "-Xcommon-sources=${it.absolutePath}" } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt index 5e10fce4282..f928dc22938 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt @@ -203,12 +203,6 @@ internal fun MutableList.addFileArgs(parameter: String, values: Collecti } } -internal fun MutableList.addListArg(parameter: String, values: List) { - if (values.isNotEmpty()) { - addArg(parameter, values.joinToString(separator = " ")) - } -} - // endregion internal fun dumpProperties(task: Task) { diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt index 9c59c6efe8a..3171c4f0b0a 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanCompileTask.kt @@ -122,8 +122,9 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { addFileArgs("-native-library", nativeLibraries) addArg("-produce", produce.name.toLowerCase()) - - addListArg("-linker-options", linkerOpts) + linkerOpts.forEach { + addArg("-linker-option", it) + } addArgIfNotNull("-target", konanTarget.visibleName) addArgIfNotNull("-language-version", languageVersion) diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt index d718d36187a..28fb6215527 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/tasks/KonanInteropTask.kt @@ -93,10 +93,10 @@ open class KonanInteropTask @Inject constructor(val workerExecutor: WorkerExecut linkerOpts.addAll(it.files.map { it.canonicalPath }) } linkerOpts.forEach { - addArg("-lopt", it) + addArg("-linkerOpt", it) } - addArgs("-copt", includeDirs.allHeadersDirs.map { "-I${it.absolutePath}" }) + addArgs("-compilerOpt", includeDirs.allHeadersDirs.map { "-I${it.absolutePath}" }) addArgs("-headerFilterAdditionalSearchPrefix", includeDirs.headerFilterDirs.map { it.absolutePath }) addArgs("-repo", libraries.repos.map { it.canonicalPath })