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

Nested frameworks folders, git and locations #768

Closed
drekka opened this Issue Sep 17, 2015 · 12 comments

Comments

Projects
None yet
5 participants
@drekka

drekka commented Sep 17, 2015

I'm using several frameworks which use nested frameworks.

App uses (->) frameworkA -> frameworkB

I tend to use the --use-submodules option because I'm also working on some of these frameworks because they are part of the app. When carthage checks them out and builds I get a flat structure like this:

<root>
    /Carthage
        /Build/iOS
                /libA.framework
                /libB.framework
        /Checkouts
            /libA
                /Carthage
                    /Build (link to <root>/Carthage/Build)
                    /Checkouts
                        /libB
            /libB
                /Carthage
                    /Build (link to <root>/Carthage/Build)

The odd thing here is that libB is checked out twice. I can see whats going on in that nested dependencies are added to the frameworks that own them, but then I'm not sure why carthage needs to check them out again at the top level.

I'm wondering why links cannot be used in the same way that the Build directories are linked back to the root Build dir.

This can actually become more confusing if you are building embedded frameworks. For example if the build for libA embeds libB inside the libA.framework file and the root project doesn't actually use it. In this case the app only needs to have libA.framework added to it. This could be confusing for people because they will be unaware that they do not need to add libB.framework to their project.

Is it possible for carthage to look at the shared build and check if any of the dependencies are being embedded? Is this even a good idea?

Another complication with the duplicate checkouts occurs if --use-submodules is set. In this case I get this:

<root>
    /Carthage
        /Build/iOS/...
        /Checkouts
            /libA (git submodule)
                /Carthage
                    /Build (link to <root>/Carthage/Build)
                    /Checkouts
                        /libB
            /libB (git submodule)
                /Carthage
                    /Build (link to <root>/Carthage/Build)

Now we have the top level projects as submodules ready to be modified, but the nested projects remain as exported versions. So I have to be careful about which ones I load into XCode. Would using links for nested projects help avoid this?

I suspect this all comes back to dealing with dependencies and versions.

@jeeftor

This comment has been minimized.

Contributor

jeeftor commented Sep 17, 2015

I was just about to ask the same question...

I was looking through my application and i have the same framework embedded 3 times

@mdiep

This comment has been minimized.

Member

mdiep commented Sep 18, 2015

Carthage discourages the use of embedded frameworks. If a framework is embedded, then you can't use it from multiple frameworks or rely on Carthage's dependency resolution. (If A and B both depend on C, then you want Carthage to pick a version that works with both A and B—and you only want to link it to your app once.)

As for symlinks, they might be possible in the non-submodule case. If you're using submodules, I think symlinks would only lead to pain.

In any case, you should only be modifying projects in the top-level Carthage directory.

@jeeftor

This comment has been minimized.

Contributor

jeeftor commented Sep 18, 2015

Any chance we will see support for this anytime soon? I have a networking framework used by some higher level frameworks for example.

@mdiep

This comment has been minimized.

Member

mdiep commented Sep 18, 2015

If you're using that networking in multiple higher-level frameworks that are used in the same app, then you don't want to nest it inside them. There a bunch of versioning problems if you do this.

You can still use the networking framework in your higher-level frameworks. You just don't embed them—the app target has to do that.

@drekka

This comment has been minimized.

drekka commented Sep 22, 2015

Okies. Thanks for the feedback. We have now flattened our frameworks.

@lemonkey

This comment has been minimized.

lemonkey commented Nov 19, 2015

I have a similar situation, where my existing project is an iOS application, which has a submodule that is the main static library for lower level code, etc. Wanting to convert this to a dynamic framework to support Swift, but this library already has 3rd party dependencies (was originally using Cocoapods). These dependencies are also being used in the iOS application.

The submodule static library has its own unit tests, etc. so it needs to be able to be built on its own and get those 3rd party dependencies. However, the parent app also needs these dependencies for its own logic, etc.

Would it be possible to flatten the overall framework architecture in this case using Carthage?

@mdiep

This comment has been minimized.

Member

mdiep commented Nov 20, 2015

@lemonkey We typically add the 3rd party dependencies to the framework—usually with submodules using Carthage. Then we add both a .xcodeproj and .xcworkspace for the framework. The project contains all the code for the framework. The workspace includes that project and the projects for the dependencies. Then consumers of the framework can include it through the project or build it through the workspace. You could look at https://github.com/ReactiveCocoa/ReactiveCocoa for an example.

There are other ways to do it, but that's what I usually do.

@lemonkey

This comment has been minimized.

lemonkey commented Nov 20, 2015

Thanks for the insight! 👍

@Vadim-Yelagin

This comment has been minimized.

Vadim-Yelagin commented Dec 1, 2015

@mdiep but if you include ReactiveCocoa in a project using Carthage, it will check out ReactiveCocoa and Result (as its dependency), but inside ReactiveCocoa's Checkouts directory there is another copy of Result. Namely, there is Carthage/Checkouts/Result and Carthage/Checkouts/ReactiveCocoa/Carthage/Checkouts/Result.
If you then have another project including this one with Carthage, you'll end up with Carthage/Checkouts/Result, Carthage/Checkouts/ReactiveCocoa/Carthage/Checkouts/Result, Carthage/Checkouts/MyProject/Carthage/Checkouts/Result and Carthage/Checkouts/MyProject/Carthage/Checkouts/ReactiveCocoa/Carthage/Checkouts/Result. So this escalates exponentially. Is there any way around this, other than "do not make your libraries depend on other libraries"?

@mdiep

This comment has been minimized.

Member

mdiep commented Dec 1, 2015

@Vadim-Yelagin Why are you concerned about the additional on-disk checkouts?

@Vadim-Yelagin

This comment has been minimized.

Vadim-Yelagin commented Dec 1, 2015

@mdiep First, I'm curious if that's the way it's supposed to be. Second, that can become a real problem as the nesting gets deeper: for 1 level it's 1 checkout, for 2 it's 2, for 3 it's 4, for 4 it's 8, for 10 it's at least 512 copies of one repository.

@mdiep

This comment has been minimized.

Member

mdiep commented Dec 1, 2015

Yes, that's expected. Realistically, dependencies don't get reused that often, so I haven't seen it be a problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment