Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPM Support #1616

Closed
wants to merge 10 commits into from
Closed

SPM Support #1616

wants to merge 10 commits into from

Conversation

drdaz
Copy link
Member

@drdaz drdaz commented Jun 10, 2021

These changes add support for Swift Package Manager. Files have been rearranged in a way that SPM will accept, and some significant transformations have been applied to our import statements.

This version links against an SPM-supporting fork of Bolts I've made. I'm not sure how hard it is to get FB to update Bolts, but we can move the parse-community version of Bolts to include those changes if it's an issue.

One of the biggest changes has been to move all our imports from within our own code to use relative paths. This is some of my first experience with SPM, and I feel like this shouldn't have been necessary; but I haven't found evidence suggesting there's a tidier way. If anybody more experienced with SPM knows of a better way, let me know. In case anybody's interested, to achieve that change, I donned my dusty Perl Monk / Regex Sith robe and wrote a script. There was no way I was doing that manually across hundreds of files, and I've got a soft spot for regexes and scripting (no kinkshaming plz 🤣).

Current state of SPM support:
Bolts ✅
Parse ✅
ParseFacebookUtils
ParseTwitterUtils
ParseUI

Opening this PR now to hopefully get feedback on the approach I've taken with the main Parse component.

@drdaz
Copy link
Member Author

drdaz commented Jun 10, 2021

The test error is an odd one:

The following build commands failed:
	AnalyzeShallow /Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/Unit/UserCommandTests.m normal arm64
(1 failure)

❌  /Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Source/Internal/Commands/PFRESTCommand.h:12:9: '../PFNetworkCommand.h' file not found, did you mean 'PFNetworkCommand.h'?

#import "../PFNetworkCommand.h"
        ^~~~~~~~~~~~~~~~~~~~~~~


▸ Analyzing URLSessionUploadTaskDelegateTests.m
▸ Compiling UserUnitTests.m
▸ Compiling UserFileCodingLogicTests.m
▸ Compiling UserControllerTests.m
iOS Tests Failed!
drdaz@Darrens-MacBook-Air Parse-SDK-iOS-OSX % cd /Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Source/Internal/Commands/
drdaz@Darrens-MacBook-Air Commands % ls ../PFNetworkCommand.h
../PFNetworkCommand.h

The file is where it's expected to be, and it builds fine outside of the test context. If anybody has a clue, let me know 😃

@stale
Copy link

stale bot commented Oct 2, 2021

This issue has been automatically marked as stale because it has not had recent activity. If you believe it should stay open, please let us know! As always, we encourage contributions, check out the Contributing Guide

@stale stale bot added the Stale label Oct 2, 2021
@mtrezza mtrezza removed the Stale label Oct 14, 2021
@mtrezza mtrezza mentioned this pull request Jan 19, 2022
@mtrezza mtrezza linked an issue Jan 21, 2022 that may be closed by this pull request
@drdaz
Copy link
Member Author

drdaz commented Feb 2, 2022

@mman Let's take it here.

@drdaz Do you have any error messages?

Here's the output from my last run. It's entirely internal headers I think.

➜  Parse-SDK-iOS-OSX git:(drdaz-master) ✗ swift test
'Parse' /Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX: warning: Invalid Exclude '/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Source/Info.plist': File not found.
'Parse' /Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX: warning: Invalid Exclude '/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/Other/Swift': File not found.
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/UserCommandTests.m:10:9: fatal error: 'PFHTTPRequest.h' file not found
#import "PFHTTPRequest.h"
        ^~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/SessionUtilitiesTests.m:10:9: fatal error: 'PFSessionUtilities.h' file not found
#import "PFSessionUtilities.h"
        ^~~~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/UserControllerTests.m:14:9: fatal error: 'PFCommandRunning.h' file not found
#import "PFCommandRunning.h"
        ^~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/URLSessionTests.m:17:9: fatal error: 'PFRESTCommand.h' file not found
#import "PFRESTCommand.h"
        ^~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/URLSessionCommandRunnerTests.m:16:9: fatal error: 'PFCommandRunningConstants.h' file not found
#import "PFCommandRunningConstants.h"
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/SessionControllerTests.m:15:9: fatal error: 'PFCommandRunning.h' file not found
#import "PFCommandRunning.h"
        ^~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/SQLiteDatabaseTest.m:14:9: fatal error: 'PFSQLiteDatabase.h' file not found
#import "PFSQLiteDatabase.h"
        ^~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/SessionUnitTests.m:14:9: fatal error: 'PFSessionController.h' file not found
#import "PFSessionController.h"
        ^~~~~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/UserFileCodingLogicTests.m:12:9: fatal error: 'PFUserFileCodingLogic.h' file not found
#import "PFUserFileCodingLogic.h"
        ^~~~~~~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/URLSessionDataTaskDelegateTests.m:18:9: fatal error: 'PFURLSessionJSONDataTaskDelegate.h' file not found
#import "PFURLSessionJSONDataTaskDelegate.h"
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/drdaz/Documents/Development/Others/Parse-SDK-iOS-OSX/Parse/Tests/ParseTests/URLConstructorTests.m:12:9: fatal error: 'PFURLConstructor.h' file not found
#import "PFURLConstructor.h"
        ^~~~~~~~~~~~~~~~~~~~
17:9: fatal error: 'PFURLSessionUploadTaskDelegate.h' file not found
#import "PFURLSessionUploadTaskDelegate.h"
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
1 error generated.
1 error generated.
[15/324] Compiling OCMNotificationPoster.m
error: fatalError

I assume the headerSeatchPath is relative to the path I've specified for the target. But I've also tried adding extras with extra leading '../'s just to make sure it's not relative to the source file. No dice 🤷🏽‍♂️

@drdaz
Copy link
Member Author

drdaz commented Feb 2, 2022

Okay. All the missing files are one or more folders deep in the internal headers folder. I think I see the problem 🙂

@drdaz
Copy link
Member Author

drdaz commented Feb 3, 2022

@mman There just isn't a practicable way around flattening the source tree is there? I dislike that it removes meaningful structure from the codebase. But every way around it that I find seems to suck more in the long run.

If the structure remains, we end up having to encode it (so, all the subdirectories) somewhere; either in a .h file or in Package.swift.

I've tried generating this list of CSettings (headerSearchPath) dynamically in Package.swift like this:

    static func getInternalHeaderSearchPaths() -> [CSetting] {
        
        var result = [CSetting]()
        result.append(.headerSearchPath("../../Source/Internal/"))
        
        let paths = try? FileManager.default.subpathsOfDirectory(atPath: "Parse/Source/Internal")
        if let paths = paths {
            paths.forEach { path in
                if !(path.hasSuffix(".h") || path.hasSuffix(".m")) {
                    // This is a directory; add to search path
                    let pathString = "../../Source/Internal/\(path)"
                    result.append(.headerSearchPath(pathString))
                }
            }
        }
        return result

    }

And this actually seems to work from the command line. But not at all in Xcode 😭

@mman
Copy link
Contributor

mman commented Feb 7, 2022

@drdaz I have flattened the tree in order to keep the Package.swift simple and predictable. More over, the longer I use C the more I believe that the system is sources, public headers, and private headers. Any other (potentially more complex) structure is going to make everything broken in the long run. The same applies for swift modules, you have sources, you have public API (public headers) and private internal API (the private headers in C).

So I do not say what is correct approach for this PR, I am still experimenting what works the best.

for example, there are certain files for all targets, certain for iOS only, some for macOS only, some for watchOS only. Splitting these into sub targets is rather complex using current state of SPM, emitting a warning when compiling a macOS only file for iOS is also problematic as it CI, so it looks to me like a bunch of good old #ifdef statements will be needed.

But flat source tree looks like a no brainer. The structure is already in the file name….

@mtrezza
Copy link
Member

mtrezza commented Jan 30, 2023

Closing in favor of #1683

@mtrezza mtrezza closed this Jan 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support Swift Package Manager
3 participants