CocoaPods and Target Dependencies - ios

I recently inherited an old iOS 5 multi-project that have a xcworkspace that have the following projects:
Communications project: contains some reusable code and frameworks, defines a target as static library.
Client project: iOS client project that has nested a symbolic link to the 1. project and includes a Target Dependency to it.
Manager project: same structure as described for 2..
Note: to clarify the meaning of static library and nested projects, please have a look to http://www.raywenderlich.com/41377/creating-a-static-library-in-ios-tutorial (Method 2: Subprojects).
I am trying to add CocoaPods for the 3rd project, but I can't modify the HEADER_SEARCH_PATHS and OTHER_LDFLAGS values because they are use to link the static library.
Is there any workaround for this?

I found the answer, it is as simple as add manually the $(inherited) option to HEADER_SEARCH_PATHS without deleting the existing static library headers dir.

Related

Embedding XCFramework in application with project framework dependencies

I have an Xcode workspace which features a project with an iOS Application target, and another project with a Framework target. The framework target is dependent on another framework, which is integrated in the form of an xcframework:
MyApp
MyFramework
OtherFramework
Using regular OtherFramework.framework would require it to be linked to MyFramework and then embedded in MyApp even though MyApp doesn't require the framework itself. However when integrating with xcframework, this project then fails to build with a No such module 'OtherFramework' error.
Project settings:
MyFramework Project
MyApp Project
Removing OtherFramework.xcframework from the MyApp target fixes the build issue, but then causes library not loaded errors as the framework is not present in the application.
Demo project here: https://github.com/msaps/XCFramework-Link-Issue
How are you meant to link an xcframework in an application and link in a dependent framework?
Why?
pyckamil just posted this article which explains the issue in detail: Everything wrong with XCFrameworks.
It turns out Xcode has an optimisation for the ProcessXCFrameworkLibrary step which extracts the correct .framework from an .xcframework for the active build architecture. This is only run once which causes issues for additional targets that try to link the same framework.
Update
This issue is resolved in Xcode 12.0
UPDATED - Resolved in Xcode 12.0
shinsuk came up with a reliable workaround that works by adding architecture-explicit framework search paths to ensure the correct .framework within an XCFramework is found.
Details can be found in the README.
Check build settings and defining the Framework Search Paths to a folder which contains the frameworks in question. If the frameworks are placed in your project directory, simply set the framework search path to $(SRCROOT) and set it to recursive.
check the response Getting error "No such module" using Xcode, but the framework is there
IMO, It seems not xcframework issue.
Check out this answer: https://stackoverflow.com/a/59435627/2661407
Umbrella frameworks are not supported on iOS, watchOS, or tvOS.
OtherFramework.xcframework should be signed and embedded in your host app.
and add "#executable_path/Frameworks" setting into your MyFramework.framework > Build settings > Runpath Search Paths.
I had this issue as well after using xcframework instead of framework. So I changed my project structure:
The MyFramework Peoject embed OtherFramework.xcframework,Then make it exported using #_exported import OtherFramework in MyFramework Project. And the MyApp just link MyFramework but can both import/use MyFramework and OtherFramework.
BTW, It seems to custom the #rpath and manual codesign the OtherFramework.
I had an issue like that as well.
First, make sure if you have MyFramework.framework file within the same directory as MyApp.
Second, when building MyFramework.framework, make sure that OtherFramework.xcframework is as well in MyFramework's project directory.
And one more thing, check target SDK versions. They should be somewhere on the same level.
I had the same issue as you, and after seeing your pbxproj I think it can be solved the same way.
Change your framework search path to recursive (either through UI or manually editing the pbxproj "$(SRCROOT)/../Frameworks" => "$(SRCROOT)/../Frameworks/**"), like so: https://github.com/msaps/XCFramework-Link-Issue/pull/1/files

Trying To Merge Static Frameworks Using Carthage

carthage version: 0.25.0
xcodebuild -version: 8.3.3
Are you using --no-build? No
Are you using --no-use-binaries? No
Are you using --use-submodules? No
Are you using --cache-builds? No
Cartfile
github "rs/SDWebImage"
github "AgileBits/onepassword-extension"
github "hsousa/HCSStarRatingView"
github "sugoi-wada/facebook-ios-sdk" "780a72cd6086c57939d83a7143462ae13dfb9a74"
github "CSStickyHeaderFlowLayout/CSStickyHeaderFlowLayout"
github "card-io/card.io-iOS-source"
I'm able to build my dependencies using a build script as outlined in the documentation here. Now I'm trying to merge my static frameworks into a dynamic one and running into problems.
To start, I'm adding a single framework to the dylib target, I've disabled bitcode and added the following OTHER_LDFLAGS: -all_load, -ObjC. I'm starting small with the HCSStarRatingView. It has been added to they dylib target and that builds.
To test this new combined framework I've added an app target. I can import the framework target and the app target recognizes it. However when I try to declare a new view with let view = HCSStarRatingView(frame: .zero) I'm getting the following error: Use of unresolved identifier 'HCSStarRatingView'.
I'm assuming that I don't import HCSStarRatingView directly because it's now part of my framework target. I'm also assuming that I don't have to add anything to my dynamic framework target's umbrella header to expose the linked static frameworks inside. Are those assumptions correct? Any idea what I could be missing here?
i think your assumption might be wrong.
I have a similar setup and got it working by importing both: dynamic framework and the static library that it depends on. eg:
import framework-target
import HCSStarRatingView
furthermore i had to make sure that the app target included the carthage build path

Xcode Swift: how to import a Swift project

I have made an Xcode Swift project ("Project1"). In a new project ("Project2"), I have trouble adding project 1.
I have tried adding project 1 to project 2's build phases (target dependancies, compiled sources, link binary with libraries); didn't work. When adding to the compiled sources, it wouldn't work no matter which option I chose (folder references, groups, copy if needed).
I get no compiler errors at:
import Project1
But when I try to use a class from project 1, I get the error "Use of undeclared type".
I have also tried to following links with no success:
External library usage in xcode
Xcode : Adding a project as a build dependency
Xcode how to add an external project
Both projects are in Swift (iOS).
I'd be very thankful if someone helped me with this issue.
Update: Project 1 is not a framework - it's an iOS app. I need to use some of its classes in project 2. The problem is that project 1 uses the Objective C library Common Crypto via a bridging header. When I manually add project 1 classes into project 2, I get an error ("unresolved identifier") in the project 1 Swift code that uses Common Crypto.
So in a nutshell: I have an iOS app (project 1), which is in Swift but uses Common Crypto via bridging header. When I add a number of classes from project 1 into project 2, it cannot resolve the references (in project 1) to Common Crypto variables.
Assuming Project1is a Framework and Project2 is an application using the framework:
Create a virgin Workspace (Xcode File -> new -> Workspace) named TestWorkspace
From the Finder, drag the Project1.xcodeprojfile to the TestWorkspace
From the Finder, drag the Project2.xcodeprojfile to the TestWorkspace, above Project1
Edit your TestWorkspace schemas Build setup:
Add Project1 and Project2
make sure Project1 is above Project2
Untick "Paralellize Build" to assure Project1 is build first
Build
Select Project2s target -> General
Drag artefact project1.framework(in Productsgroup) to "Linked Framworks and Libraries"
Note: To be visible for the client, all classes and methods in your project1.framework have to be public or open. Finde detailed information in Apples documentation.
Edit: As you have CommonCrypto as a dependency you will have to add the module to your Project2 project instead to solve your issues ( this is the easiest without resorting to an umbrella framework ). Add a run script build phase and include http://pastebin.com/1vmiqffu
-- Credits: Script 'stolen' from: https://github.com/henrinormak/Heimdall
Ok so I'm going to assume here that Project1 actually has a framework as a target. What are the access permissions set on the types you are trying to use?
Here are a couple of catchya's with Swift and frameworks as I encountered them:
You do not have a bridging header, instead your framework includes headers of non-Swift dependencies inside the header file of your framework ( ModuleName.h ). This also means these will be available to whatever project you import them to. As far as I know you need to use a module.modulemap in order to make use of private headers and includes.
All Swift Classes / Structs / Definitions in general are internal by default. It is a very good design choice and it forces you to think about the access rights on every component you write. Keeping things private by default makes it easier to only open stuff that really needs to be open ( public, open ), allowing for easier code maintenance since you know that private things are only accessed within the same context. ( Otherwise: error )
For some more assistance this link might be of help to you on how to do some fundamentals:
your first ios framewok (swift)

Can you make a Podspec with conditional dependencies?

I want to know if you can define dependencies on an static lib in a podspec depending on the type of the Target that the Pods project is going to be linked to.
I need to be able to NOT add a dependency to an static lib if the target project is itself an static lib.
Why I need this?
I've built a podspec for cocos2d-iphone v3 and using it in a personal pet project. Works perfectly when you use it as a dependency for an executable. Unfortunately it doesn't works well the way I've organiced my project:
It's a multiplatform project app consisting in two xcode projects for the ios and osx executables. Both link to an static library with shared code (another xcode project). I've made the cocos2d a dependency for that last static library.
Unfortunately, cocos2d has a dependency over lib z, which is also static. As you can't link two static libraries the link phase fails. The error message is as follows:
file: -lz is not an object file (not allowed in a library)
It's easy to remove that dependency but I would prefer the process to be more easier for the end user.
My approach to solve this problem would be add a conditional in the podspec so the lib z only is added if the project is not an static library. I guess it can be done with pre_install hooks, but they are discouraged by the cocoapods team.
Is there any other way to accomplish this?

How to make XCode add the linked project headers and implementaion files to the static library and framework

I have a static library project and in that project I linked a .xcodeproj to the source code so I can update easily actually and to not copy and paste files in the static library project for easy update.
The purpose thought it's to embed this .xcodeproj with my code into the result static library or .framework that I will build using a script.
Although I can see that there is nothing added in the compile sources or the copy header files which I added. If I try to add with drag and drop files from the linked project to my static library build phases copy header section it copies the file to my project again, but I don't want this.
And if I add a header file #import to one of my public headers and try to use the static library to the client project it complains that the header is not found!
So, in the end, what I want is the whole linked project files to be copied in the resulting static library or .framework with the scripts and target I have.
Is this possible to achieve, I think I miss some project setting that I'm not aware about that will see and copy all header and implementation files to my result static library or .framework?
Is my approach overall correct? I don't think that there is no option to use a linked project in a static library and embed it when the build is happening since I am using it in my project!
I could add the .framework of the third party component too and merge to my static library. I have created this question earlier today. Is it possible to include a .framework in a .framework and how?
Regards.
Not sure if your #import-not-found issue is a linker issue, but...
Make sure to use the -ObjC flag in "Other Linker Flags" in the library's Build Settings. This gets the linker to build everything in the library.
Mentioned here:
https://developer.apple.com/library/ios/technotes/iOSStaticLibraries/Articles/configuration.html
And also make sure you link in the library in the build settings for the project that needs it.

Resources