Can I parallelize my build when linking against multiple interdependent static libraries? - ios

I've built my app as a workspace containing one project with an app binary target and many projects containing static library targets. My app target links against all the static libraries. Some of my static libraries depend on each other, and I handle this by ordering the targets built in my scheme so that all dependencies are built before the libraries that depend on them.
What I'd like to accomplish is to use the 'Parallelize Build' feature to speed up building my app scheme. However I need to ensure that my static libraries are built with respect to their dependencies. It doesn't seem like I can set 'Target Dependencies' between these static library targets because they are not all in the same project (Is this the case or am I misunderstanding how this works? Is it possible to have cross project target dependencies)?
Is there any way to accomplish this? Thanks for any information!

After some research it does seem like the only way to get this working is to set up my app using nested subprojects instead of a workspace (so that I can create target dependencies between my dependent libraries). I'd love to be corrected on this point if anyone knows another way!

Related

Make framework compatible for different Xcode versions

I have a specific scenario I am trying to overcome and have yet to find a solution (if one exists) to my problem.
I am building a framework that can be used inside of other applications. This framework contains static libraries.
Now, inside my framework, if I want to add classes that use APIs from Xcode12, I would also want my framework to be able to compile in Xcode11.
This could obviously lead to compilation issues as I have no control of my framework inside other applications and as my framework will already be turned into a binary file (.a). Adding any build script to the frameworks' build phases won't be relevant.
I have been trying to look for similar scenarios or solutions for this problem, but have yet to find anything substantial.
Is there any way to overcome this or am I trying to do something that is impossible?

Hundreds of targets, same code base in xcode configuration

We are at 400+ targets in xcode. It still works fine but there has to be a better way to set this up by keeping the same code base but not having all those targets which could slow down xcode.
Android Studio lets you update the appname, which loads that folder from disk so only that project is loaded to run and program against. In XCode that is not the case, all targets are available.
It's been years but is there a better way now, with hundreds of targets that doesnt involve Git or Branching? The questions in regards to this are old and only for a few projects, we are talking hundreds here.
Your question lacks enough context to make a specific recommendation but in general...
Use Frameworks
If you can, combine sensible things into a single (or multiple) framework target. Frameworks can be more than fancy wrappers around a dynamic library, they can contain helper tools and such as well.
Use Workspaces
If there is a logical grouping to your existing targets you can separate them out into their own Xcode projects. Once you have them in their own projects you can create a workspace that references those individual projects. Even if the combined workspace loads in everything upfront (I don't think it does tho) you can still open and use the separate projects for a fast and fluid experience when working on the components.
Use static libraries
If you have a ton of targets such that one requires A, B, and C, but another needs B, C, D then you can actually put A, B, C, and D together in a static library and rely on the linker to strip out unused code from each individual target. This obviously does not reduce the number of targets you have, but you can make the static library its own project and include it in a common workspace. This will also speed up compilation as the files only need be compiled once.
Parameterize Targets or Use Schemes
If your targets are simply wrapping some external build tool/script with hardcoded parameters (I've actually seen this) you can actually pass a ton of existing variables from xcode to these external tools and eliminate "duplicate" targets. Similarly you can add new schemes if some of your targets are simply permutations of each other. A good example I've seen of this are people that have a separate target for "sanitized" (address sanitizer, etc) builds you can instead create a sanitization scheme instead of a target.
Use "Script" Build Phases
If some of your targets are doing something such as linting then you can instead employ a script build phase to call the linter instead of having a separate target to do it.
Offload Targets to an External build System
Xcode can have targets that simply call out to an external tool/script using the Script build phase (and using variable parameters as mentioned above). This can make sense to do if you already use another build system (make, cmake, etc) for another platform. Use Xcode only for the Mac/iOS specific targets and offload everything else to a cross platform build system.
If the build system outputs errors in a format Xcode understands it will even show file and line errors the same as native Xcode targets. I've seen people write thin wrappers around external tools to catch parse and reprint errors into such a format.

How to re-export a framework and use it in another project in iOS? (Should I?)

I have two projects I'm working on in XCode. Project 2 depends on Project 1, and I want it to be able to use the same frameworks I have embedded in Project 1 (they're Carthage dependencies). I discovered the "Re-exported Framework Names" section in Build Settings, but I'm not at all clear on how I might use it.
What should I put in that field? Just the name? (PromiseKit). Or the filename (PromiseKit.framework)? Or the full path?
How do I then reference this framework in Project 2? Right now I'm getting a build error: framework not found PromiseKit for architecture arm64 and I can't see any obvious way to add that framework link.
And a broader question: do I need to do this? I'm a relative newbie and working on the assumption that setting up separate Carthage dependencies for both projects means that there will be two separate compiled frameworks in my final binary, which would be a waste. But is XCode cleverer than I think and taking this into account?
If the two projects are related, put them in the same Xcode workspace and then you can share the frameworks between the two.
If the projects are independent, put the frameworks into a separate folder, add them separately to both projects and when adding them to the projects, don't choose Copy files if needed.

Embedding Dependency Frameworks into a Single Dynamic Framework

I have this project that is designed to be used as a Dynamic Framework, named ProjectA.framework.
However, ProjectA depends on other dynamic frameworks, such as Alamofire, Realm, and a couple smaller ones. I want to generate a single .framework file that contains all the frameworks embedded, but I'm not sure if it's possible.
Now I have ProjectB, that will use ProjectA as a dynamic framework, and ideally I would like to drag only the ProjectA as a dependency. I'm using Carthage, and it automatically fetches and builds all dependencies, but I'm dragging only ProjectA.framework into the Linked Frameworks and Libraries section.
The projects builds, but gets a runtime error, complaining that one of the third party dependencies was not found.
It is possible to achieve what I am trying to do?
Is this a limitation of carthage or a wrong setup on my side?

iOS dependency management and packaging

I'm completely new to iOS development and coming from an Android background. I was starting to look at what alternatives are out there for dependency management in iOS and found out that CocoaPods seems to be the most prevalent option.
After reading a lot of links about this topic I'm kinda at a loss and wondering what is the usual way dependencies are handled in iOS.
I have two questions:
1) What would the equivalent of using gradle to generate library (.aar) projects be in iOS? If there's any equivalent option. From what I've seen one can wrap static libraries and headers into frameworks and these can be used in other apps, is this the standard way to do it?
2) If (1) is correct, does CocoaPods offer a mechanism to add frameworks as dependencies?
I don't have a Android background but from what I understand of .aar files CocoaPods does something very similar. CocoaPods uses .podspec files (described here) to generate static libraries (and soon dynamic frameworks which are new in iOS 8) that are then linked into your project.
A podspec can define source files, assets, libraries, or frameworks that a source vendors for linking into your application. So yes it does support adding frameworks as dependencies, although until iOS 8 frameworks were not supported at all on iOS.
As far as the 'standard' way to do it, I think that's based on opinion. There are a few general ways to include dependencies you can choose from.
Drag files, frameworks, and whatever else you need into your project manually. Updating these is more difficult and that also means you have to configure your .xcodeproj depending on what features that library needs (such as ARC)
Drag a provided .xcodeproj into your project, and link the relevant target from the given project. This can be nice if the library provides a project that can build a framework or static library, in this case you'd pull in that library but their project would handle custom compiler flags.
Do either of the above while including them as git submodules. Assuming nothing massive changes in the project this helps a lot with updating your dependencies.
Use CocoaPods. CocoaPods will handle all the custom linking and updates based on semantic versioning (usually).
Use Carthage. Carthage is an in- between CocoaPods and the .xcodeproj solution. It will download code based on semantic versions defined by git tags, then you drag the generated frameworks into your project.
All of these options have pros and cons and the decision normally comes down to how you feel about the control you have over the inclusion of the library, and how automated you want it to be.
I do not have android nor iOS background however I've been developing a CI tool for both platforms and here are the answers
As You mentioned this a framework and pods (libraries) from cocoapods are distributed that way. For instance, have a look at Apphance. When spec is clicked it's visible that this library will be accessible as a Apphance-Production.framework.
You add pods to Podfile and download them with pod install command. This command will made classes from Apphance accessible from the code. Some people do commit downloaded pods, other not (it's like adding jars or aars to source control).

Resources