Non-pod framework (GoogleTagManager) missing reference to library moved to pod - objective-c

The use case is the following:
We developed an SDK, that uses, among other dependencies, GoogleAnalytics.
The SDK was shipped in old-fashioned way of adding our files + our other dependencies.
One of the dependencies is googleAnalytics lib, that the client's used later also for(by) GoogleTagManager (also non-pod import).
Now, we moved our SDK to be shipped as pod and all our dependencies (GoogleAnalytics libs i.e.) "moved" to the pod project with us, so the TagManger doesn't now include them (GoogleAnalytics looks missing in original project - "red" file).
Adding it also to the original project created a "duplicate files" linker error while the current state is raising linker error because tag manager doesn't have its GoogleAnalytics dependency.
What is the proper solution to this situation?
Why does it doesn't "know" the Google analytics lib from the pods target if the rest of the project do?

Related

How to resolve Swift Package Manager target overlapping sources error

I have a GitHub repo that is an Objective-C project that defines multiple targets (one per each targeted OS: macOS, iOS, tvOS, etc.). These targets share most of the source code files of the project.
I am trying to add SPM support to the project and in the Package.swift file I define matching targets with source path referring to the same folder containing those source code files shared across the targets.
When I add this SPM-"enabled" project/package to a test project that is trying to use it as a dependency via SPM, I get an error saying that the second target in the dependency package having overlapping sources with another target (the first one that uses the same shared source code files).
Any ideas about how to fix the problem? I would assume my multi-target configuration over the shared source code files is not that uniqueue...
I finally figured out what was the problem and what should be a solution to it.
My mistake was to think of SPM targets the same way Xcode thinks of them. In reality, SPM targets are essentially named folder containing source code files that need to be built to produce a product or products. They do not assume a definition of a recipe regarding how to build (the way Xcode targets do). However, a codebase that depends on a given SPM package does apply its Xcode targets to build itself and the dependency (prior to building its own codebase). The SPM targets are completely agnostic to the targeted device.
Hence, when I tried to map all my Xcode targets as similar SPM targets (at the same time referring to the same source code files from multiple SPM targets) it was wrong from the SPM point of view.
The correct solution anded up to be a definition of a single SPM target over a single codebase location (path) and everything went well from there.
Here is a good video that explains the SPM concepts well and that subsequently led me towards the working solution:
Creating Swift Packages

Module not found for framework dependency in Xcode

I have a project with multiple framework targets, that also have pods dependencies.
I have:
No circular dependencies between targets
Everything, including pods, is in Objective-C, no Swift at all.
use_frameworks! in Podfile, so all pods are frameworks, not libraries.
Here is my structure:
TUSystemKit depends on TUModels (which is a framework).
TUModels depends on Pods_TUModels (generated by pods).
Pods_TUModels depends on JSONModel
TUModels is automatically linked with its own pod framework (which contains JSONModel).
TUSystemKit has TUModels as target dependency.
TUSystemKit is linked with TUModels.
Visually, the dependencies are like this:
TUSystemKit ➔ TUModels ➔ Pods_TUModels ➔ JSONModel
When I select MyModels as the build target in Xcode, build succeeds. However, when I select TUSystemKit, the build fails, saying that module JSONModel is not found while building module TUSystemKit (TUUser in screenshot belongs to TUModels):
What am I doing wrong? Obviously I shouldn't be explicitly linking against all the frameworks in the dependency tree. Why does TUModels build perfectly but TUSystemKit errs on a module import inside a linked framework's code? Do I need to change something with pods?
After hours of refactoring, I've managed to build my project. I can't tell what exactly was wrong as it took me literally a day to organize all the dependencies and frameworks and it kept failing at a different point, more than a 100 times, but here are some observations to lead to a successful build:
All the public-facing classes are added as public headers to the target, and not to any other target.
All the code (.m files) are in Compile Sources section of the target, and not in any other target.
All the public facing classes' headers are included at umbrella header (a header with the exact same name with the framework)
The application embeds all the custom frameworks (not the pods).
All the files inside a framework target only #import required files within the same target or a file listed on any targets umbrella header that the framework has a dependency on.
Obvious, redundant, but worth noting again: no classes between frameworks should have circular dependencies (e.g. ClassA in FrameworkA depends on ClassB in FrameworkB, while some class in FrameworkB depends on some class on FrameworkA). I had some, and created delegates. Do whatever pattern fits your design: IoT/dependency injection, notifications/publisher-subscriber etc. But do it: separate the concerns clearly.
Try to avoid using same classes in multiple targets. Instead, have it in one target, and make the other target depend on the containing target, creating a dependency chain.
After refactoring many files and playing with project settings, I managed to build and run everything again. My previous setup had various number of combinations of the issues that I mentioned above, messing everything up. After cleaning all the bits and grouping code into functional, modular frameworks, I could build it.
If you came here due to the parse error -> module not found,
in certain occasions you may be forced to add the path manually.
This is...
go to your project at the top
select your project target
select build settings
search the parameter Framework Search Paths under the title Search Paths
add the one where yours is located. Example: (using cocoa pods) $(SRCROOT)/Pods
indicate/set it to be recursive (access to the option by double-clicking your previously added path)
The problem should have been resolved by the 3erd party lib with commands like install / update / build or similar but if it fails and you are stuck, this is an option in order to continue.
In the same tone, if you get an error from pods indicating that
The sandbox is not in sync with the Podfile because the builder is unable to find files like Podfile.lock, then you may consider to go in the same direction adding some user-defined settings:
select build settings
press the '+' symbol, "Add User-Defined Setting".
add this pair:
param= PODS_PODFILE_DIR_PATH value = ${SRCROOT}/.
param = PODS_ROOT value = ${SRCROOT}/Pods
Cheers

RestKit and CocoaLumberjack integrated as frameworks in Xcode7

I'm working on a project that uses both RestKit and CocoaLumberjack. The project also uses some other pods, some of them only exist in swift. I use cocoapods 0.38.2 for dependency management, my podfile looks like this (removed other pods for readability):
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
pod 'RestKit'
pod 'CocoaLumberjack'
I need to use use_frameworks! because of those other pods that are swift-only. I try to compile this using Xcode7 beta 5, I get the following errors:
"_OBJC_CLASS_$_DDLog", referenced from:
objc-class-ref in RKLumberjackLogger.o
ld: symbol(s) not found for architecture x86_64
So I took a look into the offending file and found this:
#if __has_include("DDLog.h")
#import "RKLumberjackLogger.h"
#import "DDLog.h"
Looks like the entire file resolves to nothing if the DDLog.h is not present, in which case I think the RestKit logging falls back to NSLog or whatever. Otherwise, the Lumberjack logging is used, which is what I want.
After some investigation, my suspicion is that the RestKit somehow sees the CocoaLumberjack headers (where the DDLog.h is), but is not properly linked against it when the project is built. Feel free to question this in case you have better ideas, but I can confirm that going to the CocoaLumberjack sources and manually adding DDLog.m as a member to the RestKit framwork target allows me to compile the project properly.
So, my question is, what is the correct way of fixing this? RestKit is not directly dependent on CocoaLumberjack, but tries to detect it and use it if possible, but fails miserably. Is there a way to link RestKit with Lumberjack from my project level so I don't have to modify the pods?
Example project can be found here
Your suspicion is correct.
RestKit somehow sees the CocoaLumberjack headers (where the DDLog.h is), but is not properly linked against it when the project is built
This is a problem with RestKit and everything that you would do within your own project would be a workaround. So arguably, there is no single correct way to fix this in your project.
I have filed a Pull Request with a fix for this issue.
Update:
The pull request has been merged, but at the time of writing this update, no new version of RestKit has been released yet.
pod "RestKit", :head, :subspecs => ['Core', 'CocoaLumberjack']
RestKit's Lumberjack logging functionality has been moved into a separate subspec that you have to specify if you want to use it.
:head will tell CocoaPods to use the current master instead of a released version.

How should the app project depend on libHello.a and libHello.a depend on libPods.a?

I tried to use cocoapods in an static library project iKit, and use iKit as a subproject in my main app project. When I build the main app project, an error is occur:
Look image here:
How should I struct the source and static library like that?
If I directly Use the cocoapods in main app project TestiKit, everything will be OK.
What I should do?
If iKit has dependencies that are served from CocoaPods, they are definitely not being linked when you include the project this way. You'd probably be best off creating a podspec for iKit and linking that within your main project. Then in this new podspec you could specify iKit's dependencies and everything would be linked correctly. The issue here is that since you're not including the Pods project created in the iKit workspaces that CocoaPods uses Pods.xcconfig can't link its dependencies.

Populating the configuration to the nested library project

I have a main project, which includes a nested library project which produces a libCore.a library.
Both of the projects have the two configurations debug and release. Now if I build the main project with a given configuration, how can I make sure that this is passed down to the library project as well?
Make your project directly dependent on the libCore project. Do achieve this, do the following:
Drag the libCore project file to your main project. It happens sometimes, that only the xcodeproj file is moved. If this happens to you, restart XCode (this happend to me with RestKit and the latest XCode).
After point 1 is done and you can browse the dependency project, go to your target build phases and add the libCore as the target dependencies.
Link against libCore.a by adding in the Link Binary with Libraries phase.
These are 3 basic steps, I don't know what the libCore is, if it needs to be linked with any other libraries then you will also have to link your target against those libraries.