-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add support for Swift Package Manager only projects #1945
base: master
Are you sure you want to change the base?
Conversation
@ikesyo, could you please review this PR when you're available? Thanks! PS: I'm not sure why the test is failing. It fails just after rebasing |
Last time I talked to the SwiftPM folks, it was suggested that we not rely on this functionality. I'll try to find someone at WWDC to talk to about this. |
@mdiep, I'm curious why we should not rely on that function. I think unstable solution is better than no solution. Even we can offer this functionality as a beta (or with a explicit flag) and change the implementation future. I hope I could distribute my code-only libs to Carthage without Xcode :) |
I don't think that's true. An unstable solution would likely:
|
You might be true if the Anyway, do you have any suggestion for adding Carthage support to existing SPM-only project? |
I think generating the xcodeproj is a fine way to start Carthage support. Generate, share the scheme, and check it in, and you should be good to go. |
@mdiep You mean the Xcode project from |
No, I mean generating with |
Hmm, I'm confused because you just said that |
It's not guaranteed to work for all projects. But if it's a fine starting place. If it works out of the box for your project, great! This acts as a QA step for projects—they have to confirm that the generated project works. |
Thanks for your kind reply. I hope we could find a better solution 👍 Feel free to close or keep this PR open. |
@mdiep, was there any updates on WWDC? :) |
After talking to someone from the SwiftPM team, I'm tentatively on board with adding support for this. It will require some testing. I'll try to play with this soon, but it will need to be a lower priority than some of my other OSS maintenance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need some documentation updates as well.
Source/CarthageKit/Project.swift
Outdated
public func generateSwiftPackageManagerXcodeProjectIfAvailable(forDependencyAt dependencyPath: String) -> SignalProducer<(), NoError> { | ||
let files = (try? FileManager.default.contentsOfDirectory(atPath: dependencyPath)) ?? [] | ||
|
||
let hasXcodeProjectFile = files.lazy.filter { $0.hasSuffix(".xcodeproj") || $0.hasSuffix(".xcworkspace") }.first != nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of doing foo.lazy.filter { ... }.first
, you should be able to do foo.first { ... }
.
let hasPackageFile = files.lazy.filter { $0 == "Package.swift" }.first != nil | ||
guard hasPackageFile else { return .init(value: ()) } | ||
|
||
let task = Task("/usr/bin/swift", arguments: [ "package", "generate-xcodeproj" ], workingDirectoryPath: dependencyPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should definitely have a project event that gets printed to the console.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generating an Xcode project to the dependency directory makes it dirty so that should be avoided. You should generate a project to a temporary directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ikesyo For a temporary directory, would $TMPDIR
be preferred?
.flatten(.concat) | ||
.ignoreTaskData() | ||
.on(value: { (project, scheme) in | ||
NSLog("Building scheme \"\(scheme)\" in \(project)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remove this log from the test?
@mdiep, Sounds cool. I found that SPM generated project can cause a problem if the library has dependencies. I'll update this PR soon with more specific tests. Thanks! |
Source/CarthageKit/Project.swift
Outdated
public func generateSwiftPackageManagerXcodeProjectIfAvailable(forDependencyAt dependencyPath: String) -> SignalProducer<(), NoError> { | ||
let files = (try? FileManager.default.contentsOfDirectory(atPath: dependencyPath)) ?? [] | ||
|
||
let hasXcodeProjectFile = files.lazy.filter { $0.hasSuffix(".xcodeproj") || $0.hasSuffix(".xcworkspace") }.first != nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not be sufficient––Carthage allows having Xcode projects or workspaces in any subdirectories so you should need to check the dependency directory recursively.
let hasPackageFile = files.lazy.filter { $0 == "Package.swift" }.first != nil | ||
guard hasPackageFile else { return .init(value: ()) } | ||
|
||
let task = Task("/usr/bin/swift", arguments: [ "package", "generate-xcodeproj" ], workingDirectoryPath: dependencyPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generating an Xcode project to the dependency directory makes it dirty so that should be avoided. You should generate a project to a temporary directory.
Another viewpoint: Deployment target settings of a generated Xcode project are not set for iOS, tvOS, and watchOS (macOS is set to I'm still reluctant to add this feature. |
When talking to the SwiftPM folks, this did seem like a potential issue. I'm not super knowledgable about it, but they mentioned the idea of passing an I guess any SwiftPM project wouldn't depend on the SDK, so Carthage could hardcode the oldest viable option?
I think you're more knowledgable about this than I am, so definitely speak up if you think something is a bad idea. |
Sounds reasonable to me. We can pass |
We can set deployment version by providing a xcconfig and bundle version by modifying an Info.plist. Currently I'm archiving SPM generated xcodeproj as following:
I think I can do similar with Swift but I'm not sure this would be the best solution 🤔 |
Is there any update on this one? |
There's some unaddressed feedback above. |
The generated xcodeproj has all platforms available as build targets, I spoke to @aciidb0mb3r about it and he said that the platform specification in Edit: well the deployment targets ARE set correctly. So maybe the trick is to only build for the platforms that the target project sets? Not fool-proof, but perhaps sufficient? |
Hey everyone, so I've been thinking about this a lot and here is my current plan:
I will begin work on this, this weekend, so if there are concerns with my approach, please speak up! Thanks for the help 🙏 |
As an update here I have submitted a PR to SwiftPM to get the platform information from the |
Update: the |
May I ask how are we doing with this PR? |
I am unlikely to find time for this in near future, here’s my progress though: |
@mxcl: Would you mind elaborating a bit on what would need to be done on your PR? |
I believe the remaining part is parsing dump-package and setting deployment targets, nothing else. |
From what I can see these are the following settings which would need to be added to the generated Xcodeproj: IPHONEOS_DEPLOYMENT_TARGET = 8.0
SUPPORTED_PLATFORMS = iphonesimulator iphoneos
SDKROOT = iphoneos
DEFINES_MODULE = YES
MODULEMAP_FILE = $(PACKAGE_NAME).xcodeproj/GeneratedModuleMap/$(TARGET_NAME)/module.modulemap Steps:
If the project does not specify platform information, I'm guessing we should just fail out - but some steer on that from the core contributors would be good. If the above sounds reasonable, I can give it a go - but I will hang fire until I get some feedback. Edit: Have I found a further complication? Unless I'm missing something, I think we will also need to generate an xcodeproj for each platform we want to build for because only one target is generated by SwiftPM. |
I don't think so, @ollieatkinson @mxcl any continued work on this? I may be able to help pick it up, as we currently are writing a bunch of SPM modules internally that need Carthage integration for some of our current apps and support both is a bit of a pain for the interim, so would be interested in helping out on this |
So, looks like there's an edge case that won't make this workable for us, and that's when an SPM project has dependencies that are also Carthage dependencies by the consuming project. Probably won't take this on anymore myself, as I don't think there's any solution to that problem :/ |
@devxoul Hey! What is the status of this PR? It is open since 2017. It would be great if Carthage could build Swift Packages :) |
@thedavidharris: I understand the issue of having common dependencies between SPM and Carthage, and that's an issue because Carthage is not designed to deal with that manually. However, it is currently a problem that libraries that only support SPM cannot be used in a Carthage project. Do you think there could be a way to deal with that problem by leveraging xcodegen? I'm thinking of a way to generate an xcodeproj that would embed SPM packages, while allowing to ignore SPM dependencies that also come from Carthage. Would be fine if it requires some manual work to get the setup correct, as it would allow Carthage users to benefit from SPM-only libraries. Or do you think that it's not worth it and SPM will quickly take over now that it is embedded in Xcode? |
Anyone trying to accomplish this, I got it running fairly easily with another tool in combination with Carthage. No need to manually maintain xcodeproj files, as this can generate them from your
|
Background
Swift Package Manager doesn't have Xcode dependency so the library authors can distribute their code without Xcode project files. Already there are many projects that don't have Xcode project files in their Git repository (e.g. ReactorKit). One of the most important design goal of Carthage is to reduce the responsibility of Xcode:
This PR makes Carthage to have less dependency of Xcode by supporting SPM-only libraries.
Summary
swift package generate-xcodeproj
before each build processes if the dependency doesn't have both.xcodeproject
and.xcworkspace
butPackage.swift
.Related Issues