Short answer
Is is not supported as of CocoaPods 1.10.2. There are reasons why it isn't supported and probably won't be supported any time soon or only when building with Xcode 13.
Long answer
When integrating a pod to a target, CocoaPods (CP) must perform a couple of steps to make that happen. I won't list all of them here but the following four are relevant to this answer:
- Create an umbrella header.
- Build a (dynamic/static) framework or static library.
- Adding the umbrella header to the header search path of the target.
- Liking the built framework/library to the target.
Let me go through these steps one by one:
1. Create an umbrella header
The content of the umbrella header depends on the platform the pod is built for. E.g. if it is macOS, it will import Cocoa
, if it is iOS, it will import UIKit
. As umbrella headers are treated in a special way, especially when using modules (and when dealing with Swift code as well, you do want to use modules, trust me), using #ifdef
to make parts of them platform dependent is a rather bad idea. So to support multiple platforms, CP would need to create one umbrella header per platform.
Please note that this is exactly what CP does, if you integrate the same pod into two targets for two different platforms. E.g. if one target is macOS and one is iOS, there will be two umbrella headers, one ending in -macOS.h
and one ending in -iOS.h
. So in theory, this functionality is there, there is just no way to specify more than one platform per target so far and thus the created umbrella header will only work with one target platform. That is what Vikas Dadheech probably meant when he said:
And if I just specify platform as only iOS or Mac
then the project in question fails to build on other platform.
Currently the created header will only play nice with either platform. Please note that this also holds true for any auto-generated module map file (.modulemap
).
2. Build a (dynamic/static) framework or static library
Just as before, how the library/framework is built depends on the platform as a Podspec file can specify different build options per platform and even select different files to be included in a build depending on platform, the pod must be built separately per platform, even if both platforms would use the same CPU instruction set (e.g. ARM Mac and ARM iPad) and the code otherwise contains nothing that is platform specific.
And just as before, this functionality is there when integrating the same pod in into different targets for different platforms, resulting in two libraries/frameworks with a platform suffix.
3. Adding the umbrella header to the header search path of the target
Now its getting a bit more tricky. Assuming we have two umbrella headers (and maybe also two module map files), only one of them must be visible when building the target they integrate into and which one depends the target platform. This is no problem when we are talking about different targets as different build settings per target are easy but in that case it's a single target and this comes with some implications.
Yet even that is solvable, e.g. by making settings depend on SDK, after all you will require a different SDK per platform, so you can do things like this:
HEADER_SEARCH_PATHS[sdk=macosx*] = ....
HEADER_SEARCH_PATHS[sdk=iphoneos*] = ...
to ensure that only the headers and map files for the correct platform are visible for the build.
4. Liking the built framework/library to the target
And here comes the problem: If you want to use Xcode's linking, you can either link against the macOS or the iOS version you've built in step 2 but you cannot link to either one depending on the target platform you are building for. So how do you make sure the binary links against the correct library and only one of them?
You can ...
combine all versions into a universal binary and always link against this one. This will work as long as your target platforms have different CPU architectures (e.g. x86 for Mac and ARM for iOS) but it won't work if your platforms have equal ones (e.g. ARM Mac and ARM iPhone). With the instruction of ARM Macs, this option is pretty much dead and it was already not possible before when your two targets are iOS and tvOS since both have been ARM, too.
not use Xcode's linking at all and instead set linking flags by hand as well as library search paths using the same trick as for the headers above. Well, this will only work with static libraries and frameworks out of the box and only reliably with the new Xcode build system if you manually set target dependencies. With dynamic frameworks you also manually must copy the frameworks, sometimes (re-)sign them correctly, and also manage dependencies by hand. All possible, but seems rather fragile and may have even more implications than I just named above. I guess this is a somewhat risky approach with lots of possible pitfalls and some setups will simply not work that way at all, no matter what you do.
use the selective linking feature of Xcode 13. This is exactly what is needed here and Apple has probably implemented it as the CPU architecture no longer is suitable for many linking cases. Yet Xcode 13 is currently still in beta and if the feature relies upon that capability, it will require using Xcode 13 for building and this requires a Mac running at least Big Sur.