Xcode subproject framework dependency build fail - ios

I have one Xcode iOS project (I'll call it the super project) which contains another Xcode iOS project as a subproject.
The subproject is an iOS static library. I have done everything described at http://www.blog.montgomerie.net/easy-xcode-static-library-subprojects-and-submodules.
So, the static library is listed as a target dependency under the super project's target's build phases.
The static library is already linked as a binary library in the super project's target's build phases. In a class in the super project, I am able to reference classes in the subproject but when I try to build the super project I get tons of errors for undefined symbols.
These "undefined symbols" are classes in the frameworks that the subproject (static library) depends on. My question is, how do I get the super project build process to be able to locate the header files of the frameworks that the subproject depends on?
I assumed that linking the static library would have handled this unless I'm doing something else wrong. Just for the heck of it, I also tried linking all of the frameworks that the subproject depends on as binary libraries to the super project.
This got rid of all the errors but then the build still failed because it says there were 33 duplicate symbols (because now both projects are linking the same frameworks).
I do not think that the super project should have to link the subproject's framework dependencies. Thanks in advance.

I think your problem is that the superproject do not find all the static library headers when the build fails with tons of "undefined symbols" errors.
Have a look in superproject settings panel, under build settings tab. Find "header search paths" and "user header search path" (or something similar) and put inside them the path of subproject headers folder. If you put /** at the end of the path, xcode will search inside all the subfolder of the path.
Make sure the "always search user header search path" flag is on/true.

Related

How to create a close source SDK for iOS with other framework dependencies

I have multiple projects that build into XCFramework. For example:
FeatureA.xcframework
FeatureB.xcframework
FeatureC.xcframework
When I build MySDK, it produces a .xcframework with a "frameworks" folder in it. FeatureA, B and C are inside that folder. This means that the frameworks were embeded.
But, when I add MySDK into another project and try to build I get: no such module "FeatureA" OR Could not build "FeatureA" to Objc.
The only way that my test project builds is by adding each .xcframework dependency. I tried using the search paths, but no luck.
I also tried change the modulemap file, but the error describe above continues.
I want to build a SDK, MySDK.xcframework that contains all depencency frameworks. In this way I hope that someone who wants to use my library will only have to import MySDK.xcframework.
What I want is even possible for iOS?

Interdependent frameworks Xcode

I'm working on a set of (internal use only) frameworks that encapsulate various elements of my development process. Some of these frameworks are dependent on one another, but I'd like to keep them separate so as to be more manageable. I'm running into various compiler errors now which I think have to do with the dependencies overlapping.
At the moment all of these frameworks and an app share the same workspace as different projects. How can I configure my app and frameworks to compile in this situation?
Here's the boiled down idea:
App dependencies: A.framework B.framework C.framework D.framework
A.framework dependencies none
B.framework dependencies A.framework
C.framework dependencies A.framework B.framework
D.framework dependencies none
More info:
Currently, in C.framework, I have dragged A and B.frameworks into the "Frameworks" folder. I read elsewhere to do that an to not Link Binary With Libraries. Either way, I get a compiler error for some functions that are in the headers of both A and B.framework:
ld: symbol(s) not found for architecture armv7
The build settings for A & B have "Build Active Architectures Only" set to NO and valid architectures set to include "armv7".
B.framework, however has no issue building.
Update :
I'm now able to get the App to build, by Linking Binaries in each of the targets... however it immediately crashed with this error :
dyld: Library not loaded: #rpath/A.framework/A
Referenced from: /var/containers/Bundle/Application/94488FD7-B731-4E6B-86E6-3D2F09BB4E04/App.app/App
Reason: image not found
The problem most likely causing this error message is related to the libraries not building in the correct order.
One possible solution to the order the libraries get built lies in adding all dependent libraries as sub-projects to the main project. This is appropriate when all projects are owned and maintained by the same entity, as the OP mentioned.
Add each project to the main one by going to "Build Phases -> Link Binary With Libraries.", then add each framework project file using the "+" button. Then go to each sub-project, and add it's dependencies.
For B.framework project, go to "Link Binary With Libraries.", and add A.framework as a dependency.
Similarly, for C.framework, add A.framework and B.framework, as dependencies.
As a suggestion, also add all frameworks to "Link Binary With Libraries.", under the main project, all of them get used.
One thing to keep an eye out in such situation, is to make sure there are no circular dependencies, and dependencies don't get added multiple times in different projects.
The image below shows an example of a similar setup to the one in the OP. There is a FrameworkTest project. All 4 frameworks are added as "Link Binary With Libraries." under it. For FrameworkB, FrameworkA is added under "Link Binary With Libraries.". Similarly workflow for FrameworkC. Xcode seemed to figure out the dependencies without the need for "Target Dependancies" settings. This project builds and runs. Haven't gotten as far as calling items from each framework.
Another solution to this, using a workspace would be to have one top level project, and move each framework as a sub-project. Then add each framework to the top-level project's "Embedded Frameworks" section.
Use the "Link Binary With Libraries." section of each framework sub-project, to define its dependencies.
Ok, so I seem to have gotten past this in the following way.
Instead of having my workspace have each framework as a separate "top-level" project, I moved the framework projects into sub projects of the App project.
Then, I added each framework to the App's "Embed Frameworks" section (and was able to remove it from "Link Binary.." and "Target Dependencies" sections.
Within each framework, I used the "Link Binary..." section to include the dependent frameworks.
I'm not sure that I understand all the pieces to why this works, but at least I can move on!
Thanks #vel-genov for your help!
Make sure these settings are correct:
FRAMEWORK_SEARCH_PATHS (in Build Settings)
Link Binary With Libraries (in Build Phases)
INSTALL_PATH (change to #rpath for all frameworks) (in Build Phases)
#rpath (Runpath Search Paths) (add #executable_path/../Frameworks for your app and all frameworks that need embedded another framework) (in Build Settings)

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.

Duplicate Symbol Error: SBJsonParser.o?

I currently have ShareKit in my project that is compiled as a static library. It is properly implemented. I also have implemented Amazon's AWS SDK by just adding their framework into my project.
It seems that the duplicate symbol is coming from Amazon's AWS SDK file, "AWSIOSSDK". This is what it looks like:
And that file is colliding with ShareKit's file, libShareKit.a. This is what that file looks like:
Anyway both of these files are ones that I haven't seen before. And it seems that some JSON files are colliding within them.
I have looked at other SO questions and they say to do some things with the compiled sources but none of these files are in the compiled sources from either library.
Here is the exact error Xcode gives:
ld: duplicate symbol _OBJC_CLASS_$_SBJsonParser
Anyway, does anyone have any ideas what I should do? My app does not compile unless I fix this issue.
Thanks!
You could go ahead and split a library archive into its object files and merge them again by leaving out the duplicates.
See the following walkthrough for getting an idea to manage that task:
Avoiding duplicate symbol errors during linking by removing classes from static libraries
Both of these have built SBJsonParser into their static libraries. This is not the correct way to build a static library. Each should build without SBJson and then you should link all of them together with SBJson. There are a couple of solutions:
Rebuild these libraries (or have their maintainers do so) to not include third-party libraries directly into a static library. This is the ideal solution.
Remove the incorrect SBJson files from the .a files using ar. You should be able to do this using ar -t to list the objects in the .a and then ar -d to delete the ones that shouldn't be in there. You could of course also ar -x to extract all the .o files and link them directly.
I had the same issue with FaceBookConnect Framework (let's call it project B) and my project (project A). Both were linking again JSON framework.
The solution is :
Go to Project B > Target > Build Phase > Remove JSON from the "Link Binary with libraries"
Make sure the JSON framework is still in the project (don't remove it) so project B can build
Build your project B you shouldn't get any error. The project should build but not embed the JSON frameworks symbols
Add both project B product (a framework) AND JSON framework in project A
Go to Project A > Target > Build Phase and check that both project B and JSON have been added to the "Link binary with libraries" section
Build your project A
Regards,

Is there a better way to link to a configuration specific static lib on iOS than OTHER_LINKER_FLAGS?

Situation: Linking against an SDK (which I'm building) that has Release, Debug, & Distribution versions of it's static library (.a file). There doesn't seem to be a way in Xcode GUI to indicate that a static library is only used for a given Configuration.
I can use "Other Linker Flags" (OTHER_LDFLAGS) in the Build pane of the target or project settings like this:
-all_load -ObjC "${SRCROOT}/MySDKFolder/${CONFIGURATION}-universal/libMYsdk.a"
which seems to work. Just wondering if anyone knows a better way. ( the -all_load and -ObjC are to get ObjC categories linked in properly).
I'm using gcc 4.2 at this point (SDK default for 4.3 sdk and 3.x.x Xcode).
So, it turns out I was letting the Xcode UI confuse me. If you add the generic search path with the ${CONFIGURATION} variables and then add one of the static library instances to the project and target it'll do the right thing and link with the right one even though if you get info on that library in the project it'll show you the specific path.
However, if you want it to actually have Xcode notice changes made to one of the static libraries, you'll need to add ALL versions of your static library to the project and target (yes, it'll look like it's linking with all three, no worries!).
To have Xcode detect the the .a file changed as the result of a build script phase you have to actually have all the source files that are used to build the .a file in the Run Script Input pane (a pain!) to not have to run your build script every time; And all three variants of the .a file in the output pane so Xcode knows what to check after your script runs to see if it needs to relink the project.

Resources