kif-framework / KIF

Keep It Functional - An iOS Functional Testing Framework
Other
6.21k stars 914 forks source link

KIF swift package manager warnings and errors #1212

Closed kikeenrique closed 3 years ago

kikeenrique commented 3 years ago

Hi 😀!, I was eager to try SPM and I've just tested it with version 3.8.0 and I get a warning and some errors.

  1. I created an empty project on Xcode, with testing artefacts.
  2. Added KIF as dependency on "Swift Packages"
  3. Hit tests.

As a result, I get this warning:

Umbrella directory '/Users/kikeenrique/Library/Developer/Xcode/DerivedData/Iris-ipad-eqvhyhvbervzgndvqpelptfppwhj/SourcePackages/checkouts/KIF/Sources/KIF/include' not found

inside this autogenerated KIF.modulemap.

module KIF {
umbrella "/Users/kikeenrique/Library/Developer/Xcode/DerivedData/TestKIF-cyhhveqlzbzhwmflkpwnrpiuptwz/SourcePackages/checkouts/KIF/Sources/KIF/include"
export *
}

And on linking phase I see this errors:

Undefined symbols for architecture x86_64:
  "_IOHIDEventCreateDigitizerEvent", referenced from:
      _kif_IOHIDEventWithTouches in KIF.o
  "_IOHIDEventCreateDigitizerFingerEventWithQuality", referenced from:
      _kif_IOHIDEventWithTouches in KIF.o
  "_IOHIDEventSetIntegerValue", referenced from:
      _kif_IOHIDEventWithTouches in KIF.o
  "_IOHIDEventAppendEvent", referenced from:
      _kif_IOHIDEventWithTouches in KIF.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Regards

kenji21 commented 3 years ago

to fix, the undefined symbols, you may add linkerSettings: [.linkedFramework("IOKit")]), (like here: https://github.com/openium/KIF/blob/spm-support-freez/Package.swift#L23)

        .target(
            name: "KIF",
            dependencies: [],
            cSettings: [.headerSearchPath("ApplePrivateAPIs/")],
            linkerSettings: [.linkedFramework("IOKit")]),
kikeenrique commented 3 years ago

@kenji21 you mean that fix must be applied in KIF, don't you?

About the umbrella module map, I haven't found where is it being generated, so no clue on how to fix it. Anyone?

kenji21 commented 3 years ago

can you fork and try to add this line to check if it fixes Undefined symbols errors, I'm confident it does

kikeenrique commented 3 years ago

@kenji21 Ok, yeah, I confident that will fix the linking problem. Any guess for the modulemap warning? Because I use to work with warnings as errors and that makes it a bigger problem.

kenji21 commented 3 years ago

Same, turning warnings to errors is a good practice, well, the https://github.com/openium/KIF/tree/spm-support-freez/Sources/KIF directory in my fork has an include/KIF directory, while current KIF master have not

dostrander commented 3 years ago

I'll put up a PR to fix this

dostrander commented 3 years ago

https://github.com/kif-framework/KIF/pull/1215

@kenji21 @kikeenrique

kikeenrique commented 3 years ago

Is there any check using a test project that compiles using SPM version?

kenji21 commented 3 years ago

Sure, add the package from its remote / fix-branch :

Screenshot 2

as there is no "public headers", we can't access any class inside the module, I think the target should define a "publicHeadersPath" (which defaults to TargetName/include) :

publicHeadersPath: String? = nil,

https://docs.swift.org/package-manager/PackageDescription/PackageDescription.html

kikeenrique commented 3 years ago

I'm sorry to express myself so badly. I mean if there is any test on CI to check that SPM is working as expected.

kenji21 commented 3 years ago

integrating a Swift package inside a Xcode project is as simple as drag & dropping the "Package.swift enclosing folder" in the project, during my PR, I had added it to the Testable Swift.xcodeproj:

https://github.com/openium/KIF/blob/spm-support-freez/Documentation/Examples/Testable%20Swift/Testable%20Swift.xcodeproj/project.pbxproj#L47

https://github.com/openium/KIF/blob/spm-support-freez/Documentation/Examples/Testable%20Swift/Testable%20Swift.xcodeproj/project.pbxproj#L523

But I don't think if this sample project is built during CI builds

kikeenrique commented 3 years ago

I've been checking both spm-support-freez and spm-support branches and I've not seen any empty project that just uses the SPM package. I consider it a simple and easy test to avoid issues like this. As you said, it's just 2 steps.

justinseanmartin commented 3 years ago

But I don't think if this sample project is built during CI builds

@dostrander - I believe we compile some of the Sample projects as part of the CI script, don't we? Seems worth checking on that to prevent regressions in the future.

dostrander commented 3 years ago

@kenji21 @kikeenrique @justinseanmartin So i have been looking into this. I've added a project to be able to test that its hooked up properly and can see the issue that @kikeenrique is saying where it can't find the headers. Looking into this I am trying to find a solution where we don't have to put all of our headers in an include/ folder as it breaks the convention of the Headers + Implementation should be side by side.

I am curious if y'all have any ways to get around this issue. I can't seem to get one that works. I've tried putting the publicHeadersPath: ./ so the KIF target looks like:


.target(
            name: "KIF",
            dependencies: [],
            publicHeadersPath: "./",
            cSettings: [
                .headerSearchPath("ApplePrivateAPIs/"),
                .headerSearchPath("Additions/"),
                .headerSearchPath("Classes/"),
                .headerSearchPath("Visualizer/"),
                .headerSearchPath("IdentifierTests/"),
            ],
            linkerSettings: [.linkedFramework("IOKit")]
        )```

However that creates issues where it can't find internal headers of the package. Any insight into this would be greatly appreciated as I am not very well versed in the SwiftPM ecosystem
kenji21 commented 3 years ago

I can see two ways:

I've searched in other "pure obj-c" frameworks having a Package.swift, like https://github.com/ccgus/fmdb/blob/master/Package.swift#L23 or https://github.com/robbiehanson/CocoaAsyncSocket/blob/master/Package.swift#L24 it seems that .m files could be alongside headers in the publicHeadersPath

kikeenrique commented 3 years ago

I've just tested an "empty" Xcode project, with a UI test target linking to KIF. With next Package.swift content I'm getting no warnings (but the 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0):

...
        .target(
            name: "KIF",
            dependencies: [],
            publicHeadersPath: ".",
            cSettings: [
                .headerSearchPath("ApplePrivateAPIs/"),
                .headerSearchPath("Additions/"),
                .headerSearchPath("Classes/"),
                .headerSearchPath("Visualizer/"),
                .headerSearchPath("IdentifierTests/"),
            ],
            linkerSettings: [ .linkedFramework("IOKit")]
        ),
...

Could it be a problem with "." vs "./" ?

dostrander commented 3 years ago

Try importing it into a file, that's when i start getting the error. It doesn't change if i have a . or a ./

kikeenrique commented 3 years ago

I've a guess.

publicHeadersPath is set to ".", which is "Sources/KIF" for target KIF. And contains no headers, but directories.

When Xcode compiles the KIF module, for each file it search for headers in common paths, such are the current directory and publicHeadersPath. So any file with dependencies on the other directories, would need to be more specific about its imports.

With next changes, and previous post Package.swift, it compiles and runs when you "import KIF" on a XCTestCase.

diff --git a/Sources/KIF/IdentifierTests/KIFUITestActor-IdentifierTests.h b/Sources/KIF/IdentifierTests/KIFUITestActor-IdentifierTests.h
index 7da13b44c37f05285883c442157f7c6674df6c94..823b83463b94eb47ecf74cedda85b1f32761e0ad 100644
--- a/Sources/KIF/IdentifierTests/KIFUITestActor-IdentifierTests.h
+++ b/Sources/KIF/IdentifierTests/KIFUITestActor-IdentifierTests.h
@@ -6,7 +6,7 @@
 //
 //

-#import "KIFUITestActor.h"
+#import "Classes/KIFUITestActor.h"

 @interface KIFUITestActor (IdentifierTests)

diff --git a/Sources/KIF/Additions/XCTestCase-KIFAdditions.h b/Sources/KIF/Additions/XCTestCase-KIFAdditions.h
index 64f966c0720390ea5e6c5276522cf447d4279425..441c784b7a67ed4ca6fbad6b71e5e2cf24fe0147 100644
--- a/Sources/KIF/Additions/XCTestCase-KIFAdditions.h
+++ b/Sources/KIF/Additions/XCTestCase-KIFAdditions.h
@@ -7,7 +7,7 @@
 //

 #import <XCTest/XCTest.h>
-#import "KIFTestActor.h"
+#import "Classes/KIFTestActor.h"

 @interface XCTestCase (KIFAdditions) <KIFTestActorDelegate>

diff --git a/Sources/KIF/Classes/KIF.h b/Sources/KIF/Classes/KIF.h
index bccb241d043761412a887293022511171abb4978..48d3adb298881e73c1e2fd203238b8dea9a1fe16 100644
--- a/Sources/KIF/Classes/KIF.h
+++ b/Sources/KIF/Classes/KIF.h
@@ -16,4 +16,4 @@
 #import "KIFUIViewTestActor.h"
 #import "KIFUIObject.h"

-#import "XCTestCase-KIFAdditions.h"
+#import "Additions/XCTestCase-KIFAdditions.h"
diff --git a/Sources/KIF/Classes/KIFTestCase.h b/Sources/KIF/Classes/KIFTestCase.h
index 7764710963acfa17eed233d9288c3f8a49fae17b..a3606cbf388643ce089a3cc3d3660235614ffa1b 100644
--- a/Sources/KIF/Classes/KIFTestCase.h
+++ b/Sources/KIF/Classes/KIFTestCase.h
@@ -12,7 +12,7 @@
  * @discussion This class provides four new methods: @c beforeAll and @c afterAll which run once before and after all tests and @c beforeEach and @c afterEach which run before and after every test. @c beforeEach and @c afterEach are guaranteed to run in the same instance as each test, but @c beforeAll and @c afterAll are not.  As such, @c beforeEach can be used to set up instance variables while @c beforeAll can only be used to set up static variables.
  */
 #import <XCTest/XCTest.h>
-#import "XCTestCase-KIFAdditions.h"
+#import "Additions/XCTestCase-KIFAdditions.h"

 @interface KIFTestCase : XCTestCase

diff --git a/Sources/KIF/Classes/KIFUITestActor.h b/Sources/KIF/Classes/KIFUITestActor.h
index db346ed02defb6ca6dcfcc91f1c44b37eb0b1d10..7ba4d67e33a5b3c64f1079a4819c151a986974ec 100644
--- a/Sources/KIF/Classes/KIFUITestActor.h
+++ b/Sources/KIF/Classes/KIFUITestActor.h
@@ -9,7 +9,7 @@

 #import "KIFTestActor.h"
 #import <UIKit/UIKit.h>
-#import "UIView-KIFAdditions.h"
+#import "Additions/UIView-KIFAdditions.h"

 #if DEPRECATE_KIF_TESTER
dostrander commented 3 years ago

@kikeenrique I think that worked, put up a PR for it now

dostrander commented 3 years ago

@kikeenrique it looks like it works for SwiftPM but not normally: https://github.com/kif-framework/KIF/pull/1218/checks?check_run_id=2022227282

pbartolome commented 3 years ago

There are other pure ObjC frameworks that are using the "symbolic link" option to place all headers inside a folder (E.g. XMPP https://github.com/robbiehanson/XMPPFramework/blob/master/Package.swift#L58 which has a include folder with symbolic links to the original headers https://github.com/robbiehanson/XMPPFramework/tree/master/include/XMPPFramework). It seems a good trade off as it should not affect other integration methods (carthage, manual, cocoapods...)

I will try to write some tests, but with the following changes (https://github.com/kif-framework/KIF/commit/4d67b9e7c0e11da867ac0849ed386b4b61988572) the SPM integration works, I have to test the other integration methods but as the original headers have not changed I don't expect issues

EDIT: well... same issue, as the 'include' folder is inside the Sources you will see duplicated declarations, taking a look at XMPPFramework, the sources have not been moved to a Sources folder and the include folder is a the top level, next to the Package.swift, I will try to take a look to that approach.

EDIT 2: The previous issue was related with a dirty DerivedData, the approach works with SPM and the test are passing https://github.com/pbartolome/KIF/runs/2185119947?check_suite_focus=true

pbartolome commented 3 years ago

I've created a PR that fixes the issues commented on this issue https://github.com/kif-framework/KIF/pull/1219

kikeenrique commented 3 years ago

After #1219 this issue can be considered fixed