[K/N] Refactor ObjcExportTest build script

This commit is contained in:
Pavel Kunyavskiy
2023-02-06 15:27:49 +01:00
committed by Space Team
parent 69b90e107c
commit b4bd847345
4 changed files with 242 additions and 246 deletions
+106 -240
View File
@@ -5603,13 +5603,13 @@ Task frameworkTest(String name, Closure<FrameworkTest> configurator) {
}
baseDir "$testOutputFramework/${task.name}"
if (fr.library != null) {
dependsOn konanArtifacts[fr.library].getByTarget(target.name)
fr.libraries.forEach { library ->
dependsOn konanArtifacts[library].getByTarget(target.name)
libraries {
file konanArtifacts[fr.library].getArtifactByTarget(target.name)
file konanArtifacts[library].getArtifactByTarget(target.name)
}
linkerOpts "-L$buildDir"
UtilsKt.dependsOnKonanBuildingTask(task, fr.library, target)
UtilsKt.dependsOnKonanBuildingTask(task, library, target)
}
extraOpts fr.bitcode ? "-Xembed-bitcode" : "-Xembed-bitcode-marker"
@@ -5626,35 +5626,45 @@ Task frameworkTest(String name, Closure<FrameworkTest> configurator) {
}
}
if (isAppleTarget(project)) {
frameworkTest('testObjCExport') {
final String frameworkName = 'Kt'
final String dir = "$testOutputFramework/testObjCExport"
Task objcExportTest(
Task allTask,
String suffix,
List<String> frameworkOpts,
List<String> swiftOpts,
Boolean isStaticFramework,
Boolean needLazyHeaderCheck
) {
final String name = "testObjCExport$suffix"
final String frameworkName = "Kt$suffix"
final String expectedLazyHeaderName = "expectedLazy${suffix}.h"
final Task task = frameworkTest(name) {
final String dir = "$testOutputFramework/$name"
final File lazyHeader = file("$dir/$target-lazy.h")
doLast {
// Check lazy header.
final String expectedLazyHeaderName = "expectedLazy.h"
final String expectedLazyHeaderDir = file("objcexport/")
final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName)
if (needLazyHeaderCheck) {
final String expectedLazyHeaderDir = file("objcexport/")
final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName)
if (expectedLazyHeader.readLines() != lazyHeader.readLines()) {
exec {
commandLine 'diff', '-u', expectedLazyHeader, lazyHeader
ignoreExitValue = true
if (!expectedLazyHeader.exists() || expectedLazyHeader.readLines() != lazyHeader.readLines()) {
exec {
commandLine 'diff', '-u', expectedLazyHeader, lazyHeader
ignoreExitValue = true
}
copy {
from(lazyHeader)
into(expectedLazyHeaderDir)
rename { expectedLazyHeaderName }
}
throw new Error("$expectedLazyHeader file patched;\nRun gradlew ${allTask.path} --continue and don't forget to commit the patch")
}
copy {
from(lazyHeader)
into(expectedLazyHeaderDir)
rename { expectedLazyHeaderName }
}
throw new Error("$expectedLazyHeader file patched;\nre-run the test and don't forget to commit the patch")
}
// Check bundle ID.
final String frameworkPath = "$dir/$target/${frameworkName}.framework"
final String frameworkPath = "$dir/$target/Kt.framework"
final Pattern pattern = ~"<key>CFBundleIdentifier</key>\n\\s*<string>foo.bar</string>"
final String plistPath = (target.family == Family.OSX) ?
"$frameworkPath/Resources/Info.plist" :
@@ -5669,7 +5679,7 @@ if (isAppleTarget(project)) {
konanArtifacts {
library(libraryName, targets: [target.name]) {
srcDir "objcexport/library"
artifactName "test-library"
artifactName "test-$libraryName"
delegate.getByTarget(target.name).configure{
UtilsKt.dependsOnDist(it)
}
@@ -5677,14 +5687,27 @@ if (isAppleTarget(project)) {
extraOpts "-Xshort-module-name=MyLibrary"
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
}
}
codesign = !isStaticFramework
framework(frameworkName) {
enabled = !isK2(project) // KT-56182
sources = ['objcexport']
library = libraryName
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xexport-kdoc", "-Xbinary=bundleId=foo.bar"]
libraries = [libraryName]
artifact = 'Kt'
bitcode = !isStaticFramework
isStatic = isStaticFramework
if (needLazyHeaderCheck) {
opts += "-Xemit-lazy-objc-header=$lazyHeader"
}
opts += [
"-Xexport-kdoc",
"-Xbinary=bundleId=foo.bar",
]
opts += frameworkOpts
}
swiftSources = ['objcexport']
swiftExtraOpts = swiftOpts
if (isNoopGC) {
swiftExtraOpts += ["-D", "NOOP_GC"]
}
@@ -5692,220 +5715,63 @@ if (isAppleTarget(project)) {
swiftExtraOpts += ["-D", "AGGRESSIVE_GC"]
}
}
allTask.dependsOn(task)
return task
}
frameworkTest('testObjCExportNoGenerics') {
final String frameworkName = 'KtNoGenerics'
final String frameworkArtifactName = 'Kt'
final String dir = "$testOutputFramework/testObjCExportNoGenerics"
final File lazyHeader = file("$dir/$target-lazy.h")
doLast {
final String expectedLazyHeaderName = "expectedLazyNoGenerics.h"
final String expectedLazyHeaderDir = file("objcexport/")
final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName)
if (expectedLazyHeader.readLines() != lazyHeader.readLines()) {
exec {
commandLine 'diff', '-u', expectedLazyHeader, lazyHeader
ignoreExitValue = true
}
if (isAppleTarget(project)) {
final Task ObjCExportAllTask = tasks.create("testObjCExportAll")
objcExportTest(
ObjCExportAllTask,
'',
[],
[],
false,
true
)
objcExportTest(
ObjCExportAllTask,
'NoGenerics',
["-Xno-objc-generics"],
[ '-D', 'NO_GENERICS' ],
false,
true
)
objcExportTest(
ObjCExportAllTask,
'LegacySuspendUnit',
["-Xbinary=unitSuspendFunctionObjCExport=legacy"],
[ '-D', 'LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT' ],
false,
true
)
objcExportTest(
ObjCExportAllTask,
'NoSwiftMemberNameMangling',
["-Xbinary=objcExportDisableSwiftMemberNameMangling=true"],
[ '-D', 'DISABLE_MEMBER_NAME_MANGLING' ],
false,
false
)
objcExportTest(
ObjCExportAllTask,
'NoInterfaceMemberNameMangling',
["-Xbinary=objcExportIgnoreInterfaceMethodCollisions=true"],
[ '-D', 'DISABLE_INTERFACE_METHOD_NAME_MANGLING' ],
false,
false
)
copy {
from(lazyHeader)
into(expectedLazyHeaderDir)
rename { expectedLazyHeaderName }
}
throw new Error("$expectedLazyHeader file patched;\nre-run the test and don't forget to commit the patch")
}
}
def libraryName = frameworkName + "Library"
konanArtifacts {
library(libraryName, targets: [target.name]) {
srcDir "objcexport/library"
artifactName "test-library"
if (!useCustomDist) {
dependsOn ":${target.name}CrossDistRuntime", ':distCompiler'
}
extraOpts "-Xshort-module-name=MyLibrary"
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
}
}
framework(frameworkName) {
enabled = !isK2(project) // KT-56182
sources = ['objcexport']
artifact = frameworkArtifactName
library = libraryName
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xno-objc-generics"]
}
swiftSources = ['objcexport']
swiftExtraOpts = [ '-D', 'NO_GENERICS' ]
if (isNoopGC) {
swiftExtraOpts += ["-D", "NOOP_GC"]
}
}
frameworkTest('testObjCExportLegacySuspendUnit') {
final String frameworkName = 'KtLegacySuspendUnit'
final String frameworkArtifactName = 'Kt'
final String dir = "$testOutputFramework/testObjCExportLegacySuspendUnit"
final File lazyHeader = file("$dir/$target-lazy.h")
doLast {
final String expectedLazyHeaderName = "expectedLazyLegacySuspendUnit.h"
final String expectedLazyHeaderDir = file("objcexport/")
final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName)
if (expectedLazyHeader.readLines() != lazyHeader.readLines()) {
exec {
commandLine 'diff', '-u', expectedLazyHeader, lazyHeader
ignoreExitValue = true
}
copy {
from(lazyHeader)
into(expectedLazyHeaderDir)
rename { expectedLazyHeaderName }
}
throw new Error("$expectedLazyHeader file patched;\nre-run the test and don't forget to commit the patch")
}
}
def libraryName = frameworkName + "Library"
konanArtifacts {
library(libraryName, targets: [target.name]) {
srcDir "objcexport/library"
artifactName "test-library"
if (!useCustomDist) {
dependsOn ":${target.name}CrossDistRuntime", ':distCompiler'
}
extraOpts "-Xshort-module-name=MyLibrary"
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
}
}
framework(frameworkName) {
enabled = !isK2(project) // KT-56182
sources = ['objcexport']
artifact = frameworkArtifactName
library = libraryName
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xbinary=unitSuspendFunctionObjCExport=legacy"]
}
swiftSources = ['objcexport']
swiftExtraOpts = [ '-D', 'LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT' ]
if (isNoopGC) {
swiftExtraOpts += ["-D", "NOOP_GC"]
}
}
frameworkTest('testObjCExportNoSwiftMemberNameMangling') {
final String frameworkName = 'KtNoSwiftMemberNameMangling'
final String frameworkArtifactName = 'Kt'
final String dir = "$testOutputFramework/testObjCExportNoSwiftMemberNameMangling"
def libraryName = frameworkName + "Library"
konanArtifacts {
library(libraryName, targets: [target.name]) {
srcDir "objcexport/library"
artifactName "test-library"
if (!useCustomDist) {
dependsOn ":${target.name}CrossDistRuntime", ':distCompiler'
}
extraOpts "-Xshort-module-name=MyLibrary"
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
}
}
framework(frameworkName) {
enabled = !isK2(project) // KT-56182
sources = ['objcexport']
artifact = frameworkArtifactName
library = libraryName
opts = ["-Xbinary=objcExportDisableSwiftMemberNameMangling=true"]
}
swiftSources = ['objcexport']
swiftExtraOpts = [ '-D', 'DISABLE_MEMBER_NAME_MANGLING' ]
if (isNoopGC) {
swiftExtraOpts += ["-D", "NOOP_GC"]
}
}
frameworkTest('testObjCExportNoInterfaceMemberNameMangling') {
final String frameworkName = 'KtNoInterfaceMemberNameMangling'
final String frameworkArtifactName = 'Kt'
final String dir = "$testOutputFramework/testObjCExportNoInterfaceMemberNameMangling"
def libraryName = frameworkName + "Library"
konanArtifacts {
library(libraryName, targets: [target.name]) {
srcDir "objcexport/library"
artifactName "test-library"
if (!useCustomDist) {
dependsOn ":${target.name}CrossDistRuntime", ':distCompiler'
}
extraOpts "-Xshort-module-name=MyLibrary"
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
}
}
framework(frameworkName) {
enabled = !isK2(project) // KT-56182
sources = ['objcexport']
artifact = frameworkArtifactName
library = libraryName
opts = ["-Xbinary=objcExportIgnoreInterfaceMethodCollisions=true"]
}
swiftSources = ['objcexport']
swiftExtraOpts = [ '-D', 'DISABLE_INTERFACE_METHOD_NAME_MANGLING' ]
if (isNoopGC) {
swiftExtraOpts += ["-D", "NOOP_GC"]
}
}
frameworkTest('testObjCExportStatic') {
final String frameworkName = 'KtStatic'
final String frameworkArtifactName = 'Kt'
final String libraryName = frameworkName + "Library"
konanArtifacts {
library(libraryName, targets: [target.name]) {
srcDir "objcexport/library"
artifactName "test-library"
delegate.getByTarget(target.name).configure{
UtilsKt.dependsOnDist(it)
}
extraOpts "-Xshort-module-name=MyLibrary"
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
}
}
codesign = false
framework(frameworkName) {
enabled = !isK2(project) // KT-56182
sources = ['objcexport']
bitcode = false
artifact = frameworkArtifactName
library = libraryName
isStatic = true
opts = ["-Xbinary=objcExportSuspendFunctionLaunchThreadRestriction=none"]
}
swiftSources = ['objcexport']
swiftExtraOpts = [ '-D', 'ALLOW_SUSPEND_ANY_THREAD' ]
if (isNoopGC) {
swiftExtraOpts += ["-D", "NOOP_GC"]
}
}
objcExportTest(
ObjCExportAllTask,
'Static',
["-Xbinary=objcExportSuspendFunctionLaunchThreadRestriction=none"],
[ '-D', 'ALLOW_SUSPEND_ANY_THREAD' ],
true,
false
)
frameworkTest('testValuesGenericsFramework') {
framework('ValuesGenerics') {
@@ -5966,7 +5832,7 @@ if (isAppleTarget(project)) {
frameworkTest("testGh3343Framework") {
framework('Gh3343') {
sources = ['framework/gh3343']
library = 'objcGh3343'
libraries = ['objcGh3343']
}
swiftSources = ['framework/gh3343/']
}
@@ -5982,7 +5848,7 @@ if (isAppleTarget(project)) {
frameworkTest("testKt43517Framework") {
framework('Kt43517') {
sources = ['framework/kt43517']
library = 'objcKt43517'
libraries = ['objcKt43517']
}
swiftSources = ['framework/kt43517/']
}
@@ -6054,7 +5920,7 @@ if (isAppleTarget(project)) {
frameworkTest("testForwardDeclarationsFramework") {
framework('ForwardDeclarations') {
sources = ['framework/forwardDeclarations']
library = 'frameworkForwardDeclarations'
libraries = ['frameworkForwardDeclarations']
}
swiftSources = ['framework/forwardDeclarations/']
}
@@ -704,14 +704,33 @@ __attribute__((swift_name("InterfaceMethodNameManglingKt")))
+ (KtInterfaceNameManglingC2 *)o2 __attribute__((swift_name("o2()")));
@end
/**
* Summary class [KDocExport].
*
* @property xyzzy Doc for property xyzzy
* @property zzz See below.
*/
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("KDocExport")))
@interface KtKDocExport : KtBase
/** Non-primary ctor KDoc: */
- (instancetype)initWithName:(NSString *)name __attribute__((swift_name("init(name:)"))) __attribute__((objc_designated_initializer));
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
/**
* @param xyzzy is documented.
*
* This is multi-line KDoc. See a blank line above.
*/
@property (readonly) NSString *xyzzy __attribute__((swift_name("xyzzy")));
/** @property xyzzy KDoc for foo? */
@property (readonly) NSString *foo __attribute__((swift_name("foo")));
/** @property foo KDoc for yxxyz? */
@property int32_t yxxyz __attribute__((swift_name("yxxyz")));
@end
@@ -719,6 +738,37 @@ __attribute__((swift_name("SomeClassWithProperty")))
@interface KtSomeClassWithProperty : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
/**
* Returns dispatcher that executes coroutines immediately when it is already in the right context
* (e.g. current looper is the same as this handler's looper) without an additional [re-dispatch][CoroutineDispatcher.dispatch].
*
* Immediate dispatcher is safe from stack overflows and in case of nested invocations forms event-loop similar to [Dispatchers.Unconfined].
* The event loop is an advanced topic and its implications can be found in [Dispatchers.Unconfined] documentation.
* The formed event-loop is shared with [Unconfined] and other immediate dispatchers, potentially overlapping tasks between them.
*
* Example of usage:
* ```
* suspend fun updateUiElement(val text: String) {
* **
* * If it is known that updateUiElement can be invoked both from the Main thread and from other threads,
* * `immediate` dispatcher is used as a performance optimization to avoid unnecessary dispatch.
* *
* * In that case, when `updateUiElement` is invoked from the Main thread, `uiElement.text` will be
* * invoked immediately without any dispatching, otherwise, the `Dispatchers.Main` dispatch cycle will be triggered.
* **
* withContext(Dispatchers.Main.immediate) {
* uiElement.text = text
* }
* // Do context-independent logic such as logging
* }
* ```
*
* Method may throw [UnsupportedOperationException] if immediate dispatching is not supported by current dispatcher,
* please refer to specific dispatcher documentation.
*
* [Dispatchers.Main] supports immediate execution for Android, JavaFx and Swing platforms.
*/
@property (readonly) KtSomeClassWithProperty *heavyFormattedKDocFoo __attribute__((swift_name("heavyFormattedKDocFoo")));
@end
@@ -727,6 +777,13 @@ __attribute__((swift_name("KdocExportKt")))
@interface KtKdocExportKt : KtBase
/**
* Useless function [whatever]
*
* This kdoc has some additional formatting.
* @param a keep intact and return
* @return value of [a]
* Check for additional comment (note) below
*
* @note This method converts instances of IllegalArgumentException to errors.
* Other uncaught Kotlin exceptions are fatal.
*/
@@ -1039,16 +1096,24 @@ __attribute__((swift_name("Bar")))
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
/**
* My method
* @param nodocParam is one arg
* @param fooParam is second arg
* @param fooParam annotations Foo BugReport(assignedTo="me", status="fixed")
* @return their sum
*
* @note annotations
* Foo
* @param fooParam annotations Foo BugReport(assignedTo="me", status="fixed")
* @note This method converts instances of CancellationException to errors.
* Other uncaught Kotlin exceptions are fatal.
* @note This method has protected visibility in Kotlin source and is intended only for use by subclasses.
*/
- (void)bazNodocParam:(int32_t)nodocParam fooParam:(int32_t)fooParam completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("baz(nodocParam:fooParam:completionHandler:)"))) __attribute__((deprecated("warning")));
/**
/** My property
***
*
*
* @note annotations
* Foo
* BugReport(assignedTo="me", status="open")
@@ -704,14 +704,33 @@ __attribute__((swift_name("InterfaceMethodNameManglingKt")))
+ (KtInterfaceNameManglingC2 *)o2 __attribute__((swift_name("o2()")));
@end
/**
* Summary class [KDocExport].
*
* @property xyzzy Doc for property xyzzy
* @property zzz See below.
*/
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("KDocExport")))
@interface KtKDocExport : KtBase
/** Non-primary ctor KDoc: */
- (instancetype)initWithName:(NSString *)name __attribute__((swift_name("init(name:)"))) __attribute__((objc_designated_initializer));
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
/**
* @param xyzzy is documented.
*
* This is multi-line KDoc. See a blank line above.
*/
@property (readonly) NSString *xyzzy __attribute__((swift_name("xyzzy")));
/** @property xyzzy KDoc for foo? */
@property (readonly) NSString *foo __attribute__((swift_name("foo")));
/** @property foo KDoc for yxxyz? */
@property int32_t yxxyz __attribute__((swift_name("yxxyz")));
@end
@@ -719,6 +738,37 @@ __attribute__((swift_name("SomeClassWithProperty")))
@interface KtSomeClassWithProperty : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
/**
* Returns dispatcher that executes coroutines immediately when it is already in the right context
* (e.g. current looper is the same as this handler's looper) without an additional [re-dispatch][CoroutineDispatcher.dispatch].
*
* Immediate dispatcher is safe from stack overflows and in case of nested invocations forms event-loop similar to [Dispatchers.Unconfined].
* The event loop is an advanced topic and its implications can be found in [Dispatchers.Unconfined] documentation.
* The formed event-loop is shared with [Unconfined] and other immediate dispatchers, potentially overlapping tasks between them.
*
* Example of usage:
* ```
* suspend fun updateUiElement(val text: String) {
* **
* * If it is known that updateUiElement can be invoked both from the Main thread and from other threads,
* * `immediate` dispatcher is used as a performance optimization to avoid unnecessary dispatch.
* *
* * In that case, when `updateUiElement` is invoked from the Main thread, `uiElement.text` will be
* * invoked immediately without any dispatching, otherwise, the `Dispatchers.Main` dispatch cycle will be triggered.
* **
* withContext(Dispatchers.Main.immediate) {
* uiElement.text = text
* }
* // Do context-independent logic such as logging
* }
* ```
*
* Method may throw [UnsupportedOperationException] if immediate dispatching is not supported by current dispatcher,
* please refer to specific dispatcher documentation.
*
* [Dispatchers.Main] supports immediate execution for Android, JavaFx and Swing platforms.
*/
@property (readonly) KtSomeClassWithProperty *heavyFormattedKDocFoo __attribute__((swift_name("heavyFormattedKDocFoo")));
@end
@@ -727,6 +777,13 @@ __attribute__((swift_name("KdocExportKt")))
@interface KtKdocExportKt : KtBase
/**
* Useless function [whatever]
*
* This kdoc has some additional formatting.
* @param a keep intact and return
* @return value of [a]
* Check for additional comment (note) below
*
* @note This method converts instances of IllegalArgumentException to errors.
* Other uncaught Kotlin exceptions are fatal.
*/
@@ -1039,16 +1096,24 @@ __attribute__((swift_name("Bar")))
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
/**
* My method
* @param nodocParam is one arg
* @param fooParam is second arg
* @param fooParam annotations Foo BugReport(assignedTo="me", status="fixed")
* @return their sum
*
* @note annotations
* Foo
* @param fooParam annotations Foo BugReport(assignedTo="me", status="fixed")
* @note This method converts instances of CancellationException to errors.
* Other uncaught Kotlin exceptions are fatal.
* @note This method has protected visibility in Kotlin source and is intended only for use by subclasses.
*/
- (void)bazNodocParam:(int32_t)nodocParam fooParam:(int32_t)fooParam completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("baz(nodocParam:fooParam:completionHandler:)"))) __attribute__((deprecated("warning")));
/**
/** My property
***
*
*
* @note annotations
* Foo
* BugReport(assignedTo="me", status="open")
@@ -59,7 +59,7 @@ open class FrameworkTest : DefaultTask(), KonanTestExecutable {
* @param bitcode bitcode embedding in the framework,
* @param isStatic determines that framework is static
* @param artifact the name of the resulting artifact,
* @param library library dependency name,
* @param library list of library dependency names,
* @param opts additional options for the compiler.
*/
class Framework(
@@ -68,7 +68,7 @@ open class FrameworkTest : DefaultTask(), KonanTestExecutable {
var bitcode: Boolean = false,
var isStatic: Boolean = false,
var artifact: String = name,
var library: String? = null,
var libraries: List<String> = emptyList(),
var opts: List<String> = emptyList()
) : Serializable // Required for Gradle when using Framework as task input.