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: allow podspecs to declare Swift Package Manager dependencies with spm_dependency #11953

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

mfazekas
Copy link

@mfazekas mfazekas commented Jun 15, 2023

Implements: #11942

See also: #743
and: #344

Also note that implementation is very simplistic, if same spm is included by multiple specs they have to have the exact same requirements. In future this can be improved by implementing a version range merge.

See https://github.com/mfazekas/pods-spm-dep-poc/#how-it-works on description of the changes made to the pods project.

I've added a single integration test, but it required some hacking to project to to_yaml:
https://github.com/CocoaPods/CocoaPods/pull/11953/files#diff-2f87abe8c188a9e01c085e87a3a38d78dcc50ca8d2fe79367e5e2deec6bcd778R13-R15

@mfazekas mfazekas force-pushed the podspec-spm branch 3 times, most recently from fadf326 to d34cd52 Compare July 1, 2023 13:45
@@ -6,7 +6,8 @@
url = https://github.com/tonymillion/Reachability.git
[submodule "spec/cocoapods-integration-specs"]
path = spec/cocoapods-integration-specs
url = https://github.com/CocoaPods/cocoapods-integration-specs.git
url = https://github.com/mfazekas/cocoapods-integration-specs.git
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be reverted before merge

@@ -20,7 +20,8 @@ gemspec

group :development do
cp_gem 'claide', 'CLAide'
cp_gem 'cocoapods-core', 'Core'
# cp_gem 'cocoapods-core', 'Core'
gem 'cocoapods-core', :git => 'https://github.com/mfazekas/Core', branch: 'podspec-spm'
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be reverted before merge

@osrufung
Copy link

osrufung commented Aug 3, 2023

Thank you for this! 👏

@mfazekas
Copy link
Author

@dnkoutso how can we move forward with this?

@Dragna
Copy link

Dragna commented Aug 31, 2023

is there anything we can do to help in shipping this ? 🙂

@orta
Copy link
Member

orta commented Aug 31, 2023

A lot of it depends on folks' time to do OSS. As CocoaPods, if there's not a critical need for a release during betas we tend to really only ship after the RC version of Xcode - so I think this is likely to get some eyes over it in prep for making a release for the next Xcode major

We're happy conceptually with the idea, just needs some eyes over implementation ideally around when we are looking at making the next release

@Dragna
Copy link

Dragna commented Oct 25, 2023

@mfazekas I tested it (after rebasing on cocoapods 1.13.0), and it seems that if I define a dependency in a subspec, I see the library declared in the pod target where I defined the SPM dependency, but the spm dependency isn't added to the Pods xcodeproj.

I want to look into this to make it work, would you have some insight for me on where to look ? That would be really helpful🙂 🙏

end

def install_spm_dedpendecies(project, pod_targets)
spm_dependencies = pod_targets.flat_map { |target| target.root_spec.consumer(target.platform).spm_dependencies }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updating this line to get the dependencies on all the specs lets us define spm dependencies at the subspec level 🙂

Suggested change
spm_dependencies = pod_targets.flat_map { |target| target.root_spec.consumer(target.platform).spm_dependencies }
spm_dependencies = pod_targets.flat_map { |target|
target.specs.flat_map{ |spec| spec.consumer(target.platform).spm_dependencies }
}

@Dragna
Copy link

Dragna commented Nov 22, 2023

I'm getting here step by step, I added the possibility to add local packages to a podspec.

one problem I have now is that for reasons (unknown to me for now) I get a undefined symbols when building the project.

it means that if I have a Pod module A that depends on a swift package B, when I build my project, A compiles, but I get a compile error on the project stating that it doesn't know about B.

I may be missing a piece here (I'm lacking understanding of the build system) and any help would be great 🙂.

@mfazekas
Copy link
Author

mfazekas commented Nov 22, 2023

I'm getting here step by step, I added the possibility to add local packages to a podspec.

one problem I have now is that for reasons (unknown to me for now) I get a undefined symbols when building the project.

it means that if I have a Pod module A that depends on a swift package B, when I build my project, A compiles, but I get a compile error on the project stating that it doesn't know about B.

I may be missing a piece here (I'm lacking understanding of the build system) and any help would be great 🙂.

Can you check 3.) here?
https://github.com/mfazekas/pods-spm-dep-poc/#how-it-works

@Dragna
Copy link

Dragna commented Nov 22, 2023

Can you check 3.) here?
https://github.com/mfazekas/pods-spm-dep-poc/#how-it-works

Thank you for your quick answer 🙏

It seems that I have everything set here and the paths were added.

my error is not a No Such Module X on the pod importing my swiftpackage, it's more at the level of the target I'm trying to use which depends on the pod.

my target does not use the swift package code, only the pod.

if I manually add my package to the target, everything compiles.

I'm trying with a big project, I'll try making an example

@Dragna
Copy link

Dragna commented Nov 22, 2023

Ok I have a way of reproducing this, if the podspec that import the swift package is defined as a static_framework
s.static_framework = true, it's in this case that I have my error.
I must be missing a build setting in this case.
here is a small example project

SPMIntegrationInPodsExample.zip

you can install the env by doing :

  1. make // to install my fork of cocoapods where are my currents modifications (based on what you did)
  2. make install or bundle exec pod install // instead of a pod install (there is still some debug logging sorry for that 🙏)

I would totally understand that you don't have time for this, but if you think of anything that could be of help to me on how to better understand / solve let me know, I'll try to implement and test that to push a PR on your fork 🙂

@Dragna
Copy link

Dragna commented Nov 28, 2023

Hi every one,

I'm still investigating on the static_framework generation and I'm kind of stuck there, I must be missing something.

I have a test project that has 3 pods:

  1. LocalPod
    • is static
    • dependencies
      • EmbededPod
      • SwiftUIX using SPM
  2. LocalPod2
    • dynamic
    • dependencies
      • none for this example
  3. EmbededPod
    • is static
    • dependencies
      • SwiftUIX using SPM

in that configuration when I build my app I get a build error saying that I have duplicated symbols for SwiftUIX

I made another sample project, where I have almost the same architecture, but I don't use Pods, I use static libraries directly that have SPM as dependencies, and everything works fine, I can compile without problem.

I may be missing what the difference is between a vanilla static lib and a Pod static framework is. (it seems that in the case of cocoapods, it's generating .framework folder even for the static_frameworks)

if anyone has any idea that would be super helpful 🙂 🙏 .

Funnily if I add SwiftUIX using SPM to my LocalPod2 which is dynamic, I could then add the path to BuildDir/PackageFrameworks in the FRAMEWORK_SEARCH_PATHS to look for the framework and adding it in the OTHER_LDFLAGS.

If I do this everything seems to compile and work (no more duplicated symbols 🤷‍♂️) but it's more of a hack as I need to declare the package in a dynamic pod to see its generated framework in the build products.

@contfedorov
Copy link

@mfazekas
Could you please clarify if your PR deals with dependency resources correctly?

Imagine the situation. I have an OSS project on Github that defines SPM package. I am able to consume it via Cocoapods by manually creating .podspec with s.source and s.source_files defined. I have just one issue with this. Project has resources (strings, images, etc.) that are packed into .bundle file. XCode generates resource_bundle_accessor.swift that finds that bundle and makes it acessable to Swift code. In case dependency is consumed by SPM, that file is generated. In case dependency is consumed by Cocoapods, that file is not generated.

So, I am wondering if your PR can handle this.

@mfazekas
Copy link
Author

mfazekas commented Apr 5, 2024

@contfedorov so this PR does what's described in: https://github.com/mfazekas/pods-spm-dep-poc/#how-it-works

1.) Adds the Package Dependency to the Pods project.
2.) Adds the targets dependencies to Frameworks and Libraries of the pod
3.) (Adds to Swift Import Paths)

@contfedorov
Copy link

contfedorov commented Apr 10, 2024

@mfazekas
Can I do the same by modifying my .podspec in any way?

UPD Checked a bit more, looks like there are no chances to do it via podspec only. Thanks for your POC!

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.

None yet

6 participants